マウスドラッグによる要素並び替え検討③

概要

先回までの投稿で要素をマウスドラッグで移動させる確認をしました。今回は並び替えについて確認します。何が違うかというと先回までは適当に移動させていたので、かえって移動させることで順番が判らなくなっていましたが、今回は移動後に要素を自動整列させるので、順番が明確にわかる様になっています。
div 要素と img 要素の並び替えを行っています。

div 要素並び替え

下の図が、div 要素の並び替えの状態です。上段がページを開いた時、下段が並び替え後です。下段は並び替え後ですが、各要素は重なりもすき間もなく、整列配置しています。
要素をマウスドラッグで移動させると、移動先下にある要素の前になる様に全要素を再配置します。
(→ div 要素並び替えプログラムへのリンク 

プログラムについては細かく書きませんが、ドラッグした要素を認識し、認識した要素のドラッグ中の座標から順番を計算し、再配置する様なイメージです。

<!doctype html>
<html lang="ja">

<head>
    <meta charset="utf-8">

    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>DRAG & DROP</title>

    <style>
	* { margin:0; }
	.div_dragbl { cursor:move; position:absolute; }
    </style>

    <script type="text/javascript">

	var mv_fg=""; 
	var mvs_x=0; var mvs_y=0;
	var tgt_id_no; var z_idx_ini=100;
	var X_STT_P=0; var Y_STT_P=100;
	var img_wdt=100; var img_hgt=70;
	var max_fnm=0; var row_num=0; var fct_num=0;
	var index_bef ; var index_cur ;
	var elm_order = [] ;
	var elm_chodr = [] ;

	// ◆初期設定◆
	function init_chk(){
	    get_window_info() ;
	    check_elements_order("0") ; 
	}

	// ◆マウスダウン◆
	window.onmousedown = function(e) {
	    tgt_id_no = event.target.id ;
	    event.stopPropagation();

	    if(tgt_id_no) {
		mv_fg = "true" ; z_idx_ini = z_idx_ini + 1 ;
		document.getElementById(tgt_id_no).style.zIndex = z_idx_ini ;
		mvs_x = event.clientX - parseInt(document.getElementById(tgt_id_no).style.left.replace("px","")) ;
		mvs_y = event.clientY - parseInt(document.getElementById(tgt_id_no).style.top.replace("px","")) ;
	
		var cur_x = event.clientX - mvs_x ; var cur_y = event.clientY - mvs_y ;	// 対象要素基準座標(左上)
		index_bef = get_index_num_by_pos( cur_x , cur_y ) ;
	    }
	}

	// ◆マウスムーブ◆
	window.onmousemove = function(e) {
	    if(mv_fg == "true" && tgt_id_no) {
		var cur_x = event.clientX - mvs_x ; var cur_y = event.clientY - mvs_y ;	// 対象要素基準座標(左上)
		index_cur = get_index_num_by_pos( cur_x , cur_y ) ;

		document.getElementById(tgt_id_no).style.left = cur_x + "px" ;
		document.getElementById(tgt_id_no).style.top = cur_y + "px"  ;

		if(index_cur >= 0){ check_elements_order("1") ; }
	    }
	}

	// ◆マウスアップ◆
	window.onmouseup = function(e) { 
	    mv_fg = "false" ; tgt_id_no = "" ; 

	    // 順番確定
	    if(index_cur >= 0){
	    	elm_order = [] ;
	    	for(var i=0 ; elm_chodr.length > i ; i++) { elm_order[i] = elm_chodr[i] ; }
	    }

	    for(var i=0 ; elm_order.length > i ; i++) {
		var cur_lin = Math.floor( i / max_fnm ) ;
		var cur_row = i - cur_lin * max_fnm ;
		document.getElementById(elm_order[i]).style.left = X_STT_P + cur_row * img_wdt + "px" ;
		document.getElementById(elm_order[i]).style.top = Y_STT_P + cur_lin * img_hgt + "px" ;
	    }
	}

	// ◆ウィンドウリサイズ◆
	window.onresize = function(e) { get_window_info() ; }

	// 対象要素座標からインデックス番号を取得
	function get_index_num_by_pos(cur_x,cur_y){
	    var c_c_x = cur_x + img_wdt /2 ; var c_c_y = cur_y + img_hgt / 2 ;		// 対象要素中心位置
	    var tmp_x = c_c_x - X_STT_P ; var tmp_y = c_c_y - Y_STT_P ;			// 配置基準位置からの座標

	    var x_num=-1 ; var y_num=-1 ; var idx_num=-1;
	    if(tmp_x>0 && max_fnm*img_wdt>tmp_x && tmp_y>0 && (row_num+1)*img_hgt>tmp_y){
		x_num = Math.ceil(tmp_x/img_wdt) ; y_num = Math.ceil(tmp_y/img_hgt) ;
		idx_num = max_fnm * (y_num-1) + x_num -1 ;
	    }
	    return idx_num ;								// 座標から計算したインデックス取得
	}


	// 要素配置初期化
	function get_window_info(){
	    var sW = window.innerWidth ; var sH = window.innerHeight ;			// ウィンドウサイズ
	    var elm_div = document.getElementById("draggable_div") ;			// 移動領域要素取得
	    var rect = elm_div.getBoundingClientRect() ;				// 移動領域取得
	    X_STT_P = Math.ceil(rect.left/10) + 20 ;					// 移動領域座標(X)
	    Y_STT_P = Math.ceil(rect.top/10) + 80 ;					// 移動領域座標(Y)

	    var drg_elm = document.getElementsByClassName("div_dragbl") ;		// 移動対象要素取得
	    var fct_gap = 40 ;								// Windowとのギャップ(両端合計)

	    fct_num = drg_elm.length ;							// 移動対象要素数取得
	    max_fnm = Math.floor((sW-fct_gap)/img_wdt) ;				// 1行最大表示要素数
	    row_num = Math.ceil(fct_num / max_fnm) ;					// 行数表示

	    for(var i=0 ; fct_num > i ; i++){
		var cur_lin = Math.floor( i / max_fnm ) ;
		var cur_row = i - cur_lin * max_fnm ;
		drg_elm[i].style.top = Y_STT_P + cur_lin * img_hgt + "px" ;
		drg_elm[i].style.left = X_STT_P + cur_row * img_wdt + "px" ;

		drg_elm[i].style.width = img_wdt + "px" ;
		drg_elm[i].style.height = img_hgt + "px" ;
		drg_elm[i].style.zIndex = z_idx_ini ;
		drg_elm[i].innerHTML = drg_elm[i].id ;
	    }
	}

	// 要素配置確認
	function check_elements_order(cmd_no) {

	    if(cmd_no=="0"){
		// 初回呼び出し時
		var drg_elm = document.getElementsByClassName("div_dragbl") ;		// 移動対象要素取得
		elm_order = [] ;
		for(var i=0 ; drg_elm.length > i ; i++){
		    elm_order.push(drg_elm[i].id);
	        }
	    }else{
		// 要素移動途中(配列順序の更新) ※ index_bef , index_cur に基づき更新
		elm_chodr = [] ;
		for(var i=0 ; elm_order.length > i ; i++){
		    if(i==index_cur){ elm_chodr.push(tgt_id_no); }
		    if(tgt_id_no!=elm_order[i]){ elm_chodr.push(elm_order[i]); }
		}
		if(index_cur>fct_num-1){ elm_chodr.push(tgt_id_no); }
	    }
	}

    </script>
</head>

<body onLoad="init_chk()">

	<div id="draggable_div" style="position:relative ; clear:both;">

	<?php
	    for($ii=0; $ii<20 ;$ii++){
		$id_no = substr("000000".strval($ii+1),-6) ;
		$cl_cd = '#'.str_pad(dechex(mt_rand(0, 0xFFFFFF)), 6, '0', STR_PAD_LEFT) ;
		echo '<div class="div_dragbl" id="'.$id_no.'" style="left:0px; top:0px; background-color:'.$cl_cd.';"></div>' ;
	    }
	?>
	
	</div>

	<div id="div_order" style="position:relative ; float:left;"></div>
	<div id="div_chodr" style="position:relative ; float:left;"></div>
</body> 

</html>

 

img 要素並び替え

次の図は、div 要素ではなく、img 要素で同様のことを行った例です。基本構成は同じですが、img 要素部のHTMLはPHPでサーバー側の特定フォルダ―内の画像ファイル(ping)を検索し、自動出力しています。PHPで要素部分を出力することで、データベースファイルよる画像管理などの応用も可能と考えています。
(→ div 要素並び替えプログラムへのリンク 
div 要素と比較し、img 要素はドラッグによる動きが異なり、最初動きが非常に悪かったのですが、行番38を追加することで滑らかな動きになりました。

<!doctype html>
<html lang="ja">

<head>
    <meta charset="utf-8">

    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>DRAG & DROP</title>

    <style>
	* { margin:0; }
	.div_dragbl { cursor:move; position:absolute; }
    </style>

    <script type="text/javascript">

	var mv_fg=""; 
	var mvs_x=0; var mvs_y=0;
	var tgt_id_no; var z_idx_ini=100;
	var X_STT_P=0; var Y_STT_P=100;
	var img_wdt=100; var img_hgt=100;
	var max_fnm=0; var row_num=0; var fct_num=0;
	var index_bef ; var index_cur ;
	var elm_order = [] ;
	var elm_chodr = [] ;

	// ◆初期設定◆
	function init_chk(){
	    get_window_info() ;
	    check_elements_order("0") ; 
	}

	// ◆マウスダウン◆
	window.onmousedown = function(e) {
	    mv_fg = "true" ;
	    tgt_id_no = event.target.id ;

	    event.preventDefault();  							// ◆重要◆ img要素移動時必須
	    event.stopPropagation();

	    if(tgt_id_no) {
		z_idx_ini = z_idx_ini + 1 ;
		document.getElementById(tgt_id_no).style.zIndex = z_idx_ini ;
		mvs_x = event.clientX - parseInt(document.getElementById(tgt_id_no).style.left.replace("px","")) ;
		mvs_y = event.clientY - parseInt(document.getElementById(tgt_id_no).style.top.replace("px","")) ;
	
		var cur_x = event.clientX - mvs_x ; var cur_y = event.clientY - mvs_y ;	// 対象要素基準座標(左上)
		index_bef = get_index_num_by_pos( cur_x , cur_y ) ;
		document.getElementById("idx_bf").innerHTML = index_bef ;
	    }

	}

	// ◆マウスムーブ◆
	window.onmousemove = function(e) {
	    if(mv_fg == "true" && tgt_id_no) {
		var cur_x = event.clientX - mvs_x ; var cur_y = event.clientY - mvs_y ;	// 対象要素基準座標(左上)
		index_cur = get_index_num_by_pos( cur_x , cur_y ) ;

		document.getElementById(tgt_id_no).style.left = cur_x + "px" ;
		document.getElementById(tgt_id_no).style.top = cur_y + "px"  ;

		if(index_cur >= 0){ check_elements_order("1") ; }
	    }
	}

	// ◆マウスアップ◆
	window.onmouseup = function(e) {
	    if(mv_fg == "true" && tgt_id_no) {
	    	mv_fg = "false" ; tgt_id_no = "" ; 

	    	// 順番確定
	    	if(index_cur >= 0){
	    	    elm_order = [] ;
	    	    for(var i=0 ; elm_chodr.length > i ; i++) { elm_order[i] = elm_chodr[i] ; }
	    	}

	    	for(var i=0 ; elm_order.length > i ; i++) {
		    var cur_lin = Math.floor( i / max_fnm ) ;
		    var cur_row = i - cur_lin * max_fnm ;
		    document.getElementById(elm_order[i]).style.left = X_STT_P + cur_row * img_wdt + "px" ;
		    document.getElementById(elm_order[i]).style.top = Y_STT_P + cur_lin * img_hgt + "px" ;
	    	}
	    }
	}

	// ◆ウィンドウリサイズ◆
	window.onresize = function(e) { get_window_info() ; }


	// 対象要素座標からインデックス番号を取得
	function get_index_num_by_pos(cur_x,cur_y){
	    var c_c_x = cur_x + img_wdt /2 ; var c_c_y = cur_y + img_hgt / 2 ;		// 対象要素中心位置
	    var tmp_x = c_c_x - X_STT_P ; var tmp_y = c_c_y - Y_STT_P ;			// 配置基準位置からの座標

	    var x_num=-1 ; var y_num=-1 ; var idx_num=-1;
	    if(tmp_x>0 && max_fnm*img_wdt>tmp_x && tmp_y>0 && (row_num+1)*img_hgt>tmp_y){
		x_num = Math.ceil(tmp_x/img_wdt) ; y_num = Math.ceil(tmp_y/img_hgt) ;
		idx_num = max_fnm * (y_num-1) + x_num -1 ;
	    }

	    return idx_num ;								// 座標から計算したインデックス取得
	}


	// 要素配置初期化
	function get_window_info(){
	    var sW = window.innerWidth ; var sH = window.innerHeight ;			// ウィンドウサイズ
	    var elm_div = document.getElementById("draggable_div") ;			// 移動領域要素取得
	    var rect = elm_div.getBoundingClientRect() ;				// 移動領域取得
	    X_STT_P = Math.ceil(rect.left/10) + 20 ;					// 移動領域座標(X)
	    Y_STT_P = Math.ceil(rect.top/10) + 80 ;					// 移動領域座標(Y)

	    var drg_elm = document.getElementsByClassName("div_dragbl") ;		// 移動対象要素取得
	    var fct_gap = 40 ;								// Windowとのギャップ(両端合計)

	    fct_num = drg_elm.length ;							// 移動対象要素数取得
	    max_fnm = Math.floor((sW-fct_gap)/img_wdt) ;				// 1行最大表示要素数
	    row_num = Math.ceil(fct_num / max_fnm) ;					// 行数表示

	    for(var i=0 ; fct_num > i ; i++){
		var cur_lin = Math.floor( i / max_fnm ) ;
		var cur_row = i - cur_lin * max_fnm ;
		drg_elm[i].style.top = Y_STT_P + cur_lin * img_hgt + "px" ;
		drg_elm[i].style.left = X_STT_P + cur_row * img_wdt + "px" ;

		drg_elm[i].style.width = img_wdt + "px" ;
		drg_elm[i].style.height = img_hgt + "px" ;
		drg_elm[i].style.zIndex = z_idx_ini ;
		drg_elm[i].innerHTML = drg_elm[i].id ;
	    }

	}

	// 要素配置確認
	function check_elements_order(cmd_no) {

	    if(cmd_no=="0"){
		// 初回呼び出し時
		var drg_elm = document.getElementsByClassName("div_dragbl") ;		// 移動対象要素取得
		elm_order = [] ;
		for(var i=0 ; drg_elm.length > i ; i++){
		    elm_order.push(drg_elm[i].id);
	        }
	    }else{
		// 要素移動途中(配列順序の更新) ※ index_bef , index_cur に基づき更新
		elm_chodr = [] ;
		for(var i=0 ; elm_order.length > i ; i++){
		    if(i==index_cur){ elm_chodr.push(tgt_id_no); }
		    if(tgt_id_no!=elm_order[i]){ elm_chodr.push(elm_order[i]); }
		}
		if(index_cur>fct_num-1){ elm_chodr.push(tgt_id_no); }
	    }
	}

    </script>
</head>

<body onLoad="init_chk()">
	<div id="draggable_div" style="position:relative ; clear:both;">
	<?php
	    $serch_file = glob("../1901002_js_sortable/img_vegetables/*.png") ;
	    for($ii=0; $ii<count($serch_file) ;$ii++){
		$id_no = substr("000000".strval($ii+1),-6) ;
		echo '<img src="'.$serch_file[$ii].'" class="div_dragbl" id="'.$id_no.'" title="TEST" style="width:100px; height:100px; border:solid 1px #000000;">' ;
	    }
	?>
	</div>

	<div id="div_order" style="position:relative ; float:left;"></div>
	<div id="div_chodr" style="position:relative ; float:left;"></div>
</body> 

</html>

 

まとめ

次回は、サムネイル画像の作り方を確認し、並び替え画像に追加する方法を検討してみようかと考えています。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です