5

<img>我在一个 HTML 页面上有很多标签,其中一些共享相同的动画 GIF 文件。URL 是由 JavaScript 动态设置的src,但使用我的代码,相同的字符要么再次播放,要么在最后一帧立即显示后续字符。

想法:这是一个艺术项目。输入一些文本后,字符以特殊字体显示,并且每个字符(一个接一个)完成一些转换,我只能通过使用动画 GIF 来实现。文本被拆分为单个字符,<img>标签创建如下:

<!-- delivered HTML at page load -->
<img src="initial/f.png"> <!-- I used to PNG here to outline -->
<img src="initial/o.png"> <!-- the animation is NOT set a first -->
<img src="initial/o.png">

当动画开始时,第一个<img>的 URL 设置为transition/f.gif. 只有在它完成播放(由时间确定)后,才会设置第二张图像,等等。

<!-- while 2nd animation is running -->
<img src="transition/f.gif"> <!-- already finished, displays last frame -->
<img src="transition/o.gif"> <!-- being animated right now -->
<img src="transition/o.png"> <!-- will be reset to o.gif in next step -->

我无法解决的问题:o.gif播放完示例后,下一个 O 的动画无法正常工作。

我尝试为每个角色定义一个类并将图像分配为background-image. 一旦任何出现的字符播放了任何后续出现的相同字母,就会在显示时立即显示该 GIF 的最后一帧(结束状态)。

我也尝试src直接使用 JavaScript 设置属性,但是当第二个字母 O 像这样设置时,第一个字母 O 的动画会同步重新启动。但它应该停留在最后一帧。

由于 HTML 页面也应该在本地文件系统上运行,我认为o.gif?random=argument绕过缓存机制的参数不起作用或不会产生任何影响(可能在某些计算机上,我自己的测试不会伪造)。

4

2 回答 2

2

您必须为图像创建唯一的 url,因此浏览器将始终重新加载字母而不是使用缓存的字母。例如,您可以使用一个小型 php 来实现这一点,它为参数输出正确的 gif。

<img src="gif_printer.php?letter=o&t=1234567">

t 参数应该是创建 img 标签时的时间戳。这为重新下载提供了足够的差异。

在 php 中设置标题以限制/禁用缓存和输出类型为 gif,然后简单地将图像的内容倒入标准输出。

时间戳参数和缓存控制标头应该足以让浏览器重新下载 evert letter。

如果您的测试环境反应不正确,您可以尝试 htaccess 解决方案,但为此您必须使用 Web 服务器(这对于之前的解决方案来说已经足够了)。

这意味着将所有指向 images/[az].gif 的 url 重写为 images/[az].gif,因此只需删除除第一个字母和扩展名之外的其他噪音。

于 2013-05-20T15:03:29.537 回答
2

考虑不使用 GIF,而是使用图像序列和 Javascript。我已经将一个粗略的可实例化 Javascript 对象组合在一起,它就是这样做的:

<html>
    <head>
        <script>
            function Animator(target, frames, delay)
            {
                var _this = this;
                // array of frames (image objects)
                var f = [];
                // a reference to the object where our frames will appear
                var t = document.getElementById(target);
                // the interval variable.  Used to stop and start
                var t_loop;
                // create a new image element and remember it
                var img_el = document.createElement("img");
                // current frame
                var c_frame = 0;

                t.innerHTML = "";
                t.appendChild(img_el);

                var i, img;

                // preload immediately
                for(i = 0; i < frames.length; i++)
                {
                    img = new Image();
                    img.src = frames[i];
                    f.push(img);
                }

                this.play = function()
                {
                    t_loop = window.setInterval(_this.frame, delay);
                }

                this.stop = function()
                {
                    clearInterval(t_loop);
                }

                this.gotoFrame = function(frame)
                {
                    c_frame = frame;
                    _this.frame();
                }

                this.frame = function()
                {
                    img_el.src = f[c_frame].src;

                    c_frame++;

                    if(c_frame >= f.length)
                    {
                        c_frame = 0;
                    }
                }
            }

            function loaded()
            {
                var quip_frames = [
                    "http://www.abcteach.com/images/abma_thumb.gif",
                    "http://www.abcteach.com/images/abcu_thumb.gif",
                    "http://www.abcteach.com/images/zbma_thumb.gif",
                    "http://www.abcteach.com/images/zbcu_thumb.gif",
                    "http://www.abcteach.com/images/dnma_thumb.gif",
                    "http://www.abcteach.com/images/dncu_thumb.gif"
                ];

                var anim1 = new Animator("target1", quip_frames, 100);

                var anim2 = new Animator("target2", quip_frames, 100);

                var anim3 = new Animator("target3", quip_frames, 100);

                anim1.play();
                window.setTimeout(anim2.play, 200);
                window.setTimeout(anim3.play, 300);
            }
        </script>
    </head>
    <body onload="loaded()">
        <div id="target1">
        </div>
        <div id="target2">
        </div>
        <div id="target3">
        </div>
    </body>
</html>

感谢ABCTeach的图片

该对象循环加载图像,将它们存储在一个数组中,然后通过简单地使用setInterval()以所需速率交换帧。当页面加载时,它会生成三个这样的对象,每个都指向不同的 DIV,但每个都有相同的框架。然后它告诉每个播放器使用不同的延迟(第一个立即播放,第二个在 200 毫秒后,第三个在 300 毫秒后)。在您的情况下,您将为您使用的每个字母创建一个数组:

var A = [*array of URLs to images of the letter A*];
var B = [*array of URLs to images of the letter B*];    
...

Animator然后为页面上的每个 div创建一个新对象,并将其发送到适当的字母数组:

var letter_so_and_so = new Animator("div_so_and_so", A, 100);
var letter_this_and_that = new Animator("div_this_and_that", B, 100);
var another_letter = new Animator("another_div", B, 100);

最后给每个人一个偏移开始,或者调用他们的Animator.gotoFrame(f)方法在不同的帧上开始(不要忘记Animator.play()!)。

JSFiddle

尝试在你的代码中采用这样的东西,我想你会发现它会产生奇迹。

于 2013-05-20T21:02:38.300 回答