図形外でダブルクリックすると移動出来る様になる


図形以外の領域でダブルクリックすると図形が移動できる様になる。
また、ダブルクリックすると図形の回転ができる様になる。
移動と回転をダブルクリックで切り替える。

JavaScript部分の「イベントのリッスンを開始する(Window)」と
「ダブルクリック時に実行される関数」との定義で切替えている。

↓以下がテストのソースサンプルです。

▼JavaScript

<script type="text/javascript">
// 匿名関数内で実行
window.onload = function (){

	// 各エレメントを取得
	var element = document.getElementById("cube");
	var bounds = element.getBoundingClientRect();
	var r = 100;
	var xa = bounds.left + r;
	var ya = bounds.top + r;
	var angleX = -20;
	var angleY = -20;
	//前回値(角度)
	var angleX_A = -20;
	var angleY_A = -20;
	//クリック時点(角度)
	var angleX_B = 0;
	var angleY_B = 0;
	//移動時点(角度)
	var angleX_C = 0;
	var angleY_C = 0;
	//*180°反転対応
	var angleX_R = 0;
	var angleY_R = 0;

	var flgMove = false;
	var flgOut = false;
	//*回転移動スイッチ
	var flgRD = true;
	
	document.querySelector("#reset").onclick = function () {location.reload()};
	// ------------------------------------------------------------
	// ダブルクリック時に実行される関数
	// ------------------------------------------------------------
	function ModeFunc(w){
		if (flgRD) { flgRD = false } else { flgRD = true};
		if (flgRD) {
			document.getElementById("mode").textContent = "モード:回転モード";
			document.getElementById("cube").style.opacity = "1.0";
		}
		if (!flgRD){
			document.getElementById("mode").textContent = "モード:移動モード";
			document.getElementById("cube").style.opacity = "0.6";
		}
	}
	// ------------------------------------------------------------
	// クリック時に実行される関数
	// ------------------------------------------------------------
	function MouseDownFunc(e){
		if (flgRD) {
			if (!flgMove){
				flgMove = true;
				angleX_R = 0;
				angleY_R = 0;
				xb = e.clientX;
				yb = e.clientY;
				
				//角度Y
				var gapX = (xb - xa) / r;
				gapX = Math.round((gapX) * 1000) / 1000;
				var gapXB = Math.floor(gapX);
				if (gapX < 0){gapXB = gapXB + 1};
				angleY_B = (gapXB * 90) + 90;
				gapX = gapX - gapXB;
				angleY_B = (Math.asin(gapX) / Math.PI * 180 + angleY_B) % 360;
				if ( isNaN(angleY_B)){angleY_B = 0};
				
				//角度X
				var gapY = (yb - ya) / r;
				gapY = Math.round((gapY) * 1000) / 1000;
				var gapYB = Math.floor(gapY);
				if (gapY < 0){gapYB = gapYB + 1};
				angleX_B = gapYB * 90;
				gapY = gapY - gapYB;
				angleX_B = - (Math.asin(gapY) / Math.PI * 180 + angleX_B) % 360;
				if ( isNaN(angleX_B)){angleX_B = 0};
			}
		} else {
			flgOut = true;
		}
	}
	// ------------------------------------------------------------
	// クリックが離された時に実行される関数
	// ------------------------------------------------------------
	function MouseUpFunc(e){
		flgMove = false;
		angleX_A = angleX;
		angleY_A = angleY;
	}
	function MouseUpEventFunc(w){
		if (flgRD) {
			if (flgMove) {
				flgMove = false;
				angleX_A = angleX;
				angleY_A = angleY;
			}
		}
		if (!flgRD){
			if (flgOut) {
				DropFunc(w)
				flgOut = false;
			}
		}
	}
	
	// ------------------------------------------------------------
	// マウスオーバー時に実行される関数
	// ------------------------------------------------------------
	function MouseOverFunc(e){
	}

	// ------------------------------------------------------------
	// マウスカーソルが移動するたびに実行される関数
	// ------------------------------------------------------------
	function MouseMoveFunc(e){
		if (flgRD){
			if (flgMove){
				RotateFunc(e);
			}
		}
	}
	
	// ------------------------------------------------------------
	// マウスアウト時に実行される関数
	// ------------------------------------------------------------
	function MouseOutFunc(e){
	}

	// ------------------------------------------------------------
	// マウス移動時に角度を求める関数
	// ------------------------------------------------------------
	function RotateFunc(e){
//		カーソル位置を求める		
		var xc = e.clientX;
		var yc = e.clientY;
//		回転率を求める
		//角度Y
		var gapX = (xc - xa) / r;
		gapX = Math.round((gapX) * 1000) / 1000;
		var gapXC = Math.floor(gapX);
		if (gapX < 0){gapXC = gapXC + 1};
		angleY_C = (gapXC * 90) + 90;
		gapX = gapX - gapXC;
		angleY_C = (Math.asin(gapX) / Math.PI * 180 + angleY_C) % 360;
		if ( isNaN(angleY_C)){angleY_C = 0};
		//角度X
		var gapY = (yc - ya) / r;
		gapY = Math.round((gapY) * 1000) / 1000;
		var gapYC = Math.floor(gapY);
		if (gapY < 0){gapYC = gapYC + 1};
		angleX_C = gapYC * 90;
		gapY = gapY - gapYC;
		angleX_C = - (Math.asin(gapY) / Math.PI * 180 + angleX_C) % 360;
		if ( isNaN(angleX_C)){angleX_C = 0};
		
//		クリックされた角度から移動された角度を引き元の角度を足す
		angleX = Math.round((angleX_C - angleX_B + angleX_A) * 1000) / 1000 % 360;
		angleY = Math.round((angleY_C - angleY_B + angleY_A) * 1000) / 1000 % 360;
		//* 反転した場合の基準Y角度
		if (angleX >=-100 && angleX <=100){angleY_R=0};
		if (angleX < -100 && angleY_R==0){angleY_R=angleY_C*2};
		if (angleX > 100 && angleY_R==0){angleY_R=angleY_C*2};
/*		//* 反転した場合の基準X角度
		if (angleY >=-90 && angleY <=90){angleX_R=0};
		if (angleY < -90 && angleX_R==0){angleX_R=angleX_C*2};
		if (angleY > 90 && angleX_R==0){angleX_R=angleX_C*2};
*/
		if (angleY_R != 0){
			angleY = Math.round(((angleY_R - angleY_C) - angleY_B + angleY_A) * 1000) / 1000 % 360;
		}
		if (angleX_R != 0){
			angleX = Math.round(((angleX_R - angleX_C) - angleX_B + angleX_A) * 1000) / 1000 % 360;

		}

//		図形を回転させる
		var AngleRotate =""
		if ( angleX == parseFloat(angleX))
			{AngleRotate = AngleRotate + "rotateX(" + angleX + "deg)"};
		if ( angleY == parseFloat(angleY))
			{AngleRotate = AngleRotate + "rotateY(" + angleY + "deg)"};
		if ( AngleRotate != ""){
			document.getElementById("cube").style.transform = AngleRotate;
		};

	}

	// ------------------------------------------------------------
	// マウス移動時に角度を求める関数
	// ------------------------------------------------------------
	function DropFunc(w){
//		カーソル位置を求める		
		var psLeft = w.clientX;
		var psTop = w.clientY;

//		図形を移動させる
		if ( psLeft != "")
			{document.getElementById("main").style.left = psLeft + "px"};
		if ( psTop != "")
			{document.getElementById("main").style.top = psTop + "px"};

		bounds = element.getBoundingClientRect();
		xa = bounds.left + r;
		ya = bounds.top + r;
		flgOut = true;
	}

	// ------------------------------------------------------------
	// イベントのリッスンを開始する
	// ------------------------------------------------------------
	// イベントリスナーに対応している
	if(element.addEventListener){

		// ダブルクリック時に実行されるイベント
//		element.addEventListener("dblclick" , ModeFunc);
		// クリックを離した時に実行されるイベント
//		element.addEventListener("mouseup" , MouseUpFunc);
		// マウス押下時に実行されるイベント
		element.addEventListener("mousedown" , MouseDownFunc);
		// マウスオーバー時に実行されるイベント
		element.addEventListener("mouseover" , MouseOverFunc);
		// マウスカーソルが移動するたびに実行されるイベント
		element.addEventListener("mousemove" , MouseMoveFunc);
		// マウスアウト時に実行されるイベント
		element.addEventListener("mouseout" , MouseOutFunc);

	// アタッチイベントに対応している
	}else if(element.attachEvent){

		// ダブルクリック時に実行されるイベント
//		element.attachEvent("ondblclick" , ModeFunc);
		// クリックを離した時に実行されるイベント
//		element.attachEvent("onmouseup" , MouseUpFunc);
		// マウス押下時に実行されるイベント
		element.attachEvent("onmousedown" , MouseDownFunc);
		// マウスオーバー時に実行されるイベント
		element.attachEvent("onmouseover" , MouseOverFunc);
		// マウスカーソルが移動するたびに実行されるイベント
		element.attachEvent("onmousemove" , MouseMoveFunc);
		// マウスアウト時に実行されるイベント
		element.attachEvent("onmouseout" , MouseOutFunc);

	}
	// ------------------------------------------------------------
	// イベントのリッスンを開始する(Window)
	// ------------------------------------------------------------
	// イベントリスナーに対応している
	if(window.addEventListener){

		// ダブルクリック時に実行されるイベント
		window.addEventListener("dblclick" , ModeFunc);
		// マウスボタンを押すと実行されるイベント
//			window.addEventListener("mousedown" , MouseDownEventFunc);
		// マウスカーソルを移動するたびに実行されるイベント
//		window.addEventListener("mousemove" , MouseMoveEventFunc);
		// マウスボタンを離すと実行されるイベント
		window.addEventListener("mouseup" , MouseUpEventFunc);

	// アタッチイベントに対応している
	}else if(document.attachEvent){

		// ダブルクリック時に実行されるイベント
		document.attachEvent("ondblclick" , ModeFunc);
		// マウスボタンを押すと実行されるイベント
//		document.attachEvent("onmousedown" , MouseDownEventFunc);
		// マウスカーソルを移動するたびに実行されるイベント
//		document.attachEvent("onmousemove" , MouseUpEventFunc);
		// マウスボタンを離すと実行されるイベント
		document.attachEvent("onmouseup" , MouseUpEventFunc);

	}

};
</script>

▼CSS

<style>
body{
	width: 100%;
	height:100%;
}
#wrap{
	width: 100%;
	height:100%;
	position:relative;
}
#reset{
	margin:30px 30px;
}
#main {
	position:absolute;
	top:200px;
	left:200px;
}
#cube {
	margin:0;
	position: relative;
	transform-style: preserve-3d;
	transform-origin:100px 100px;
	transform: rotateX(-20deg) rotateY(-20deg);
	-webkit-transform-style: preserve-3d;
	-webkit-transform-origin:100px 100px;
	-webkit-transform: rotateX(-20deg) rotateY(-20deg);
	-ms-transform-style: preserve-3d;
	-ms-transform-origin:100px 100px;
	-ms-transform: rotateX(-20deg) rotateY(-20deg);
}
.surface {
	position: absolute;
	left: 0;
	top: 0;
	width: 200px;
 	height: 200px;
	text-align: center;
	line-height: 200px;
	box-sizing: border-box;
	border: 2px solid black;
}
text{
	fill:black;
	font-size:130px;
	user-select: none;
	-moz-user-select: none; /* Firefox */
	-webkit-user-select: none; /* Safari、Chromeなど */
	-ms-user-select: none; /* IE10かららしい */
}
#front {
	transform: rotateY(0deg) translateZ(100px);
	-webkit-transform: rotateY(0deg) translateZ(100px);
	-ms-transform: rotateY(0deg) translateZ(100px);
	background:red;/*赤*/
	opacity: 0.6;

}
#back {
	transform: rotateX(180deg) translateZ(100px);
	-webkit-transform: rotateX(180deg) translateZ(100px);
	-ms-transform: rotateX(180deg) translateZ(100px);
	background:pink;/*ピンク*/
	opacity: 0.6;
}
#right{
	transform: rotateY(90deg) translateZ(100px);
	-webkit-transform: rotateY(90deg) translateZ(100px);
	-ms-transform: rotateY(90deg) translateZ(100px);
	background:blue;/*青*/
	opacity: 0.6;
}
#left {
	transform: rotateY(-90deg) translateZ(100px);
	-webkit-transform: rotateY(-90deg) translateZ(100px);
	-ms-transform: rotateY(-90deg) translateZ(100px);
	background:skyblue;/*水色*/
	opacity: 0.6;
}
#top {
	transform: rotateX(90deg) translateZ(100px);
	-webkit-transform: rotateX(90deg) translateZ(100px);
	-ms-transform: rotateX(90deg) translateZ(100px);
	background:green;/*緑*/
	opacity: 0.6;
}
#bottom {
	transform: rotateX(-90deg) translateZ(100px);
	-webkit-transform: rotateX(-90deg) translateZ(100px);
	-ms-transform: rotateX(-90deg) translateZ(100px);
	background:yellow;/*黄色*/
	opacity: 0.6;
}
</style>

▼HTML

<div id="wrap">
	<p><br></p>
	<p id="mode">モード:回転モード</p>
	<div id="buttonBox">
		<button id="reset">リセット</button>
	</div>
<!-- 正六面体 -->
	<div id="main">
		<div id="cube">
			<svg class="surface" id="front" viewBox="-100 -100 200 200" >
				<g>
					<rect x="-100" y="-100" width="200" hight="200"></rect>
					<text x="-50" y="40">1</text>
				</g>
			</svg>
			<svg class="surface" id="back" viewBox="-100 -100 200 200" >
				<g>
					<rect x="-100" y="-100" width="200" hight="200"></rect>
					<text x="-50" y="40">2</text>
				</g>
			</svg>
			<svg class="surface" id="right" viewBox="-100 -100 200 200" >
				<g>
					<rect x="-100" y="-100" width="200" hight="200"></rect>
					<text x="-50" y="40">3</text>
				</g>
			</svg>
			<svg class="surface" id="left" viewBox="-100 -100 200 200" >
				<g>
					<rect x="-100" y="-100" width="200" hight="200"></rect>
					<text x="-50" y="40">4</text>
				</g>
			</svg>
			<svg class="surface" id="top" viewBox="-100 -100 200 200" >
				<g>
					<rect x="-100" y="-100" width="200" hight="200"></rect>
					<text x="-50" y="40">5</text>
				</g>
			</svg>
			<svg class="surface" id="bottom" viewBox="-100 -100 200 200" >
				<g>
					<rect x="-100" y="-100" width="200" hight="200"></rect>
					<text x="-50" y="40">6</text>
				</g>
			</svg>
		</div>
	</div>
</div>

デモページは、こちら