停止加载 gif 动画,鼠标悬停开始激活

Posted

技术标签:

【中文标题】停止加载 gif 动画,鼠标悬停开始激活【英文标题】:Stop a gif animation onload, on mouseover start the activation 【发布时间】:2011-08-14 15:37:03 【问题描述】:

我有一个包含很多 GIF 的页面。

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

我在寻找什么

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

2 在鼠标悬停时 => 动画为那个 gif 启动

3 On mouseout => 该 gif 动画再次停止

我想这可以在 Jquery 中完成,但我不知道如何。

【问题讨论】:

javascript to control image animation?的可能重复 【参考方案1】:

不,您无法控制图像的动画。

您需要每个图像的两个版本,一个是动画的,一个不是。悬停时,您可以轻松地从一张图像更改为另一张图像。

例子:

$(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 指出的那样,拥有两个版本的图像并不是唯一的选择,您显然可以使用画布元素来创建动画第一帧的副本。请注意,这并不适用于所有浏览器,例如 IE 8 不支持 canvas 元素。

【讨论】:

这个答案只是部分正确。现在您可以使用 canvas 标签从 gif 的第一帧创建静止图像(freezeframe 插件就是这样做的)。显然有两个版本可能会为您节省大量带宽,只是说这不是唯一的选择。 @kritzikratzi:请注意,画布技巧仅适用于与页面本身来自同一域的图像。 Canvas 无法捕获从其他地方加载的图像。 为什么投反对票?如果你不解释你认为错的地方是什么,它就无法改进答案。 赞成,因为这是一个很好的解决方案,尽管人们拒绝投票给你一个只有 3 年历史的答案,但你仍然继续更新它,一开始就没有错。谢谢,这有帮助。 @TheDembinski:是的,在某些情况下这将是一个更好的解决方案,这完全取决于您拥有多少图像以及您愿意预加载多少数据。如果你在悬停时切换元素,你甚至可以只使用 CSS。【参考方案2】:

最好的选择可能是有一个静止图像,当你想停止它时,你用它替换 gif。

    <img src="gif/1303552574110.1.gif"  class="anim" >
    <img src="gif/1302919192204.gif"  class="anim" >
    <img src="gif/1303642234740.gif"  class="anim" >
    <img src="gif/1303822879528.gif"  class="anim" >
    <img src="gif/1303825584512.gif"  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】:

据我所知,只有一种方法。

有 2 张图片,首先是带有 gif 第一帧(或任何您想要的)的 jpeg 和实际 gif。

用 jpeg 加载页面并在鼠标悬停时将 jpeg 替换为 gif。您可以根据需要预加载 gif,或者如果它们是大尺寸的,则在加载 gif 时显示加载,然后用它替换 jpeg。

如果你想让它变成双线性的,比如在鼠标悬停时播放 gif,在鼠标移出时停止它,然后从你停止的帧恢复播放,那么这不能用 javascript+gif 组合来完成。

【讨论】:

【参考方案4】:

我意识到这个答案已经晚了,但是我找到了一个相当简单、优雅和有效的解决这个问题的方法,觉得有必要把它贴在这里。

但是我觉得我需要明确的一件事是,这不会在鼠标悬停时启动 gif 动画,在鼠标悬停时暂停它,并在您再次将鼠标悬停时继续它。不幸的是,这对于 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 onload 更好,因为从静态图像到 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。您所要做的就是插入静态图片的网址。

【讨论】:

这对我很有效。其他解决方案对我不起作用。 谢谢,我试试 =p 我用很多我第一次错过的东西更新了这个答案。 (还修复了一个错误,即我忘记更改脚本版本中的 ID 名称) 不,谢谢!这是我实施这项技术的地方:new.syntheticmedia.net 将鼠标悬停在徽标和导航菜单项上。 那绝对是糟糕的代码。你永远不应该像那样复制代码;而是在 DOM 中搜索图像:$("img").each(function () $(this).hover(function () ... ) ); 并使用命名约定【参考方案5】:

您可以通过逐步显示长条来解决此问题,例如幻灯片。然后你可以在任何帧上停止电影。 下面的示例(小提琴可在http://jsfiddle.net/HPXq4/9/ 获得):

标记:

 <div class="thumbnail-wrapper">
     <img src="blah.jpg">
 </div>

CSS:

.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);

显然,这可以进一步优化,但为了便于阅读,我简化了这个示例

【讨论】:

【参考方案6】:

我认为jQuery plugin freezeframe.js 可能会为您派上用场。 freezeframe.js 是一个 jQuery 插件,用于在鼠标悬停时自动暂停 GIF 并重新启动动画。

我想您可以轻松地对其进行调整以使其在页面加载时工作。

【讨论】:

这个解决方案可能更健壮,它在部分工作中使用了画布元素,但它为 OP 提出的总体基本要求增加了很多开销。 不幸的是,这里的链接和@tabacitu 的链接似乎都不再起作用了。看起来该插件在 gitHub 上可用:github.com/chrisantonellis/freezeframe.js【参考方案7】:

Mark Kramer 的一个更优雅的版本是执行以下操作:

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 el 看起来像:

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

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

【讨论】:

【参考方案8】:

重新启动gif图片的动画,可以使用代码:

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

【讨论】:

【参考方案9】:

像这样添加后缀:

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

每次用户访问该页面时,浏览器都会强制下载一个新图像。此外,客户端缓存可能会很快被填满。

以下是我在 Chrome 49 和 Firefox 45 上测试的替代解决方案。 在 css 样式表中将显示属性设置为“无”,如下所示:

#img_gif
  display:'none';

在'$(document).ready'语句外插入:

$(window).load(function() $('#img_gif').show(); );

每次用户访问页面时,动画会在所有元素加载完成后启动。这是我发现sincronize gif 和html5 动画的唯一方法。

请注意: 刷新页面(如按“F5”)后,gif动画不会重新启动。 “$(document).ready”语句不会产生与“$(window).load”相同的效果。 属性“可见性”不会产生与“显示”相同的效果。

【讨论】:

【参考方案10】:

相关答案,你可以指定一个gif的播放次数。下面的 gif 有 3 个与之关联的播放(10 秒计时器,总共 30 秒播放)。自页面加载后 30 秒后,它会在“0:01”处停止。

刷新页面以重新开始所有 3 次播放

您必须修改 gif 本身。在这里可以找到一个简单的工具来修改 GIF 播放 https://ezgif.com/loop-count。

要查看登录页面上的单循环播放 gif 示例,请使用单个播放 gif https://git-lfs.github.com/ 查看此站点

【讨论】:

【参考方案11】:

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

这里是JS:

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。【参考方案12】:

css 过滤器可以阻止 gif 在 chrome 中播放

添加

filter: blur(0.001px);

到您的 img 标签,然后 gif 冻结以通过 chrome 性能问题加载 :)

【讨论】:

【参考方案13】:

这个答案建立在 Sourabh 的基础上,他在 https://codepen.io/hoanghals/pen/dZrWLZ 上指出了一个 HTML/CSS/JavaScript 组合来完成这项工作。我尝试了这个,并制作了一个完整的网页,包括我在我的网站上尝试过的 CSS 和 JavaScript。由于 CodePens 有消失的习惯,我决定在这里展示一下。我还展示了一个简化的精简版,以展示一个人需要做的最低限度的工作。

我还必须注意一件事。上面链接中的代码(其 JavaScript Sourabh 复制了该代码)引用了 JavaScript 构造函数 SuperGif() 。我认为 Sourabh 没有解释这一点,CodePen 也没有。一个简单的搜索表明它是在buzzfeed / libgif-js ,可以从https://github.com/buzzfeed/libgif-js#readme 下载。查找下方红色箭头所指的控件,然后单击绿色的“代码”按钮。 (注意,你不会看到红色箭头:那是我告诉你在哪里看。)

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

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

这是第一页的完整 HTML、CSS 和 JavaScript。 HTML 的头部是指向 libgif.js 的链接,这是您需要的 zip 文件中的文件。然后,HTML 的正文以一些关于猫图片的文本开头,然后是一个指向动画猫 GIF 的链接,地址为 https://media.giphy.com/media/Byana3FscAMGQ/giphy.gif。

然后继续使用一些 CSS。 CodePen 使用 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>

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

当我按下粉色按钮时,页面变成了这个,GIF 开始动画。 (猫舔着水龙头里掉下来的水。)

最后,这是第二个简单的页面。与第一个不同,它没有花哨的播放/暂停控件来改变形状:它只有两个按钮。代码唯一不需要做的事情就是禁用不相关的按钮,并在按钮之间插入一些空格。

<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 文件,应该足以让任何人开始。

【讨论】:

【参考方案14】:

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

[].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>

【讨论】:

以上是关于停止加载 gif 动画,鼠标悬停开始激活的主要内容,如果未能解决你的问题,请参考以下文章

JQuery中鼠标悬停和鼠标悬停时停止和继续动画的方法

悬停时停止 CSS 动画

在图片框悬停时启用/禁用 GIF [重复]

在鼠标悬停时播放 Gif 并在鼠标移出时暂停 Gif 而不替换图像?

如何在鼠标悬停在图像上时暂停动画

快速鼠标悬停/鼠标悬停的完整悬停动画持续时间?