POPSブログ

jQuery レスポンシブスライダー処理

404

  Category:  jquery2017/02/07 pops 

レスポンシブデザインで「TOP画像のスライド」処理等をレスポンシブ対応にしてみました。結構構造と設定などがメンドウですが、大変フシギな事に一応動作します。当然、baserCMSに限らず通常のレスポンシブデザインHTML上でも動作します。その振る舞いなどを調べてみます。

 

responsive

 

TOP画像Slide処理のテスト

画像のレスポンシブ表示の知識をえて、スライド(アニメ)処理を行ってみます。
実際に色々作り、その差異を調べてみます。DEMOはローカル動作で生成したHTMLを表示しています。TOP画像としていますが画像幅を縮めれば他の場所でも利用できます。
注意、動作確認の模擬ページですので、リンクなどは機能しません。


レスポンシブスライダー使用状況

作るのが大変メンドウですから、実際運用には「プラグイン」などを利用しているのが現状であり、自作するなどほぼ無い状態のようですから、作成方法資料などもまだほぼ無い状態です。
よって、以下の記事は興味のある方のみ閲覧ください。

 

max-widthを使用した形

ここより本題に入ります。レスポンシブにはmax-widthを使用すれば対処できます。下記に構造を示します。

demo27b

 

DEMO

BaserCMSでの出力模擬ページでみてみます。ブラウザ幅を変更して確認ください。
スマートフォン、タブレットなどにCSSが適正化されているので表示に問題は出ない。

● 模擬デモページ (http://pops-web.com/main/baserhtml/top27b.html) : TOPページの模擬出力HTML

● スマートフォン等の表示 : 確認ツールで見た場合の表示

PC iphone ipad 或いは類似した機器等での表示例で、携帯(モバイル)には対応していません。PCで確認ください。


通常のHTML5ページでみてみます。ブラウザ幅を変更して確認ください。(スマートフォンでも正常に表示出来るよう修正)

● 通常デモページ (http://pops-web.com/main/baserhtml/test001.html) : 通常ページでの表示デモ

 

構造と簡単な説明

立体的に図示すれば下記の様になる。(window内に収まっている場合)

zu

 

以下、デモの html css js と簡単な説明です。position設定の違いによる振る舞いに注意ください。


1. ul要素はliを横に並べるため、position:absolute です。カラム落ちしない様に長さが重要に成ります。
(100%で目一杯伸びるわけではない、動的に常に横幅を設定しなければなりません)
position:absolute設定でウインドウ外に空白が出来ますが、これは除去出来ます。
2. li要素は position:relative で float させます。ul要素の幅があれば、常に横並びになります。
(通常のHTMLと作り方が同じであるゆえ、反面問題がおき易いようです、li要素はをposition:absoluteで並べる方法もありますがこれは別途後日に説明します)
3. max-widthはli要素に設定します。(但し、不安定な場合は外側div要素にもmax-widthを設定する)
4. 但し、画像は常に大きさを修正しなければ成りません。自動計算表示では無い点に注意。
(li要素が position:absolute の場合では、画像の大きさは自動計算表示に成るので便利なとき有り)
5. 全体をスライド移動するには常に(window幅が変わった場合)、li要素(画像)の位置を計算しなければなりません。
6. 通常のリストの並べ方とほぼ同じですから。多少理解し易いのではないでしょうか。
(構成が単純であるが、全体のスライド以外の変化は難しいかも知れない)
7. 実際には、a-linkを組み込み利用する場合が多いかと思います。
8. 実際の画像の大きさ(880x380サイズ)で表示しています。大きさ指定可能です。
9. 良く考えると、到底 max-width の恩恵を受けているとは思えない複雑さといえます。
10. IE8単独の不具合などもあるようですが、ここでは発生していません。(IEはもう考えたくないです)


● 対応ブラウザと検証

html5.js、css3-mediaqueries.jsを読み込んでいますので、仕方なく「IE」をも検証しました。
当方としては別段IEに対応する気は毛頭有りませんし、特にIE 9 8 7はもはや対応すべきではなく「排除」すべきです。


1. 一応、モダンブラウザおよび、IE 11 10 9 8 7まで表示可能です。(IEは問題ありすぎ...)
(IE11はモダンブラウザに属するが、CSS3、Canvas対応などでは他より劣るので余り対応したくない)
2. 検証はブラウザ付属ので「ペロッパーツール」および「確認ツール」で行いました。(一部、iphone6で確認)
3. デモページで使用のjQueryは jquery-1.11.3.min.js です。


HTML CSS JS

下記にHTML CSS JSを提示します。CSS JSの名前は自由です。一般的にリスト状に下記の様に書くのが好まれます。

HTML


<div id="sliderBox">
 <ul id="sliderBase">
  <li class="image-parts"><a href="#"><img src="/main/baserhtml/images/mainImage-01.jpg" /></a></li>
  <li class="image-parts"><a href="#"><img src="/main/baserhtml/images/mainImage-02.jpg" /></a></li>
  <li class="image-parts"><a href="#"><img src="/main/baserhtml/images/mainImage-03.jpg" /></a></li>
  <li class="image-parts"><a href="#"><img src="/main/baserhtml/images/mainImage-04.jpg" /></a></li>
  <li class="image-parts"><a href="#"><img src="/main/baserhtml/images/mainImage-05.jpg" /></a></li>
 </ul>
</div>

サンプルJS CSS

CSS


/*重要*/
#Page{
overflow:hidden;
}

/* 本体 */
#sliderBox{
position:relative;
width:880px;
height:380px;
margin:0 auto;
padding:0;
background-color:#000000;
overflow:hidden; /*MASK*/
}
#sliderBase{
position:absolute;
top:0;left:0;
width:880px;/*暫定*/
height:auto;
margin:0;
padding:0;
}
#sliderBase li{
list-style:none;
position:relative;
max-width:880px;
height:auto;
margin:0;
padding:0;
float:left;
}
#sliderBase li img{
width:100%;
height:auto;
margin:0;
padding:0;
}

/* btn */
#btnBox{
width:100%;
height:auto;
margin:10px auto;
text-align:center;
z-index:1000;
}
#btnBox span{
width:100%;
height:auto;
margin:5px;
font-size:16px;
color:#000000;
cursor:pointer;
}
#btnBox span.active{
color:#ff0000;
}

JS


//simple-slider3b.js
//画像slider、通常処理形式
//コントロールspan構成/a-linkつき
//IE7スクロールOK

(function($){

  $(function(){

    function init(){

	//画像の大きさ
	var image_w=880;
	var image_h=380;

	//時間
	var cycle_time=8000;
	var slide_time=800;

	//BTNグループの使用true、不使用false
	var hitbtn_use=true;

	//オブジェクト
	var box_elm_wrap=$('#sliderBox');
	var box_elm=$('#sliderBase');
	var img_elm=$('#sliderBase li');

	//変数、未使用あり
	var image_max=img_elm.length;
	var timerID=null;
	var image_no=0;
	var keep_no=0;
	var image_urls=[];
	var slide_pos=[];
	var slideelm=[];//オブジェクト保存
	var item_w;
	var cross_url="";
	var animeflag=false;

	//BTNオブジェクト
	var hit_btns=[];

	var width_v=image_w;
	var height_v=image_h;
	var keep_w=image_w;

	//URL取得位置計算
	$('#sliderBase').find('li').each(function(i){
		//仮位置
		var posxs=width_v*i;
		slide_pos[i]=posxs;//位置保存
		slideelm[i]=img_elm.eq(i);//オブジェクト保存
		//image_urls[i]=$(this).find("a").children("img").attr('src');//URL保存
	});

	//BTNグループaction-set
	if(hitbtn_use){

		//後ろにappendする
		$('#sliderBox').after('<div id="btnBox"></div>');
		var mark="&#9679;";
		//make-btn
		var btnhtml="";
		for (var i=0; i < image_max; i++) {
			//ID名を付ける
			var name="hitbtn"+i;
			btnhtml += '<span id="' + name +'">' + mark + '</span>';
		}
		//append #btnBox
 		$('#btnBox').append(btnhtml);
		btnhtml="";

		//action
		$('#btnBox').find('span').each(function(i){
			$(this).click(function(){hitno_set(i);});
		});
		//オブジェクト保存
		for (var i=0; i < image_max; i++) {
			hit_btns[i]=$('#hitbtn'+i);
		}

		//最初をactiveに
		hit_btns[0].addClass('active');

	}

	//初期化、寸法きめ
	image_no=0;
	resizeFunc();

	//スタート遅延なし
	set_timer();


	//エフェクト処理
	function effectImage(){

		animeflag=true;
		//位置情報
		var pos_x=width_v;
		var pos_y=height_v;

		if(hitbtn_use){
			hit_btns[keep_no].removeClass('active');
		}

		var pos_x=width_v*image_no;

		//エフェクト
		box_elm.animate({'left':-pos_x},slide_time,function(){

			//処理番号保存
			keep_no=image_no;
			animeflag=false;
			slideflag=true;

			if(hitbtn_use){
				hit_btns[image_no].addClass('active');
			}

			set_timer();

		});

	}

	//次ぎの開く要素を計算
	function next_set() {

		slideflag=true;
		//次ぎの番号
		image_no +=1;
		if (image_no > (image_max-1)) {image_no=0;}
		effectImage();
	}
	//指定番号で計算
	function hitno_set(no) {

		//表示番号ならキャンセル
		if(no==keep_no){return false}
		//アニメ中はキャンセル
		if(animeflag){return false}
		//タイマーclear
		clearTimeout(timerID);
		//番号
		image_no=no;
		effectImage();
		return false
	}

	//タイマーSET
	function set_timer(){

		//一旦切ってからセット
		clearTimeout(timerID);
		timerID=setTimeout(next_set,cycle_time);

	}

	//window-resize
	$(window).resize(resizeFunc);

	//スライドのためBOXの大きさ設定
	function resizeFunc(){

		window_width=$(window).width();

		//BOX、画像修正
		if(window_width<image_w){

			var w=window_width;
			var ratio=window_width/image_w;
			var h=image_h*ratio;
			var ul_w=w*image_max;

			//現在の大きさ
			width_v=w;
			height_v=h;

			box_elm_wrap.css({'width':w,'height':h});
			box_elm.css({'width':ul_w,'height':h});

			//画像幅位置修正
			chg_pos(width_v);

		}else{

			var ul_w=image_w*image_max;
			//現在の大きさ
			width_v=image_w;
			height_v=image_h;

			box_elm_wrap.css({'width':image_w,'height':image_h});
			box_elm.css({'width':ul_w,'height':image_h});

			//画像幅位置修正
			chg_pos(width_v);

		}

	}

	//画像幅位置修正
	function chg_pos(w_v){
		//幅変更がなければ実行しない
		if(keep_w==w_v){return}
		//処理
		var maxlen=image_max;
		//移動位置再計算
		for (var i=0; i < maxlen; i++) {
			slide_pos[i]=w_v*i;
			slideelm[i].find("img").css({'width':w_v});//画像幅
		}
		//現在番号位置にBaseをセット、動いた場合の修正
		var psx_v=slide_pos[keep_no]*-1;
		box_elm.css({'left':psx_v});
		keep_w=w_v;
	}

    }//init end

    //--------------------------

    //遅延/IE7
    setTimeout(function() {
      init();
    },10);

  });

})(jQuery);


HTML5でのテスト表示結果

通常デモページ (http://pops-web.com/main/baserhtml/test001.html) のHTML構成を違わせてテストした結果、モダンブラウザおよび IE7-11 まで表示結果はOKでした。

test

HTML5でのテスト表示ですが、スライダー部分はそのまま配置しています。上図は、上下の要素部分を「@media screen設定」と「@media screen設定なし」の場合の比較ですが、共に「スライダー部分」は正常に動作します。


重要、スライダー部分、右外側の「空白」が出来る場合がありますが除去の処理です。body直下の全体をラップした要素に overflow:hidden 設定すれば除去出来ます。「空白」の出ない処理方法もありますが...

事前に仕組みを作っておくのが懸命と思います。ID名などは自由です。


<body>
	<div id="wrapper">

	従来のHTML

	</div>
</body>


#wrappr{
overflow:hidden;
}

つまり、max-width をそのまま単独で使用すれば、構造によっては右外側に「空白」が出来る。

media screen設定を上書きすれば、直りますが... 、下の「@media screen設定の場合2」参照の事。


#xxxx{
max-width:xxxxpx;
}

@media設定なしで幅100%設定の場合。簡単なのでこちらでテスト表示してます。


#header,#main{
width:100%;
height:100%;/*IE8*/
margin:0 auto;
text-align:center;
background-color:#eee;
}

@media screen設定の場合1。

他の、media screen設定の外でも内でも挿入表示可能です。

確認ツール、iPhone 6 表示のスライド位置が少しおかしいが(次画像の一部が表示される)、ツールが古いせいであろう。他のデベロッパーツール確認方法では問題が無い。
また、比較的新しい、http://quirktools.com/screenfly/ の確認ツールでは正常に表示しますので、問題ないと推測します。

一番外側の要素、#sliderBoxを max-width:880px 設定にしたら正常になりました。少々手抜きだったのでしょうか....


#header,#main{
width:1025px;
height:100%;/*IE8*/
margin:0 auto;
text-align:center;
background-color:#eee;
}

/* media上書き */
@media screen and (max-width:1024px){
	#header{
		width:100%;
	}
	#main{
		width:100%;
	}
}

@media screen設定の場合2。

スライダーにmedia screen設定の場合は下記の様になるが、余りこのような設定で使用する事は無いと思う。
この場合、max-widthは media screen に設定されますので要素の幅は width:880px となる。

また個別にmedia screen 設定されましたので右に空白は出ません。心配な方はそのままでも結構です。HTML表示に影響は有りません。


#sliderBox{
position:relative;
width:880px;
height:380px;
margin:0 auto;
padding:0;
background-color:#000000;
overflow:hidden; /* MASK */
}
/* 上書き */
@media screen and (max-width:879px){
	#sliderBox{
		width:100%;
	}
}

---------------------------------------------

スライダーに@media screen設定のため
下記の空白除去は原則不要です
#wrappr{
overflow:hidden;
}

レスポンシブ CSSについては下記参考にしました。CSSの神様です。

【参考】: レスポンシブ・ウェブデザインでの CSS コードの書き方


ブラウザ幅が変わった場合の処理

主に、ブラウザの大きいPC向けの処理ですが、スマートフォンなども向きを変えますので、ブラウザ幅が変化した時の処理を書けば、常に意図する大きさに表示修正出来ます。構造により違いがありますので、効率よい構造を見つけるのが大変です。
どこまで処理するかは作成する者の考え方次第になります。

数をこなすほか方法は無いし、資料などはほぼ無い。利口な方は自作しないでプラグインを利用するのが現状の様です。



var window_width;

//window-resize
$(window).resize(resizeFunc);

//resizeされた時の処理
function resizeFunc(){

	//サイズ取得
	window_width=$(window).width();

	処理を書く

}

ブラウザ右側に空白がでる場合の処置

構造、CSS設定によっても異なると思いますが、margin:0 auto で中央表示を行った場合、下図中央の様に、構造によってはスクロールバーなどが出て、右側に少し余白が出て横幅が広がる場合があります。また、position:absoluteで配置した場合も同様です。
下記の様にすれば修正可能です。(DEMOページの場合の図)

page

 

1. body直下の要素に overflow:hidden 設定すると除去できます。
2. 通常Body直下にwrapperがあることが多いので、そこにhidden処理するようです。
3. DEMOページでは全体を #Page でラップしていますので、そこに処置しました。
4. IE7では構造次第では、「空白」を除去できない場合があります。(たいした問題では無い)


各ページのHTML構成は、下記の様に、ID「Page」のDIV要素でラップなっています。
(baserCMS構成の場合は「Page」でラップする癖が今回役に立つ結果となる)


<body>
 <div id="Page">

   ページのHTML構造

 </div>
</body>

----------------------------------------------
bodyはダメです、縦にスクロールできなくなる

#Page{
overflow:hidden;
}

エフェクト処理部分を大きくラップして、overflow:hidden しても除去出来ません。


通常Body直下にwrapperがあることが多いので、そこにhidden処理するようです。このデモHTMLではwrapperがエフェクト処理部分以下に有りますので、#Pageにしました。
#Pageなど無い場合はjQueryで処理しても良い。(ID名は自由です)


● jQueryで処理する場合は下記の様にすれば良い。


//#Pageが無い場合Body直下をラップする
$("body").wrapInner('<div id="xxxxx"></div>');
//hidden
$('#xxxxx').css({'overflow':'hidden'});

//幅設定が必要ならば
$('#xxxxx').css({'width':'100%','overflow':'hidden'});

マスク処理

1画像のみ表示するため、マスク処理していますが、ブラウザにより振る舞いが違います。


1. モダンブラウザは高さ指定が無くとも、マスク処理出来ます。
2. IE系は明示的に高さ指定をしなければならない。
3. IE7は position:relative 指定をしなければならない。
4. IE7.8マスクが安定しない場合は、横縦共に明示的に数値で変更する。


よって、ブラウザ幅が変化するたびに高さを指定処理しています。
width:880px でもいけるが、max-width:880px 設定のほうが安定する。正式にはmax-width:880px設定で在ろう。
一部のスマートフォンで乱れる場合は、max-width:880px 設定のほう良いと思われる。


CSS

#sliderBox{
position:relative;
width:880px;
height:380px;
margin:0 auto;
padding:0;
background-color:#000000;
overflow:hidden; /* MASK */
}

---------------------------------------------
JS処理、IE対策
box_elm.css({'width':ul_w,'height':h});
および
box_elm.css({'width':ul_w,'height':image_h});

position:absoluteに伴う不随処理

今まで、レスポンシブでなければ問題にはなりませんでしたが、
UL要素部分を position:absolute にしているために、ブラウザ幅を変更すれば高さが変わりますので、全体をラップしてその都度高さを変更しています。修正処理しないと余計な余白が出たり、場合によっては下のコンテンツが画像の下に潜り込む。
高さは画像の縦横の構成比率より計算しています。
画像は自動的に大きさが決まる場合が多いが、このJSでは画像の大きさをその都度決定しています。

zuzu

 

ブラウザ幅が変化した場合の処理


box_elm_wrap.css({'height':h});
および
box_elm_wrap.css({'height':image_h});

---------------------------------------------

マスクが安定しない場合、主にIE7.8、横も設定する

box_elm_wrap.css({'width':w,'height':h});
および
box_elm_wrap.css({'width':image_w,'height':image_h});

「li」要素のポジション位置

「li」要素は自動的に、float:leftで横に並びますが、スライドするのは親で有る「ul」要素です。
そのため事前にポジション位置を計算して置きマイナス方向にスライドさせます。
但し、ブラウザ幅が変わればポジション位置も変化しますので、その都度「再計算」しなければなりません。

画像の大きさも「再計算」しますので次の様に処理しています。また「li」要素のポジション位置も変更しています。


	//画像幅位置修正
	function chg_pos(w_v){
		//幅変更がなければ実行しない
		if(keep_w==w_v){return}
		//処理
		var maxlen=image_max;
		//移動位置再計算
		for (var i=0; i < maxlen; i++) {
			slide_pos[i]=w_v*i;
			slideelm[i].find("img").css({'width':w_v});//画像幅
		}
		//現在番号位置にBaseをセット、動いた場合の修正
		var psx_v=slide_pos[keep_no]*-1;
		box_elm.css({'left':psx_v});
		keep_w=w_v;
	}


● each()処理の注意

each()処理のjQueryセレクタの書き方如何では、一部スマートフォンで処理出来ない場合があるようです。(OSのバージョンにも関係あると思いますが...)

このような書き方では処理出来ない場合がある。困るな....


$('#sliderBase li').each(function(i){
	//
});

この書き方なら問題なく、処理も早い。この後resizeFunc()で正式な位置計算など行っているので、オブジェクト保存だけでよい。サムネールが必要ならここで画像URLを取得する。その他事前処理があればここで書けます。


$('#sliderBase').find('li').each(function(i){
	//仮位置
	//var posxs=width_v*i;
	//slide_pos[i]=posxs;//位置保存
	slideelm[i]=img_elm.eq(i);//オブジェクト保存
	//image_urls[i]=$(this).find("a").children("img").attr('src');//URL保存
});

● Pagerボタンの作成

Pagerボタンの作成は「span」要素で行っている。floatせずに横に並ぶので便利である。スマートフォンを考慮してほとんどが画像数最大5-6個で使用されるので「span」要素構成が効率的と思う。
「active」クラス処理のため「span」要素にIDを付与している。この方が処理が早くなる。

注意、Pagerボタンはスライダー本体の外側に配置されています。

現在、Pagerボタンは「●」を表示している。四角なら「■」、&#9632; である。


var mark="&#9679;";
//make-btn
var btnhtml="";
for (var i=0; i < image_max; i++) {
	//ID名を付ける
	var name="hitbtn"+i;
	btnhtml += '<span id="' + name +'">' + mark + '</span>';
}

画像サムネール表示なら「img」要素を入れればよい。あとで事前に保存している「画像URL」をattr()すれば表示出来る。

サンプルのJSでは「画像サムネール」表示は処理していません。


var mark="<img />";

● JS最後の遅延処理

主にIE系ですが、画像を読み込んでからでなければ、上手く動作しない場合など1秒位遅延させると良い場合があります。その対策で付けていますが、今回は必要ではありませんでした。


//遅延/IE7
setTimeout(function() {
 init();
},10);

 

使用画像

原則、使用者が用意します。(880x380サイズ) : サンプルでの使用画像




以下、形態の違うJSのテストです。baserCMS4.0系とはなっていますが、どんなCMSでも動作すると思います。

【参照】当方の記事: baserCMS4.0系 TOP画像のエフェクト処理

【参照】当方の記事: baserCMS4.0系 TOP画像のTransition処理

【参照】当方の記事: baserCMS4.0系 TOP画像のエフェクト処理2

【参照】当方の記事: baserCMS4.0系 TOP画像のエフェクト処理3


 

今回は単純にするため、コントロールボタンなど省きました。簡単ですが、以上です。

 


[ この記事のURL ]


タグ:jquery , Slider , css3 , html5

 

ブログ記事一覧

年別アーカイブ一覧



[1]