やわらかしかっけい

なんでもすぐに忘れてしまう自分のために

背景画像フェード切り替えをCSSでやろうとしたが、結局jQueryで実装した

背景画像のSVGがスライドショーのようにフェードで切り替わっていく、というのをやりたかった。

  • SVGである理由
    • 綺麗だから
  • 背景画像である理由
    • SVGだと、背景画像にしないとレスポンシブでのサイズ変更ができないから

CSSのanimationで実装したらiOSChromeでバグが出たので、
結果的にjQueryでやることになった。

CSS animationでやってみた

参考:https://webparts.cman.jp/box/bgfade/

だいたいこんなような感じだったと思う。
画像5枚が30秒でゆっくり1周する。
html

<div class="fade_img">
  <div class="bgImg src1"></div>
  <div class="bgImg src2"></div>
  <div class="bgImg src3"></div>
  <div class="bgImg src4"></div>
  <div class="bgImg src5"></div>			
</div><!-- /fade_img -->

css

.fade_img{
  position: relative;
  width: 330px;
  height: 330px;
  margin: 0 auto;
}
.fade_img  .bgImg{
  position: absolute;
  width: 100%;
  height: 100%;
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
  top        : 0;
  left       : 0;
  bottom     : 0;
  right      : 0;
  opacity    : 0;
 }
.fade_img .src1{
  background-image : url('../../../img/img00.svg');
  animation: bgAnime 30s ease 0s infinite;
}
.fade_img .src2{
  background-image : url('../../../img/img01.svg');
  animation: bgAnime 30s ease 6s infinite;
}
.fade_img .src3{
  background-image : url('../../../img/img02.svg');
  animation: bgAnime 30s ease 12s infinite;
}
.fade_img .src4{
  background-image : url('../../../img/img03.svg');
  animation: bgAnime 30s ease 18s infinite;
}
.fade_img .src5{
  background-image : url('../../../img/img04.svg');
  animation: bgAnime 30s ease 24s infinite;
}
@keyframes bgAnime {
   0% { opacity: 0; }
   8% { opacity: 1; }
  20% { opacity: 1; }
  28% { opacity: 0; }
 100% { opacity: 0; }
}

できたが、iPhone (iOS)のChromeで見た時に、
1周目だけチラついてしまうというバグが発生した。


これらの記事を参考に、
transformやperspectiveなどを一通り指定してみたが、治らなかった。

jQueryを採用

参考:
jQuery : 背景画像のクロスフェード (プラグイン無し) - Web - HomeMadeGarbage

html

<div class="fade_img">
</div>

css

.fade_img{
  position: relative;
  width: 330px;
  height: 330px;
  margin: 0 auto;
}
.fade_img .slides {
  position: absolute;
  width: 100%;
  height: 100%;
  background-repeat: no-repeat;
  background-position: center;  
}
.fade_img .slides:not(:first-child) {
  display: none;
}

script

jQuery(function($){
var speed = 4000;
var times = 6000;
var className = '.fade_img';
var bgArray = [
  "/img/img00.svg",
  "/img/img01.svg",
  "/img/img02.svg",  
  "/img/img03.svg",
  "/img/img04.svg" 
  ];
	$.each(bgArray.reverse(), function(i, value) {
	  $(className).prepend('<div class="slides" style="background-image:url(' + value + ');"></div>');
	});
	var bgNo = 1;
	var bgLength = bgArray.length;
	setInterval(function(){
	  $(className + ' .slides:nth-child(' + bgNo + ')').fadeOut(speed);
	  $(className + ' .slides:nth-child(' + ( bgNo === bgLength ? 1 : bgNo + 1) + ')').fadeIn(speed/3);
	  if ( bgNo >= bgLength ) {
	    bgNo = 1;
	  } else {
	    bgNo += 1;
	  }
	}, times);
});

これで無事に動いたが、しかし

残った課題

MacChromeでの閲覧時、
別のタブにしばらく行ってから戻ってくると、
なんかバグって遷移のスピードが速くなったりしている時がある。

しばらく眺め続けていると治る。

SetIntervalの挙動

別タブにいる間、SetIntervalは途中を省略しつつも動き続けていて、
戻ってきた時に、
「あんたが離脱していた間にたまった処理を、まとめて見せたげるね!」
とやってくれるらしい。やめてくれい

参考:
ブラウザのタブが非アクティブ時のTweenMaxとsetIntervalについて | なんかいろいろデザインする人

解決を試みたが…

【jQuery】ブラウザのタブが非アクティブ時でもsetIntervalの挙動について! - Web.fla

↑こちらの記事のおかげで、なんとかなりそうに思えたが、ならなかった。

  • window読み込み時にfocusを当てる
  • タブのfocusが外れたら、タイマーを止める

→ 別タブで戻ってきた時は動いてくれたが、読み込み時に動かなかった。

Script部分を以下のように変更したのだった

jQuery(function($){

var speed = 4000;
var times = 6000;
var className = '.fade_img';
var bgArray = [
  "/img/img00.svg",
  "/img/img01.svg",
  "/img/img02.svg",  
  "/img/img03.svg",
  "/img/img04.svg" 
  ];

	$.each(bgArray.reverse(), function(i, value) {
	  $(className).prepend('<div class="slides" style="background-image:url(' + value + ');"></div>');
	});
	var bgNo = 1;
	var bgLength = bgArray.length;

	$(window).on("load", function () { focus(); }); //読み込まれたらフォーカスを当てる
	$(window).bind("focus",function(){ //フォーカスが当たったらタイマーを設定

	    var timer=setInterval(animeFunc,times);
	    
		}).bind("blur",function(){ //フォーカスが外れたらタイマーを解除
	    clearInterval(timer);
	    
	});
 
function animeFunc(){
	  $(className + ' .slides:nth-child(' + bgNo + ')').fadeOut(speed);
	  $(className + ' .slides:nth-child(' + ( bgNo === bgLength ? 1 : bgNo + 1) + ')').fadeIn(speed/3);
	  if ( bgNo >= bgLength ) {
	    bgNo = 1;
	  } else {
	    bgNo += 1;
	  }
	}

});