正六面体上をクリックして回すJavaScriptの例です。
参考1:角度から座標を求める計算式
X座標 = 半径 * Math.cos(Y軸角度 / 180 * Math.PI)
Y座標 = 半径 * Math.sin(X軸角度 / 180 * Math.PI)
注)Y軸角度は-90°から90°の指定となる。また、X軸角度は-180°から180°の指定となる。
参考2:座標から角度を求める計算式
X角度 = Math.asin(Y座標 / 半径 / Math.PI * 180)
Y角度 = Math.acos(X座標 / 半径 / Math.PI * 180)
注)Math.asinの計算値が-90°から90°以外はNaNとなる。また、Math.acosの計算値が-180°から180°以外はNaNとなる。
1、クリックされた時点の座標から角度を求める。
2、前回クリックが離された時点の角度を求める。
3、移動された座標から角度を求める。
4、「移動された角度」から「クリックされた時点の角度」を引き「前回クリックが離された角度」を足す。
この計算で、今回動す角度が決定される。
注)マウスの移動方向と回転方向は相対関係となるので、回転値も相対値を取る。
↓以下がテストのソースサンプルです。
▼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; var angleX_Out = -20; var angleY_Out = -20; var flgMove = false; var flgOut = true; // ------------------------------------------------------------ // クリック時に実行される関数 // ------------------------------------------------------------ function MouseDownFunc(e){ if (!flgMove){ flgMove = true; xb = e.clientX; yb = e.clientY; var gapX = Math.round(((xb - xa) * 1000 ) / 1000); var gapY = Math.round(((yb - ya) * 1000 ) / 1000); angleX_B = 0 - Math.round(Math.asin(gapY / r) / Math.PI * 180 *1000) / 1000; if ( isNaN(angleX_B)){angleX_B = 0}; angleY_B = 0 - Math.round(Math.acos(gapX / r) / Math.PI * 180 *1000) / 1000; if ( isNaN(angleY_B)){angleY_B = 0}; } } // ------------------------------------------------------------ // クリックが離された時に実行される関数 // ------------------------------------------------------------ function MouseUpFunc(e){ flgMove = false; angleX_A = angleX; angleY_A = angleY; } function MouseUpEventFunc(w){ flgMove = false; angleX_A = angleX; angleY_A = angleY; } // ------------------------------------------------------------ // マウスオーバー時に実行される関数 // ------------------------------------------------------------ function MouseOverFunc(e){ flgOut = true; } // ------------------------------------------------------------ // マウスカーソルが移動するたびに実行される関数 // ------------------------------------------------------------ function MouseMoveFunc(e){ if(flgMove){ RotateFunc(e); } } // ------------------------------------------------------------ // マウスアウト時に実行される関数 // ------------------------------------------------------------ function MouseOutFunc(e){ flgOut = false; } // ------------------------------------------------------------ // マウス移動時に角度を求める関数 // ------------------------------------------------------------ function RotateFunc(e){ // カーソル位置を求める var xc = e.clientX; var yc = e.clientY; // 回転率を求める var gapX = Math.round(((xc - xa) * 1000 ) / 1000) % r; var gapY = Math.round(((yc - ya) * 1000 ) / 1000) % r; angleX_C = 0 - Math.round(Math.asin(gapY / r) / Math.PI * 180 *1000) / 1000; if ( isNaN(angleX_C)){angleX_C = 0}; angleY_C = 0 - Math.round(Math.acos(gapX / r) / Math.PI * 180 *1000) / 1000; if ( isNaN(angleY_C)){angleY_C = 0}; // クリックされた角度から移動された角度を引き元の角度を足す angleX = (angleX_C - angleX_B + angleX_A); angleY = (angleY_C - angleY_B + angleY_A); // 図形を回転させる 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}; } // ------------------------------------------------------------ // イベントのリッスンを開始する // ------------------------------------------------------------ // イベントリスナーに対応している if(element.addEventListener){ // マウス押下時に実行されるイベント // element.addEventListener("click" , MouseDownFunc); // クリックを離した時に実行されるイベント // 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("onClick" , MouseDownFunc); // クリックを離した時に実行されるイベント // element.attachEvent("onmouseup" , MouseUpFunc); // マウス押下時に実行されるイベント element.attachEvent("onmousedown" , MouseDownFunc); // マウスオーバー時に実行されるイベント element.attachEvent("onmouseover" , MouseOverFunc); // マウスカーソルが移動するたびに実行されるイベント element.attachEvent("onmousemove" , MouseMoveFunc); // マウスカーソルが図形から外れるたびに実行されるイベント // element.attachEvent("onmouseout" , MouseOutFunc); } // ------------------------------------------------------------ // イベントのリッスンを開始する // ------------------------------------------------------------ // イベントリスナーに対応している if(window.addEventListener){ // マウスボタンを押すと実行されるイベント // window.addEventListener("mousedown" , MouseDownEventFunc); // マウスカーソルを移動するたびに実行されるイベント // window.addEventListener("mousemove" , MouseMoveEventFunc); // マウスボタンを離すと実行されるイベント window.addEventListener("mouseup" , MouseUpEventFunc); // アタッチイベントに対応している }else if(document.attachEvent){ // マウスボタンを押すと実行されるイベント // 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%; } #main { margin:200px 200px; } #cube { margin:0; position: relative; transform-style: preserve-3d; transform-origin:100px 100px; 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; } #front { transform: rotateY(0deg) translateZ(100px); background:red;/*赤*/ opacity: 0.6; } #back { transform: rotateX(180deg) translateZ(100px); background:pink;/*ピンク*/ opacity: 0.6; } #right{ transform: rotateY(90deg) translateZ(100px); background:blue;/*青*/ opacity: 0.6; } #left { transform: rotateY(-90deg) translateZ(100px); background:skyblue;/*水色*/ opacity: 0.6; } #top { transform: rotateX(90deg) translateZ(100px); background:green;/*緑*/ opacity: 0.6; } #bottom { transform: rotateX(-90deg) translateZ(100px); background:yellow;/*黄色*/ opacity: 0.6; } </style>
▼HTML
<div id="wrap"> <!-- 正六面体 --> <div id="main"> <div id="cube"> <svg class="surface" id="front" viewBox="-100 -100 200 200" > <rect x="-100" y="-100" width="200" hight="200"></rect> <text x="-50" y="40">1</text> </svg> <svg class="surface" id="back" viewBox="-100 -100 200 200" > <rect x="-100" y="-100" width="200" hight="200"></rect> <text x="-50" y="40">2</text> </svg> <svg class="surface" id="right" viewBox="-100 -100 200 200" > <rect x="-100" y="-100" width="200" hight="200"></rect> <text x="-50" y="40">3</text> </svg> <svg class="surface" id="left" viewBox="-100 -100 200 200" > <rect x="-100" y="-100" width="200" hight="200"></rect> <text x="-50" y="40">4</text> </svg> <svg class="surface" id="top" viewBox="-100 -100 200 200" > <rect x="-100" y="-100" width="200" hight="200"></rect> <text x="-50" y="40">5</text> </svg> <svg class="surface" id="bottom" viewBox="-100 -100 200 200" > <rect x="-100" y="-100" width="200" hight="200"></rect> <text x="-50" y="40">6</text> </svg> </div> </div> </div>