【问题标题】:Gifs, Javascript and Multiple InstancesGifs、Javascript 和多实例
【发布时间】:2012-02-18 07:25:06
【问题描述】:

也许是一个愚蠢的问题,但无论如何。

示例:假设我有一个非循环动画 GIF,我有两个 img 元素。

<img src="" id="slot1" />
<img src="" id="slot2" />

所以我用一点javascript来改变slot1的来源。

function changE(x)
{var image=document.getElementById (x);
 image.src="animated.gif";
}

someButtonGotClicked=changE('slot1'); 

效果很好。 Gif 从头到尾播放,但如果我将 slot2 的 src 更改为相同的 gif:

changE('slot2');  

slot1 将它的 gif 重置回起点,以便与 slot2 开始它的 gif 同步。

现在我知道我可以复制 gif 并使用 2 个单独的文件,并且我知道精灵表,但我很好奇我是否可以使用 gif 的一个副本并在一个页面上多次使用它而不每次另一个 img 元素收到与其 src 相同的文件时,所有 gif 实例都会重新启动?

希望这不会令人困惑。谢谢。

【问题讨论】:

  • 您在哪些浏览器上观察到这种行为?
  • 我假设您也不想在添加新 gif 之前简单地删除第一个 gif?
  • 您是否尝试通过images-collection 访问img-element? function changE(x) {var image=document.images[x]; image.src="animated.gif"; }
  • @maerics 据我所知所有这些
  • @Teemu 没有区别,但 Ingenu 的回答似乎有效(见下文)

标签: javascript gif


【解决方案1】:

一旦图像被加载到内存中,所有其他使用相同 URL 请求该图像的对象都会从浏览器缓存中获取对该图像的引用。这避免了多次加载相同的图像。在 gif 的情况下,要跟踪的元数据之一是当前帧,它不是存储在 &lt;img&gt; dom 元素中,而是存储在用于存储该 gif 的结构中的浏览器级别。

加载时,该帧索引被重置。因此,当浏览器处理 gif 循环时,第二个图像加载会将当前帧索引设置为开头,因此两个图像同步。

这是一个浏览器实现,似乎大多数浏览器都遵循这个实现。这样做的一个好处是,如果您在一页中有数千个小 gif(来自同一个 URL),浏览器将执行更少的计算来呈现它们,因为它只会更改一帧索引,而不是数千个。

编辑: 要修复您的代码,您基本上必须在图像末尾添加一些随机的东西。

function changE(x)
{var image=document.getElementById (x);
 image.src="animated.gif?" + Math.random();
}

所以浏览器认为这是一个不同的图像(即不同的 URL)。

【讨论】:

  • 将查询字符串附加到图像 url 对此有影响吗?
  • 是的,这是一种解决方法,因为它被视为不同的 URL。
  • 这很聪明。它有什么缺点吗?
  • @Nikki 是的,带宽/加载时间,因为浏览器将加载相同的图像两次。
  • @Ingenu 所以你的解决方案中浏览器使用的资源与实际为 slot2 制作另一个 gif 副本基本相同?
【解决方案2】:

尝试使用这样的解决方案:

<img src="" id="slot1" class="animate" />
<img src="" id="slot2" class="animate" />


(function(doc, w) {
    var changE, getElementsByClassName;

    changE = function(img) {
        img.src = "animated.gif";
    };
    getElementsByClassName = function(node, classname) {
        if (node.getElementsByClassName) { // use native implementation if available
            return node.getElementsByClassName(classname);
        } else {
            return (function getElementsByClass(searchClass, node) {
                if (node == null)
                    node = doc;
                var classElements = [],
                    els = node.getElementsByTagName("*"),
                    elsLen = els.length,
                    pattern = new RegExp("(^|\\s)" + searchClass + "(\\s|$)"), i, j;

                for (i = 0, j = 0; i < elsLen; i++) {
                    if (pattern.test(els[i].className)) {
                        classElements[j] = els[i];
                        j++;
                    }
                }
                return classElements;
            })(classname, node);
        }
    };
    w.onload = function() {
        var imgs, i = 0, l;
        imgs = getElementsByClassName(doc, 'animate');
        l = imgs.length;
        for (i; i < l; i++) {
            imgs[i].onclick = function(e) { changE(this); };
        }
    };
})(document, window);

这将为每个名称为animate的图像设置一个clicke事件,并且click事件只会影响点击的特定图像。

【讨论】:

  • 当我有更多时间时,我一定会尝试理解你的解决方案:P
  • 如果您有任何问题,请给我留言。大部分代码只是按类名选择图像。如果可以的话,我建议您查看 jQuery,它将把上面的所有代码变成这样:$(.animate).click(function(e) { changE(this); });jquery.com
猜你喜欢
  • 1970-01-01
  • 2011-08-18
  • 2014-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-11
  • 2014-08-18
  • 1970-01-01
相关资源
最近更新 更多