【解決】[js]swiperでぶつかった問題のメモ。

bxsliderの動作がどうにも気に入らないので乗り換えを考えてる。

やりたいこと

幅で切り替えるレスポンシブデザインで組んでる。
その中で設置するスライドでは、PCとスマホで表示する画像のサイズを違うものにしたい。
一般的な手法としては、PC・SPそれぞれ用のスライドを作り、任意のタイミングで表示・非表示を切り替える。
bxsliderでそれをやると、PC→SP→PCみたく1周した時にスライドが表示されない症状が出た。
切り替えをcssでやったからか?jsでならできるのか?そこはまだ未検証。
まあでも幅指定をあっちこっちでやってると何かの時にズレて面倒が起きると嫌なので、じゃあ違うのに乗り換えようってなった。
スライド動作が何かのタイミングで変になったりとかもあったしね。

それぞれ用意して切り替え

こんな感じで作ってみた

<div class="swiper-container onlyPC">
<ul class="swiper-wrapper">
<li class="swiper-slide"><a href="#"><img src="http://placehold.jp/1600x600.png" alt="" /></a></li>
<li class="swiper-slide"><a href="#"><img src="http://placehold.jp/1600x600.png" alt="" /></a></li>
<li class="swiper-slide"><a href="#"><img src="http://placehold.jp/1600x600.png" alt="" /></a></li>
<li class="swiper-slide"><a href="#"><img src="http://placehold.jp/1600x600.png" alt="" /></a></li>
</ul>
<div class="swiper-pagination"></div>
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
</div>
<div class="swiper-container onlySP">
<ul class="swiper-wrapper">
<li class="swiper-slide"><a href="#"><img src="http://placehold.jp/750x1000.png" alt="" /></a></li>
<li class="swiper-slide"><a href="#"><img src="http://placehold.jp/750x1000.png" alt="" /></a></li>
<li class="swiper-slide"><a href="#"><img src="http://placehold.jp/750x1000.png" alt="" /></a></li>
<li class="swiper-slide"><a href="#"><img src="http://placehold.jp/750x1000.png" alt="" /></a></li>
<li class="swiper-slide"><a href="#"><img src="http://placehold.jp/750x1000.png" alt="" /></a></li>
</ul>
<div class="swiper-pagination"></div>
</div>
<p><script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.1/js/swiper.min.js"></script><script>
	var mySwiper = new Swiper ('.swiper-container', {
		initialSlide: 0,
    	loop: true,
		autoplay: 4000,
		speed: 1000,
		centeredSlides : true,
		pagination: '.swiper-pagination',
		nextButton: '.swiper-button-next',
		prevButton: '.swiper-button-prev'
    })
</script>[/html][css]@media screen and (min-width:751px){.onlySP{ display: none;}}@media screen and (max-width:750px){.onlyPC{ display: none;}}

ブラウザ幅750pxで切り替わる。
切り替わるんだけど、自動送りが効かなくなる。
.swiper-container自身に表示・非表示を持たせてるけど、
親を作ってそっちでやっても同様になる。
display:none;をvisibility:hidden;にしても同じ。
まあ非表示中も動かれちゃ処理がたまったもんじゃないってことなんかな、とも思う。
ページ読み込み時は両方回ってるけど。

読み込み画像を書き換える

例えばこんな感じ。

<div class="swiper-container">
<ul class="swiper-wrapper">
<li class="swiper-slide"><a href="#"><img src="http://placehold.jp/1600x600.png" alt="" /></a></li>
<li class="swiper-slide"><a href="#"><img src="http://placehold.jp/1600x600.png" alt="" /></a></li>
<li class="swiper-slide"><a href="#"><img src="http://placehold.jp/1600x600.png" alt="" /></a></li>
<li class="swiper-slide"><a href="#"><img src="http://placehold.jp/1600x600.png" alt="" /></a></li>
</ul>
<div class="swiper-pagination"></div>
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.1/js/swiper.min.js"></script>
<script>
	var mySwiper = new Swiper ('.swiper-container', {
		initialSlide: 0,
    	loop: true,
		autoplay: 4000,
		speed: 1000,
		centeredSlides : true,
		pagination: '.swiper-pagination',
		nextButton: '.swiper-button-next',
		prevButton: '.swiper-button-prev'
    })
</script>


var timer = false;
var slideImg = $('.swiper-slide img');
var slideSP = slideImg.attr('src').replace('1600x600','750x1000');
var slidePC = slideImg.attr('src').replace('750x1000','1600x600');
$(window).resize(function() {
var windowWidth = $(window).width();
if (timer !== false) {
clearTimeout(timer);
}
timer = setTimeout(function() {
console.log('resized');
if(windowWidth < 750){ $('img').attr('src', slideSP); }else{ $('img').attr('src', slidePC); } }, 200); }); 

ファイル名を置換するので当然読み込み画像は変更される。 だけど切り替えると表示がぶっ壊れる。 却下。

言い訳など

知恵を絞れば越えられる山だと思ったんだけど甘かったらしい。
探せば望みのものが出てくるかもしれない。
初めからそっちでやってればよかったかもしれない。

こういう切り替えは普通useragentの切り替えに合わせてやってる感じがある。
それに勝ちたかっただけなんだ。

20180906追記:解決

コメントのアドバイスに従ったらできた。
人に教えてもらえる有り難さったらない。
本当にありがとうございました。

<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script>
$(function(){
	var timer = false;
	var slideImg = $('.swiper-slide img');
	var slideSP = slideImg.attr('src').replace('1600x600','750x1000');
	var slidePC = slideImg.attr('src').replace('750x1000','1600x600');
	$(window).resize(function() {
	var windowWidth = $(window).width();
		if (timer !== false) {
			clearTimeout(timer);
		}
		timer = setTimeout(function() {
			console.log('resized');
			if(windowWidth < 750){
				$('img').attr('src', slideSP);
			}else{
				$('img').attr('src', slidePC);
			}
		}, 200);
	});
});
</script>
<div class="swiper-container">
<ul class="swiper-wrapper">
<li class="swiper-slide"><a href="#"><img src="http://placehold.jp/1600x600.png" alt="" /></a></li>
<li class="swiper-slide"><a href="#"><img src="http://placehold.jp/1600x600.png" alt="" /></a></li>
<li class="swiper-slide"><a href="#"><img src="http://placehold.jp/1600x600.png" alt="" /></a></li>
<li class="swiper-slide"><a href="#"><img src="http://placehold.jp/1600x600.png" alt="" /></a></li>
</ul>
<div class="swiper-pagination"></div>
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.1/js/swiper.min.js"></script>
<script>
	var mySwiper = new Swiper ('.swiper-container', {
		initialSlide: 0,
    	loop: true,
		autoplay: 4000,
		speed: 1000,
		centeredSlides : true,
		pagination: '.swiper-pagination',
		nextButton: '.swiper-button-next',
		prevButton: '.swiper-button-prev',
		observer: true,
		observeParents: true
    })
</script>

端的にいうと、パラメータに「observer: true」または「observeParents: true」もしくは両方突っ込めば動く。
調べると動作が遅いっぽいとか出てきたけど、背に腹。

上記でやった、PC/SPそれぞれのスライドを作って表示/非表示切り替えるやつにはダメ。
ついでにこういうのもダメ。

<p><style>
@media screen and (min-width:751px){
.onlySP{ display: none;}
}
@media screen and (max-width:750px){
.onlyPC{ display: none;}
}
</style>
<div class="swiper-container">
<ul class="swiper-wrapper">
<li class="swiper-slide onlyPC"><a href="#"><img src="http://placehold.jp/1600x600.png" alt="" /></a></li>
<li class="swiper-slide onlyPC"><a href="#"><img src="http://placehold.jp/1600x600.png" alt="" /></a></li>
<li class="swiper-slide onlyPC"><a href="#"><img src="http://placehold.jp/1600x600.png" alt="" /></a></li>
<li class="swiper-slide onlyPC"><a href="#"><img src="http://placehold.jp/1600x600.png" alt="" /></a></li>
<li class="swiper-slide onlySP"><a href="#"><img src="http://placehold.jp/750x1000.png" alt="" /></a></li>
<li class="swiper-slide onlySP"><a href="#"><img src="http://placehold.jp/750x1000.png" alt="" /></a></li>
<li class="swiper-slide onlySP"><a href="#"><img src="http://placehold.jp/750x1000.png" alt="" /></a></li>
<li class="swiper-slide onlySP"><a href="#"><img src="http://placehold.jp/750x1000.png" alt="" /></a></li>
<li class="swiper-slide onlySP"><a href="#"><img src="http://placehold.jp/750x1000.png" alt="" /></a></li>
</ul>
<div class="swiper-pagination"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.1/js/swiper.min.js"></script>
<script>
	var mySwiper = new Swiper ('.swiper-container', {
		initialSlide: 0,
    	loop: true,
		autoplay: 4000,
		speed: 1000,
		centeredSlides : true,
		pagination: '.swiper-pagination',
		nextButton: '.swiper-button-next',
		prevButton: '.swiper-button-prev',
		observer: true,
		observeParents: true
    });
</script>

動的になんちゃらしたい場合はjsで書き換えましょう、ということみたい。

20200715追記

もっと手っ取り早い方法を思いついたので。

レスポンシブで切り替えることを前提にするのであれば、<img>で書くんじゃなくて.swiper-slideかその下層で背景に画像設定して、cssの@media screenで切り替えたほうがスマート。楽。それがいい

コメント

  1. yatokesa より:

    これを生成時のパラメータに追加してみてはどうでしょう
    observer: true
    observeParents: true
    ずいぶんと悩まされました。

    • megefeps より:

      コメントありがとうございます。
      できました!
      パラメータちゃんと調べずにいじってたのがバレちゃいました。
      お恥ずかしい限りです。

  2. TYD より:

    こんにちは。
    同じような画像スライダーを実装しようとしています。
    動作としては、スマホ用表示の際には別画像、またはリサイズされた画像を表示したいと考えています。

    ”解決版”の記述で実装しようとした際に、複数画像は必要でしょうか?
    また別途cssに記述することはありますでしょうか?

    • megefeps より:

      コメントありがとうございます。

      ■複数画像が必要かどうか
      この記事の趣旨は「swiperで表示画像をPC/スマホ(≒ブラウザ幅)により切り替える」ですので、PCとスマホでそれぞれの画像を用意するという意味では複数画像が必要です。
      記事内では以下のように振り分けました。
      PC:http://placehold.jp/1600×600.png
      スマホ:http://placehold.jp/750×1000.png
      jsでブラウザ幅750pxを境にしてファイル名「1600×600」と「750×1000」を置換し、適した画像を表示するようにしています。
      実際にスライドを設置する際はファイル名もしくはディレクトリを
      http://example.com/img/slide01_pc.png
      http://example.com/img/slide01_sp.png

      http://example.com/img/pc/slide01.png
      http://example.com/img/sp/slide01.png
      などにして「pc」と「sp」を切り替えれば個別に指定する手間もなくて良さそうですね。

      ■CSSについて
      PC/スマホで画像を切り替えるにあたり、必要な処理はすべてjs上で完結しています。
      従って、CSSの記述は必要ありません。

タイトルとURLをコピーしました