web-dev-qa-db-ja.com

アニメーションGIFを背景画像として再起動します

background-imageとして使用されているアニメーションGIFを再開することはできますか?

このHTMLを検討してください。

<div id="face">
    <div id="eyes"></eyes>
</div>

そしてこのスタイル:

#eyes.blink {
    background-image:url('blink.gif');
}

クラスblinkblink.gifに追加するたびに、初めてではなく、#eyesアニメーションを再生したいと思います。

私はこれがうまくいくと思っていました:

function startBlink() {
    $('#eyes').addClass('blink');
}

function stopBlink() {
    $('#eyes').removeClass('blink');
}

問題は、FirefoxとWebKitブラウザーの両方が、一度再生されると、背景画像のGIFアニメーションを再度再生しないことです。クラスの点滅の追加/削除は、初めてのみ機能します。

18
hpique

アニメーションGIFをリロードすると、再生できます。これは、特に画像が大きい場合、帯域幅には理想的ではありませんが、アニメーションの再起動を強制します。

私の例では、<div id="animated">onclickを追加および削除しています。

$('#animated').click(function() {

    /* Reference to the clicked element and toggle the .go class */
    var $div = $(this);
    $div.toggleClass('go');

    /* Start the animated gif */
    if ($div.hasClass('go')) {

        /* Create an <img> element and give it the animated gif as a src.  To 
           force a reload we add a date parameter to the URL */
        var img = document.createElement('img');
        img.src = "http://yoursite.com/animated.gif?p" + new Date().getTime();

        /* Once the image has loaded, set it as the background-image */
        $(img).load(function(){
            $div.css({backgroundImage: "url("+img.src+")"});
        });

    /* Remove the background-image */        
    } else {
       $div.css({backgroundImage: "none"});
    }
})

デモ 動作中。

17
Pat

画像のsrcの最後に?+Math.random()を追加して、.gifを再読み込みすることもできます。

7
JVE999

ソリューションのいくつかの部分を組み合わせて、(うまくいけば)すべての問題を解決する1つのソリューション全体を作成しました。

  • 要素の背景画像のURLを決定します(css background-imageから)
  • Webからリロードせずに、そのイメージの再起動をトリガーします
  • すべての場所で再起動します(それぞれに個別に触れることなく)
  • アニメーションを再開した後、ターゲットがアーティファクトなしで再描画されていることを確認します

私のソリューションでは、本文に追加されるが、ブラウザによってレンダリングされるが、position: absolute; left: -5000px;を使用してページと視覚的に相互作用しないように非表示にするヘルパー画像を作成します。

ヘルパー画像への参照はresetHelperImagesにキャッシュされるため、以降の呼び出しで同じ画像に再利用できます。

私の例ではjQueryを使用していますが、jQueryがなくても機能するように適合させることができます。

テスト済み:Chrome(バージョン43.0.2357.130 m)

var resetHelperImages = {};

function restartAnimation(elem) {
  elem = $(elem);
  for (var i = 0; i < elem.length; i++) {
    var element = elem[i];
    // code part from: http://stackoverflow.com/a/14013171/1520422
    var style = element.currentStyle || window.getComputedStyle(element, false);
    // var bgImg = style.backgroundImage.slice(4, -1).replace(/"/g, '');
    var bgImg = style.backgroundImage.match(/url\(([^\)]+)\)/)[1].replace(/"/g, '');
    // edit: Suggestion from user71738 to handle background-images with additional settings

    var helper = resetHelperImages[bgImg]; // we cache our image instances
    if (!helper) {
      helper = $('<img>')
        .attr('src', bgImg)
        .css({
          position: 'absolute',
          left: '-5000px'
        }) // make it invisible, but still force the browser to render / load it
        .appendTo('body')[0];
      resetHelperImages[bgImg] = helper;
      setTimeout(function() {
        helper.src = bgImg;
      }, 10);
      // the first call does not seem to work immediately (like the rest, when called later)
      // i tried different delays: 0 & 1 don't work. With 10 or 100 it was ok.
      // But maybe it depends on the image download time.
    } else {
      // code part from: http://stackoverflow.com/a/21012986/1520422
      helper.src = bgImg;
    }
  }
  // force repaint - otherwise it has weird artefacts (in chrome at least)
  // code part from: http://stackoverflow.com/a/29946331/1520422
  elem.css("opacity", .99);
  setTimeout(function() {
    elem.css("opacity", 1);
  }, 20);
}
.myBgImageClass {
  background-image: url('http://i410.photobucket.com/albums/pp184/OllieMarchant/Countup.gif');
  width: 100px;
  height: 150px;
  background-size: 100%;
  background-repeat: no-repeat;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="myBgImageClass"></div>
<button onclick="restartAnimation($('.myBgImageClass'))">restart</button>

毎回GIFをリロードせず、帯域幅を浪費しない代替手段があります。

GIFをBase64としてメモリに保存し(ブラウザのキャッシュを回避)、FileReader APIを使用します(これは 最近のすべてのブラウザでサポートされているようです )。この方法でイメージをロードする場合は、クロスオリジンポリシーが適用されることに注意してください(イメージリロードソリューションとは異なります)。

更新:ブラウザのキャッシュは、背景画像データURIのキャッシュに関してよりスマートになり、アニメーションが最初からやり直されないようになっています。キャッシュを無効にするランダムな文字列をデータURLに追加する必要があることがわかりました( DataURI Scheme によると、オプションの属性と見なす必要があります。Chrome =&IEエッジ。)

実際の動作をご覧ください: http://jsfiddle.net/jcward/nknLrtzL/10/

仕組みは次のとおりです。この関数は、画像をBase64でエンコードされた文字列として読み込みます。

function toDataUrl(url, callback) {
  var xhr = new XMLHttpRequest();
  xhr.onload = function() {
    var reader = new FileReader();
    reader.onloadend = function() {
      callback(reader.result);
    }
    reader.readAsDataURL(xhr.response);
  };
  xhr.open('GET', url);
  xhr.responseType = 'blob'; // IE11, set responseType must come after .open()
  xhr.send();
}

次に、GIFアニメーションを再開するときはいつでも、background-imageプロパティをnoneに変更してから、base64文字列を変更します(一部のブラウザでは、子を再度追加して、更新をトリガーする必要があります。 setTimeout):

$div.css({backgroundImage: "none"});
$div.parent().add($div); // Some browsers need this to restart the anim
// Slip in a cache busting random number to the data URI attributes
$div.css({backgroundImage: "url("+img_base64.replace("image/gif","image/gif;rnd="+Math.random())+")"});

toDataURL関数の この回答 に感謝します(IE11の修正あり)。

1
Jeff Ward

Flash.gifとblink2.gifという同じ画像を2回使用して、2つのクラスを追加し、クラスを切り替えることを検討しましたか?

<div id="face">
    <div id="eyes"></eyes>
</div>

.blink {
    background-image:url('blink.gif');
}

.blink2 {
    background-image:url('blink2.gif');
}

function MakeBlink()
{
   if ($('#eyes').hasClass('blink'))
   {
      $('#eyes').removeClass('blink').addClass('blink2');
   } else
   {
     $('#eyes').removeClass('blink2').addClass('blink');
   }
}
1
Richard

私がまだこれを時々必要としているという理由だけで、私が使用する純粋なJS関数が他の誰かに役立つかもしれないと思いました。これは、アニメーションGIFをリロードせずに再起動する純粋なJSの方法です。これは、リンクやドキュメントの読み込みイベントから呼び出すことができます。

<img id="img3" src="../_Images/animated.gif">

<a onClick="resetGif('img3')">reset gif3</a>

<script type="text/javascript">

// reset an animated gif to start at first image without reloading it from server.
// Note: if you have the same image on the page more than ones, they all reset.
function resetGif(id) {
    var img = document.getElementById(id);
    var imageUrl = img.src;
    img.src = "";
    img.src = imageUrl;
};

</script>

一部のブラウザでは、img.srcをそれ自体にリセットするだけで、正常に機能します。 On IEリセットする前にクリアする必要があります。このresetGif()は、画像IDから画像名を選択します。これは、特定のIDの実際の画像リンクを変更する場合に便利です。 resetGiF()呼び出しを変更することを覚えておく必要はありません。

-ニコ

1
nico

何らかの理由でこれは機能します:

// Append the image to the page
var i = new Image();
i.src = 'some.gif';
document.body.appendChild(i);

// Now execute this line and the gif will restart
// (anywhere it appears on the page, including CSS backgrounds)
i.src = 'some.gif';

これには、実際の画像DOM要素をページに追加する必要がありますが、visibility: hiddenで非表示にすることができます。これしませんイメージをネットワーク経由で複数回ダウンロードする必要があります。

私はこれをFirefoxとChromeでのみテストしました。他のブラウザについてはよくわかりません。

0
Benjamin Knight

この回答 投稿者 Frederic Leitenberger に関しては、うまく機能していることがわかりました。

ただし、背景画像に次のように複数のレイヤー化された部分がある場合は機能しなくなります。

background-image: url(https://upload.wikimedia.org/wikipedia/commons/5/53/Google_%22G%22_Logo.svg),
    radial-gradient(ellipse at center,
        rgba(255,255,255,1) 0%,
        rgba(255,255,255,1) 50%,
        rgba(255,255,255,0) 80%);

この制限を回避するために、次のように、背景画像のURLを見つける行を変更しました。

var bgImg = style.backgroundImage.match(/url\(([^\)]+)\)/)[1].replace(/"/g, '');

これは、正規表現を使用して、背景画像のURL部分のみを抽出します。

これをコメントとして リンクされた回答 に追加したと思いますが、私は評判のない初心者なので、そうすることはできませんでした。適切な担当者がいる場合は、実際の回答にその行を追加することをお勧めします。

0
user71738