POPSブログ

jQuery レスポンシブ・スライダー、外側にボタン配置

406

  Category:  jquery2017/02/15 pops 

前頁のレスポンシブ・スライダーの改造です。コントロールボタン付き(外側)、エンドレスタイプ、サムネール表示の切り替えが出来る様に機能を拡張は同じです。通常のレスポンシブデザインHTML上でも動作します。コントロールボタンが外側についていますので少々メンドウですから余り使用されないようです。

 

responsive

 

TOP画像Slide処理エンドレスタイプ(外側にボタン配置)のテスト

前頁のレスポンシブ・スライダーを、すこし機能拡張しただけで、原則的に構造など代わりはありませんが、コントロールボタンが外側にある為少しメンドウには成ります。
実際に色々作り、その差異を調べてみます。TOP画像としていますが画像幅を縮めれば他の場所でも利用できます。

 

max-widthを使用した形

ここより本題に入ります。レスポンシブにはmax-widthを使用すれば対処できます。下記に構造を示します。
通常「お利口」な方はプラグインなどを利用します。メンドウ故自作する方は居ないと思います。
よって以下、興味のある方のみご覧ください。

 

DEMO

通常のHTML5ページでみてみます。ブラウザ幅を変更して確認ください。

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

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

 

構造と簡単な説明

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

zu

 

以下、デモの html css js と簡単な説明です。position設定の違いによる振る舞いに注意ください。
画像の大きさ計算が違うだけですので、基本的な説明は「前ページ」を参照ください。

【参照】当方の記事: jQuery レスポンシブ・スライダー、エンドレスタイプ


コントロールボタンを常に表示するために、外枠幅が大きくなりますので、それを考慮した画像の大きさ計算をします。


1. 外側はコントロールボタンがある為に大きくなります。(max-width:940px;)
(コントロールボタンを除いた幅を画像幅に割り当て、計算しますので2重手間)
2. 画像と同じ大きさのマスク層をulの上に新規挿入してマスクします。
(画像位置と合わせるため、ここでは中央配置します(30pxずらす方法もある))
3. ul.liはそのまま使用するため、幅の計算時、コントロールボタン幅分引き算して決定します。
4. その他はほとんど「前ページ」と同じスクリプトを使用出来ます。
5. サムネール画像の大きさは、表示状態をみてCSSで決定します。
6. コントロールボタンが画像と重ならないため、マチガイなく認識出来るのが最大の特徴かも...
7. 画像部分が小さくなりがちですからスマートフォンでは見づらい(敬遠される一因か...)。
8. 一応作り方を習得して於けば何らかの役に立つ時もあるでしょう。


● コントロールボタン幅は常に同じ

zuzu

 

ブラウザ幅を縮小しても、スマートフォンでの表示でも、コントロールボタン幅は常に同じに成ります。(コントロールのマークを背景画像で設定しているのが最大の理由で有り、背景画像を縮小出来ないが、要素全体にアクション設定出来るのが利点)
それゆえ、スマートフォン表示では画像がより小さく表示されますので、敬遠されがちと思います。
作るのがよりメンドウ故、尚更使用されないとも言えます。


● コントロールボタンは文字でも作れます。(下記は画像です)

zuzuzu

 

コントロールボタンを画像の左右に配置しなければならない法律は有りませんので、テキストで書いても良い訳です。
さすれば、前ページのJSを改造すれば簡単に出来る事です。
或いは、画像そのものを「左右に余白をとって」作れば、左右にコントロールがある様に見せかけるのも可能です。
(実際その様なケースがありますから、皆さん簡単に出来る様考えているのですね)


● 対応ブラウザと検証

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の名前は自由です。一般的にリスト状に下記の様に書くのが好まれます。
他と違って、#sliderBox層は画像より大きくなるため、画像と同じ大きさのマスク層(#baseMask)を間に挿入しています。
この手のスライダーは「A-link」をつけて使用される場合が多いようです。

HTML


<div id="sliderBox">
<div id="baseMask">
 <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>
</div>

サンプルJS CSS

CSS


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

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

/* 本体 */
#sliderBox{
position:relative;
width:940px;
height:380px;
margin:0 auto;
padding:0;
background-color:#cccccc;
}
/* media上書き */
@media screen and (max-width:939px){
	#sliderBox{
		width:100%;
	}
}

/* MASK中央 */
#baseMask{
position:relative;
width:880px
height:380px;
margin:0 auto;
padding:0;
overflow:hidden;
}

#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;
}

/*span構成コントロール外側*/
#sliderBox #base-prev{
display:block;
position:absolute;
top:0;left:0;
width:20px;
height:100%;
margin:0;
padding:0;
background:url('/main/baserhtml/images/arrow_left_a3.png') no-repeat center center;
cursor:pointer;
z-index:100;
}
#sliderBox #base-next{
display:block;
position:absolute;
top:0;right:0;
width:20px;
height:100%;
margin:0;
padding:0;
background:url('/main/baserhtml/images/arrow_right_a3.png') no-repeat center center;
cursor:pointer;
z-index:101;
}

/* 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;
}

#btnBox span img{
width:40px;/*40x18*/
height:18px;
border:#fff 1px solid;
}
#btnBox span img.active{
border:#f00 1px solid;
}

JS


//simple-slider5.js
//画像slider、通常処理形式エンドレスタイプ
//コントロールを外側配置
//IE7スクロールOK

(function($){

  $(function(){

    function init(){

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

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

	//コントロールBTNの使用、trueのこと
	var ctrlbtn_use=true;
	var ctrl_w=30;//コントロール幅0以上
	//エンドレスタイプ、true
	var endless=true;
	//BTNグループの使用true、不使用false
	var hitbtn_use=true;
	//サムネール使用、ボタンはfalse
	var thumb_use=true;
	//サムネールの大きさはCSSで設定

	//オブジェクト
	var box_elm_wrap=$('#sliderBox');
	var mask_elm=$('#baseMask');
	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;
	var slideflag=true;//左右
	var endless_elm;
	var key_name="";

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

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

	//liエレメント追加
	if(endless){
		box_elm.append('<li id="endless" class="image-parts"><a href="javascript:void(0);"><img /></a></li>');
		endless_elm=$('#endless');
		var url=img_elm.eq(0).find("a").children("img").attr('src');
		endless_elm.find("a").children("img").attr('src',url);
		img_elm=box_elm.children("li");//再認識させる
	}

	//URL取得位置計算
	box_elm.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/span構成
	if(ctrlbtn_use){

		//append #sliderBase
		box_elm_wrap.append('<span id="base-prev"></span>');
		box_elm_wrap.append('<span id="base-next"></span>');

		//オブジェクト
		var next_elm=$('#base-next');
		var prev_elm=$('#base-prev');

		//click-action
		next_elm.click(function(){
			//アニメ中はキャンセル
			if(animeflag){return false}
			//タイマーclear
			clearTimeout(timerID);
			next_set();
			return false
		});
		prev_elm.click(function(){
			//アニメ中はキャンセル
			if(animeflag){return false}
			//タイマーclear
			clearTimeout(timerID);
			prev_set();
			return false
		});

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

		//後ろにappendする
		box_elm_wrap.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;
			if(thumb_use){
				thumb='<img class="thumb" src="'+ image_urls[i] +'" />';
				btnhtml += '<span id="' + name +'">' + thumb + '</span>';
			}else{
				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に
		if(hitbtn_use){
			if(thumb_use){
				hit_btns[0].children("img").addClass('active');
			}else{
				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){
			if(thumb_use){
				hit_btns[keep_no].children("img").removeClass('active');
			}else{
				hit_btns[keep_no].removeClass('active');
			}
		}

		var pos_x=width_v*image_no;

		//endless事前処理
		if(endless){
			var endless_pos=slide_pos[image_max];
			if(key_name=='next'){pos_x=endless_pos;}
			if(key_name=='prev'){pos_x=width_v*image_no;box_elm.css({'left':-endless_pos});}
		}

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

			//endless
			if(endless){
				if(key_name=='next'){box_elm.css({'left':0});}
			}

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

			if(hitbtn_use){
				if(thumb_use){
					hit_btns[image_no].children("img").addClass('active');
				}else{
					hit_btns[image_no].addClass('active');
				}
			}

			set_timer();

		});

	}

	//次ぎの開く要素を計算
	function next_set() {
		if(image_no==image_max-1){key_name="next";}
		slideflag=true;
		//次ぎの番号
		image_no +=1;
		if (image_no > (image_max-1)) {image_no=0;}
		effectImage();
	}
	//戻る要素を計算
	function prev_set() {
		if(image_no==0){key_name="prev";}
		slideflag=false;
		//戻る番号
		image_no -=1;
		if (image_no < 0) {image_no=image_max-1;}
		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();
		var all_w=image_w+ctrl_w*2;//全体の横幅

		//BOX全体の横幅で判定、画像修正
		if(window_width<all_w){

			all_w=window_width;
			var w=window_width-ctrl_w*2;
			var ratio=w/image_w;
			var h=image_h*ratio;
			var ul_w=w*image_max;
			if(endless){ul_w=w*(image_max+1);}

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

			//外幅決めた方がスムーズ
			box_elm_wrap.css({'width':window_width,'height':h});
			mask_elm.css({'width':w,'height':h});
			box_elm.css({'width':ul_w,'height':h});

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

		}else{

			all_w=image_w+ctrl_w*2;
			var ul_w=image_w*image_max;
			if(endless){ul_w=image_w*(image_max+1);}
			//現在の大きさ
			width_v=image_w;
			height_v=image_h;

			//外幅決めた方がスムーズ
			box_elm_wrap.css({'width':all_w,'height':image_h});
			mask_elm.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;
		if(endless){maxlen=image_max+1;}
		//移動位置再計算
		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でした。

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


#wrappr{
overflow:hidden;
}

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

media screen設定を上書きすれば、直りますが...

@media screen設定の場合。

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

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


● max-width設定の場合


max-width設定の場合、空白がでる

#sliderBox{
position:relative;
max-width:940px;
height:380px;
margin:0 auto;
padding:0;
background-color:#cccccc;
}

空白除去のため必要です
#wrappr{
overflow:hidden;
}

● @media screen設定の場合 (デモはこちらを設定しました)


@media screen設定の場合、空白が出ない

#sliderBox{
position:relative;
width:940px;
height:380px;
margin:0 auto;
padding:0;
background-color:#cccccc;
}
/* media上書き */
@media screen and (max-width:939px){
	#sliderBox{
		width:100%;
	}
}

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

処理の相違点

基本的に前ページのJSとほぼ同じになります。相違点をあげれば、幅判定とMASK処理位になります。

● 幅判定の相違

画像幅にコントロールボタン幅を加えた全体の幅での判定になります。画像幅はコントロールボタン幅を引いた値になります。


var all_w=image_w+ctrl_w*2;//全体の横幅

//BOX全体の横幅で判定、画像修正
if(window_width<all_w){

	//各種処理

}else{

	//各種処理

}

● MASK処理

MASK処理はposition:absoluteでもposition:relativeでも設定可能です。デモでは、relativeで中央に配置しています。
IE系はマスクの大きさを設定しないと、機能しない場合が多いので注意。

中央配置です、どちらもマスク機能は同じになります。幅を変化させたい場合は便利かも知れません


/* MASK */
#baseMask{
position:relative;
width:880px
height:380px;
margin:0 auto;
padding:0;
overflow:hidden;
}

absoluteで30pxずらしています。幅を変化させた場合はCSS訂正が必要になります。


/* MASK */
#baseMask{
position:absolute;
top:0;left:30px;
width:880px
height:380px;
margin:0;
padding:0;
overflow:hidden;
}

● コントロールBTNの使用

コントロールBTNの使用のJSですからtrueで使用しますが、仮にfalse設定ではボタンが生成されませんので、画像両側が余白になります。下記のコントロール幅は片側の幅になります。
コントロール幅は0以上取りますが、中央配置マスクの場合で幅0は画像の内側にボタンが配置されます。


//コントロールBTNの使用、trueのこと
var ctrlbtn_use=true;
var ctrl_w=30;//コントロール幅0以上

JS最後の遅延処理

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


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

 

使用画像

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


透過PNG画像、下に来る画像の色合いによっては認識しづらい場合が有ります。下は自作品で、品質は良くない。
別画像の必要なかたは自作するか、ネット上でプラグイン付属画像をパクッテください。

透過画像 透過画像 透過画像 透過画像 透過画像 透過画像 透過画像 20x20透過画像
---


基本的な説明は「前ページ」などを参照ください。処理などはほぼ同じです。

【参照】当方の記事: jQuery レスポンシブ・スライダー、エンドレスタイプ

【参照】当方の記事: jQuery レスポンシブスライダー処理


 

モット効率的な方法もあるかも知れませんが、まだ判りません。誰か考えてください。
今回はコントロールボタンを画像外側に表示しました。簡単ですが、以上です。

 


[ この記事のURL ]


タグ:jquery , Slider , css3 , html5

 

ブログ記事一覧

年別アーカイブ一覧



[1]