在页面加载时停止gif动画,在鼠标悬停时开始播放

57

我有一个页面里有很多的GIF动画。

<img src="gif/1303552574110.1.gif" alt="" >
<img src="gif/1302919192204.gif" alt="" >
<img src="gif/1303642234740.gif" alt="" >
<img src="gif/1303822879528.gif" alt="" >
<img src="gif/1303825584512.gif" alt="" >

我想要的

1 在页面加载时 => 所有gif的动画都停止

2 鼠标悬停时 => 该gif的动画开始

3 鼠标移开时 => 该gif的动画再次停止

我想这可以用jQuery实现,但我不知道怎么做。


14个回答

67

不能控制图像的动画。

你需要两个版本的每个图像,一个是动画的,另一个不是动画的。在悬停时,可以轻松地从一个图像切换到另一个图像。

示例:

$(function(){
  $('img').each(function(e){
    var src = $(e).attr('src');
    $(e).hover(function(){
      $(this).attr('src', src.replace('.gif', '_anim.gif'));
    }, function(){
      $(this).attr('src', src);
    });
  });
});

更新:

时间过去了,可能性也随之改变。正如kritzikatzi所指出的那样,拥有两个版本的图像并不是唯一的选择,你可以使用canvas元素来创建动画的第一帧的副本。请注意,这在所有浏览器中都不起作用, 例如,IE 8不支持canvas元素。


5
这个答案现在只有部分正确。现在你可以使用canvas标签从gif的第一帧创建一个静止图像(这就是freezeframe插件的做法)。显然,拥有两个版本有可能会为您节省大量带宽,只是说这不是唯一的选择。 - kritzikratzi
5
请注意,画布技巧仅适用于与页面本身相同域的图像。从其他地方加载的图像无法被画布捕获。 - peterflynn
4
为什么会有负评?如果您不解释哪些地方有问题,那么回答就无法得到改进。 - Guffa
1
因为这是一个好的解决方案,而且你继续更新它,尽管有人因为一个简单的三年前的答案而对你进行了投票,但我还是给你点赞了。谢谢,这很有帮助。 - ReganPerkins
1
@TheDembinski:是的,在某些情况下,这将是更好的解决方案,这完全取决于您有多少图像以及您愿意预加载多少数据。如果您在悬停时切换元素,甚至可以仅使用CSS完成它。 - Guffa
显示剩余5条评论

21

我知道这个答案有些晚,但是我发现了一个相当简单、优雅且有效的解决方法,并觉得有必要在这里发布。

然而,需要明确一点的是,这并不能在鼠标悬停时启动gif动画,在鼠标移出时暂停它,并在再次悬停时继续它。不幸的是,这是不可能实现的。(可以使用一系列按顺序显示的图像来模拟gif的效果,但是拆分gif的每一帧并将所有那些url复制到脚本中会很耗时)

我的解决方案是让图像在鼠标悬停时看起来像开始移动。您可以将gif的第一帧制作成一个图像,并将该图像放在网页上,然后在鼠标悬停时用gif替换该图像,看起来就像它开始移动了。鼠标移出时重置为初始状态。

只需将此脚本插入HTML头部即可:

$(document).ready(function()
{
    $("#imgAnimate").hover(
        function()
        {
            $(this).attr("src", "GIF URL HERE");
        },
        function()
        {
            $(this).attr("src", "STATIC IMAGE URL HERE");
        });
});
将此代码放在您想要动画的图像的img标记中。
id="imgAnimate"

这将在鼠标悬停时加载gif,因此您的图像似乎开始移动。(这比在加载时加载gif更好,因为静态图像到gif的转换会出现不连贯,因为gif将从随机帧开始)

对于多个图像,只需创建一个函数:

<script type="text/javascript">

var staticGifSuffix = "-static.gif";
var gifSuffix = ".gif";

$(document).ready(function() {

  $(".img-animate").each(function () {

     $(this).hover(
        function()
        {
            var originalSrc = $(this).attr("src");
            $(this).attr("src", originalSrc.replace(staticGifSuffix, gifSuffix));
        },
        function()
        {
            var originalSrc = $(this).attr("src");
            $(this).attr("src", originalSrc.replace(gifSuffix, staticGifSuffix));  
        }
     );

  });

});
</script>

</head>
<body>

<img class="img-animate" src="example-static.gif" >
<img class="img-animate" src="example-static.gif" >
<img class="img-animate" src="example-static.gif" >
<img class="img-animate" src="example-static.gif" >
<img class="img-animate" src="example-static.gif" >

</body>

根据你提供的信息,该代码块是一个功能完整的网页,它将显示静态图像,并在悬停时加载并显示 gif 动画。您只需要插入静态图像的 URL 即可。


1
这对我来说很有效。其他的解决方案对我不起作用。 - Paul
谢谢,我尽力了 =p 我更新了这个答案,加入了第一次遗漏的很多内容。(还修复了一个错误,在我的脚本版本中忘记更改一个ID的名称) - Mark Kramer
不,谢谢!这是我实现这种技术的地方:http://new.syntheticmedia.net 将鼠标悬停在徽标和导航菜单项上。 - Paul
那是非常糟糕的代码。你不应该只是复制粘贴代码;相反,应该搜索DOM中的图像:$("img").each(function () { $(this).hover(function () { ... }) });并使用命名约定。 - Honest Objections

8
我认为jQuery插件freezeframe.js可能对您有用。 freezeframe.js是一个jQuery插件,可自动暂停GIF并在鼠标悬停时重新开始动画。
我猜您可以轻松地将其调整为在页面加载时运行。

这个解决方案可能更加健壮,它使用画布元素来完成部分工作,但是它会给OP提出的基本要求增加很多开销。 - Mike Kormendy
很不幸,这里链接和@tabacitu的链接似乎都已经失效了。看起来插件可以在GitHub上找到:https://github.com/chrisantonellis/freezeframe.js - indextwo

5
最好的选择可能是使用静态图片,在想要停止时替换gif动画。
    <img src="gif/1303552574110.1.gif" alt="" class="anim" >
    <img src="gif/1302919192204.gif" alt="" class="anim" >
    <img src="gif/1303642234740.gif" alt="" class="anim" >
    <img src="gif/1303822879528.gif" alt="" class="anim" >
    <img src="gif/1303825584512.gif" alt="" class="anim" >

    $(window).load(function() {
      $(".anim").src("stillimage.gif");
    });

    $(".anim").mouseover(function {
      $(this).src("animatedimage.gif");
    });

    $(".anim").mouseout(function {
      $(this).src("stillimage.gif");
    });

您可能希望有两个包含静态和动态GIF路径的数组,可以将它们分配给每个图像。


3

在这里找到了一个有效的解决方案: https://codepen.io/hoanghals/pen/dZrWLZ

JavaScript代码如下:

var gifElements = document.querySelectorAll('img.gif');

for(var e in gifElements) {

var element = gifElements[e];

if(element.nodeName == 'IMG') {

    var supergif = new SuperGif({
        gif: element,
        progressbar_height: 0,
        auto_play: false,
    });

    var controlElement = document.createElement("div");
    controlElement.className = "gifcontrol loading g"+e;

    supergif.load((function(controlElement) {
        controlElement.className = "gifcontrol paused";
        var playing = false;
        controlElement.addEventListener("click", function(){
            if(playing) {
                this.pause();
                playing = false;
                controlElement.className = "gifcontrol paused";
            } else {
                this.play();
                playing = true;
                controlElement.className = "gifcontrol playing";
            }
        }.bind(this, controlElement));

    }.bind(supergif))(controlElement));

    var canvas = supergif.get_canvas();     
    controlElement.style.width = canvas.width+"px";
    controlElement.style.height = canvas.height+"px";
controlElement.style.left = canvas.offsetLeft+"px";
    var containerElement = canvas.parentNode;
    containerElement.appendChild(controlElement);

 }
}

这个很好用,谢谢!但是你漏掉了一件事。需要使用库 buzzfeed / libgif-js。请看下面,我放了一个完整的答案,而不仅仅是 JavaScript。 - Phil van Kleur

3
纯JS实现https://jsfiddle.net/clayrabbit/k2ow48cy/(基于https://codepen.io/hoanghals/pen/dZrWLZ的canvas解决方案)

[].forEach.call(document.querySelectorAll('.myimg'), function(elem) {
    var img = new Image();
    img.onload = function(event) {
    elem.previousElementSibling.getContext('2d').drawImage(img, 0, 0);
    };
  img.src = elem.getAttribute('data-src');
  
    elem.onmouseover = function(event) {
        event.target.src = event.target.getAttribute('data-src');
    };
    elem.onmouseout = function(event) {
        event.target.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=";
    };
});
.mydiv{
  width: 320px;
  height: 240px;
  position: relative;
}
.mycanvas, .myimg {
  width: 100%;
  height: 100%;
  position: absolute;
}
<div class="mydiv">
<canvas class="mycanvas" width=320 height=240></canvas>
<img class="myimg" data-src="https://media.giphy.com/media/Byana3FscAMGQ/giphy.gif">
</div>


2
这个答案是在Sourabh的基础上建立的,他指出了一个HTML/CSS/JavaScript组合,可以在https://codepen.io/hoanghals/pen/dZrWLZ找到。我尝试了一下,并制作了一个包括CSS和JavaScript的完整网页,在我的网站上进行了测试。由于CodePens经常会消失,所以我决定在这里展示它。我还展示了一个简化的、剥离到必要元素的版本,以演示需要做的最少工作。
我还必须注意一件事。上面链接中的代码,Sourabh复制的JavaScript引用了一个JavaScript构造函数SuperGif()。我不认为Sourabh解释过这个,CodePen也没有。一个简单的搜索显示,它在buzzfeed/libgif-js中定义,可以从https://github.com/buzzfeed/libgif-js#readme下载。找到下面红色箭头指向的控件,然后点击绿色的“Code”按钮。(注:你看不到红色箭头:那是我告诉你在哪里查找。)

Screenshot of GitHub page for buzzfeed/libgif-js

一个菜单将弹出,提供各种选项,包括下载一个zip文件。下载它,并将其解压缩到您的HTML目录或其子目录中。

接下来,我将展示我制作的两个页面。第一个是从CodePen派生的。第二个则脱离了其基本要素,并显示了使用SuperGif所需的最小限度。

这是第一页的完整HTML、CSS和JavaScript代码。在HTML的head部分有一个链接到libgif.js,这是您从zip文件中需要的文件。然后,HTML的body部分以一些关于猫图片的文本开头,并跟随一个动画猫GIF的链接https://media.giphy.com/media/Byana3FscAMGQ/giphy.gif

然后继续一些CSS。CodePen使用SCSS,对于任何不知道的人来说,SCSS必须被预处理为CSS。我已经做到了,因此下面的代码是真正的CSS。

最后,就是JavaScript了。

<html>
<head>
<script src="libgif-js-master/libgif.js"></script> 
</head>

<body>

<div style="width: 600px; margin: auto; text-align: center; font-family: arial">
  <p>
And so, the unwritten law of the internet, that any 
experiment involving video/images must involve cats in 
one way or another, reared its head again. When would 
the internet's fascination with cats come to an end? 
Never. The answer is "Never".
</p> 
  <img src='https://media.giphy.com/media/Byana3FscAMGQ/giphy.gif' class='gif' />
</div>

<style>
img.gif {
  visibility: hidden;
}

.jsgif {
  position: relative;
}

.gifcontrol {
  position: absolute;
  top: 0px;
  left: 0px;
  width: 100%;
  height: 100%;
  cursor: pointer;
  transition: background 0.25s ease-in-out;
  z-index: 100;
}
.gifcontrol:after {
  transition: background 0.25s ease-in-out;
  position: absolute;
  content: "";
  display: block;
  left: calc(50% - 25px);
  top: calc(50% - 25px);
}
.gifcontrol.loading {
  background: rgba(255, 255, 255, 0.75);
}
.gifcontrol.loading:after {
  background: #FF9900;
  width: 50px;
  height: 50px;
  border-radius: 50px;
}
.gifcontrol.playing {
  /* Only show the 'stop' button on hover */
}
.gifcontrol.playing:after {
  opacity: 0;
  transition: opacity 0.25s ease-in-out;
  border-left: 20px solid #FF9900;
  border-right: 20px solid #FF9900;
  width: 50px;
  height: 50px;
  box-sizing: border-box;
}
.gifcontrol.playing:hover:after {
  opacity: 1;
}
.gifcontrol.paused {
  background: rgba(255, 255, 255, 0.5);
}
.gifcontrol.paused:after {
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 25px 0 25px 50px;
  border-color: transparent transparent transparent #ff9900;
}
</style>

<script>
var gifElements = document.querySelectorAll('img.gif');

for(var e in gifElements) {
  
    var element = gifElements[e];
    
    if(element.nodeName == 'IMG') {
    
        var supergif = new SuperGif({
            gif: element,
            progressbar_height: 0,
            auto_play: false,
        });

        var controlElement = document.createElement("div");
        controlElement.className = "gifcontrol loading g"+e;

        supergif.load((function(controlElement) {
            controlElement.className = "gifcontrol paused";
            var playing = false;
            controlElement.addEventListener("click", function(){
                if(playing) {
                    this.pause();
                    playing = false;
                    controlElement.className = "gifcontrol paused";
                } else {
                    this.play();
                    playing = true;
                    controlElement.className = "gifcontrol playing";
                }
            }.bind(this, controlElement));
        
        }.bind(supergif))(controlElement));
    
        var canvas = supergif.get_canvas();     
        controlElement.style.width = canvas.width+"px";
        controlElement.style.height = canvas.height+"px";
    controlElement.style.left = canvas.offsetLeft+"px";
        var containerElement = canvas.parentNode;
        containerElement.appendChild(controlElement);
    
  }
}
</script>

</body>
</html>

当我将页面放在我的网站上并显示时,顶部看起来是这样的:

Web page with paused animated GIF of cat

当我按下粉色按钮时,页面就会变成这个样子,并且GIF开始动画。(猫舔着从水龙头滴落的水。)

Web page with running animated GIF of cat

结束时,这是第二个简单的页面。与第一个不同,它没有花哨的播放/暂停控件来改变形状:它只有两个按钮。代码唯一不必要的功能是禁用不相关的按钮,并在按钮之间插入一些空格。
<html>

<head>
<script src="libgif-js-master/libgif.js"></script>
</head>

<body>

<button type="button" onclick="play()"
        id="play_button"
        style="margin-right:9px;"
>
Play
</button>
      
<button type="button" onclick="pause()"
        id="pause_button"
>
Pause
</button>

<img src="https://media.giphy.com/media/Byana3FscAMGQ/giphy.gif" 
     id="gif" 
/>

<script>
var gif_element = document.getElementById( "gif" );
    
var supergif = new SuperGif( {
             gif: gif_element,
                          progressbar_height: 0,
                          auto_play: false
               } );

supergif.load();

function play()
{
  var play_button = document.getElementById( "play_button" );
  play_button.disabled = true;

  var pause_button = document.getElementById( "pause_button" );
  pause_button.disabled = false;
 
  supergif.play();
}

function pause()
{
  var play_button = document.getElementById( "play_button" );
  play_button.disabled = false;

  var pause_button = document.getElementById( "pause_button" );
  pause_button.disabled = true;

  supergif.pause();
}

pause_button.disabled = true;
</script>

</body>
</html>

这个加上libgif-js中的example.html文件,应该足以让任何人入门。

1
您可以通过使用类似于电影带的步骤来展示长条,从而解决此问题。然后,您可以在任何一帧上停止电影。 以下是示例(fiddle 可在 http://jsfiddle.net/HPXq4/9/ 上找到):
标记:
 <div class="thumbnail-wrapper">
     <img src="blah.jpg">
 </div>

样式表:

.thumbnail-wrapper{
   width:190px;
   height:100px;
   overflow:hidden;
   position:absolute;
}
.thumbnail-wrapper img{
   position:relative;
   top:0;
}

这是JS代码:

var gifTimer;
var currentGifId=null;
var step = 100; //height of a thumbnail
$('.thumbnail-wrapper img').hover(
   function(){
      currentGifId = $(this)
      gifTimer = setInterval(playGif,500);
   },
   function(){
       clearInterval(gifTimer);
       currentGifId=null;
   }
);

var playGif = function(){
   var top = parseInt(currentGifId.css('top'))-step;
   var max = currentGifId.height();
   console.log(top,max)
   if(max+top<=0){
     console.log('reset')
     top=0;
   }
   currentGifId.css('top',top);
}

显然,这可以进一步优化,但我为了易读性简化了这个例子。


1
"马克·克莱默的更加优雅的版本是按照以下步骤进行:"

function animateImg(id, gifSrc){
  var $el = $(id),
    staticSrc = $el.attr('src');
  $el.hover(
    function(){
      $(this).attr("src", gifSrc);
    },
    function(){
      $(this).attr("src", staticSrc);
    });
}

$(document).ready(function(){
  animateImg('#id1', 'gif/gif1.gif');
  animateImg('#id2', 'gif/gif2.gif');
});

甚至更好的方法是使用数据属性:

或者更好的方法是使用数据属性:

$(document).ready(function(){
  $('.animated-img').each(function(){
    var $el = $(this),
      staticSrc = $el.attr('src'),
      gifSrc = $el.data('gifSrc');
    $el.hover(
      function(){
        $(this).attr("src", gifSrc);
      },
      function(){
        $(this).attr("src", staticSrc);
      });
  });
});

而img元素可能看起来像这样:

<img class="animated-img" src=".../img.jpg" data-gif-src=".../gif.gif" />

注意:此代码未经测试,但应该可以正常工作。

1

要重新启动 gif 图像的动画,您可以使用以下代码:

$('#img_gif').attr('src','file.gif?' + Math.random());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接