回転行列の公式(x’ = cosθ * x – sinθ * y, y’ = sinθ * x + cosθ * y)を使って、Canvasに描いたオブジェクトをマウスの方向に回転させる。
オブジェクトをマウスの方向に、回転行列(Rotating Matrix)を使って回転させる(HTML5, JavaScript, CSS3) : デモ
オブジェクトをマウスの方向に、回転行列(Rotating Matrix)を使って回転させる(HTML5, JavaScript, CSS3) : ZIPファイル(6kb)
1.HTML
<!DOCTYPE html> <html lang="jp"> <head> <meta charset="UTF-8" /> <title>マウスの方向に回転行列|Rotate Matrix to Mouse</title> <link href="css/base.css" rel="stylesheet" type="text/css"> <script src="js/base.js"></script> <script src="js/devicecheck.js"></script> </head> <body> <div id="contents"> <canvas id="canvas" width="300" height="300"> </canvas> </div> </body> </html>
2.CSS
@charset "utf-8"; body { margin:0; padding:0; background-color: #fff; font-family:Helvetica, HiraKakuProN-W3, sans-serif; font-size:12px; color:#000; } #contents { position: absolute; top: 0; left: 0; width: 300px; height:300px; border: 1px solid #000; overflow:hidden; } #canvas { position: absolute; top: 0; left: 0; width: 300px; height:300px; }
3.JavaScript
devicecheck.js
var g_mobiledevice = false; //iPhone、iPad、Androidのときtrue var g_browsername = 'unknown'; var g_browserver = -1; if(checkUserAgent() == false) { window.alert('このブラウザは対象外です'); } function checkUserAgent() { var ua = navigator.userAgent; //iPhoneか? var mstr = ua.match(/iPhone OS \d+/); if(mstr != null){ var vstr = mstr[0].match(/\d+/); if(parseInt(vstr[0]) >= 3) { g_mobiledevice = true; g_browsername = 'iPhone'; //alert('major-version ' + vstr); return true; } } //iPadか? if(ua.indexOf('iPad') > -1) { mstr = ua.match(/CPU OS \d+/); if(mstr != null) { var vstr = mstr[0].match(/\d+/); if(parseInt(vstr[0]) >= 3) { g_mobiledevice = true; g_browsername = 'iPad'; //alert('major-version ' + vstr); return true; } } } //Androidか? var mstr = ua.match(/Android \d+\.\d+/); if(mstr != null) { g_browsername = 'Android'; var vstr = mstr[0].match(/\d+\.\d+/); g_browserver = parseFloat(vstr[0]); g_mobiledevice = true; if(pg_browserver > 2.1) { //alert('version ' + vstr); return true; } } //Chromeか? mstr = ua.match(/Chrome\/\d+/); if(mstr != null) { g_browsername = 'Chrome'; var vstr = mstr[0].match(/\d+/); g_browserver = parseInt(vstr[0]); if(g_browserver >= 9) { //alert('major-version ' + vstr); return true; } } //Safariか? if(ua.indexOf('Safari') > -1) { mstr = ua.match(/Version\/\d+/); if(mstr != null){ var vstr = mstr[0].match(/\d+/); if(parseInt(vstr[0]) >= 5) { g_browsername = 'Safari'; //alert('major-version ' + vstr); return true; } } } //Internet Explorerか? mstr = ua.match(/MSIE \d+/); if(mstr != null) { var vstr = mstr[0].match(/\d+/); if(parseInt(vstr[0]) >= 9) { g_browsername = 'MSIE'; //alert('major-version ' + vstr); return true; } } //Firefoxか? mstr = ua.match(/Firefox\/\d+/); if(mstr != null){ var vstr = mstr[0].match(/\d+/); if(parseInt(vstr[0]) >= 4) { g_browsername = 'Firefox'; //alert('major-version ' + vstr); return true; } } //Operaか? if(ua.indexOf('Opera') > -1) { mstr = ua.match(/Version\/\d+/); if(mstr != null){ var vstr = mstr[0].match(/\d+/); if(parseInt(vstr[0]) >= 11) { g_browsername = 'Opera'; //alert('major-version ' + vstr); return true; } } } return false; }
base.js
window.addEventListener("load", init, false); var centerX; var centerY; var theCanvas; var ctx; var currentX0; var currentY0; var currentX1; var currentY1; var currentX2; var currentY2; var points = new Array(); var mouseX; var mouseY; function init() { document.getElementById('canvas').addEventListener('touchstart', function() { event.preventDefault(); }); document.getElementById('canvas').addEventListener('touchmove', function() { event.preventDefault(); }); document.getElementById('canvas').addEventListener('touchend', function() { event.preventDefault(); }); //ボタンタイプ if(g_mobiledevice==true) { buttonStart = 'touchstart'; buttonMove = 'touchmove'; buttonEnd = 'touchend'; } else { buttonStart = 'mousedown'; buttonMove = 'mousemove'; buttonEnd = 'mouseup'; } theCanvas = document.getElementById("contents"); centerX = (theCanvas.currentStyle || document.defaultView.getComputedStyle(theCanvas,'')).width; centerX = Number(centerX.replace('px','')); centerX = centerX / 2; centerY = (theCanvas.currentStyle || document.defaultView.getComputedStyle(theCanvas,'')).height; centerY = Number(centerY.replace('px','')); centerY = centerY / 2; theCanvas = document.getElementById("canvas"); theCanvas.addEventListener(buttonMove, mouseDownHandler, false); function mouseDownHandler(e) { if(g_mobiledevice) { var rect = event.currentTarget.getBoundingClientRect(); mouseX = event.touches[0].pageX - rect.left - centerX; mouseY = event.touches[0].pageY - rect.top - centerY; } else if(g_browsername == 'MSIE' || g_browsername == 'Opera') { rect = document.getElementById("canvas").getBoundingClientRect(); mouseX = event.clientX - rect.left - centerX; mouseY = event.clientY - rect.top - centerY; } else if(g_browsername == 'Firefox') { rect = document.getElementById("canvas").getBoundingClientRect(); mouseX = e.clientX - rect.left - centerX; mouseY = e.clientY - rect.top - centerY; } else { rect = event.currentTarget.getBoundingClientRect(); mouseX = event.clientX - rect.left - centerX; mouseY = event.clientY - rect.top - centerY; } set(mouseX, mouseY); } ctx = theCanvas.getContext("2d"); var x = Math.cos(18*Math.PI/180)*50*1.62; var y = Math.sin(18*Math.PI/180)*50*1.62; points.push({x:-(x/2),y:-y}); points.push({x:x/2,y:0}); points.push({x:-(x/2),y:y}); set(0,0); } function set(mx,my) { var mx = mx; var my = my; ctx.clearRect(0,0,300,300); var dx = mx; var dy = my; var radian = Math.atan2(dy,dx); var i=0; var currentX0 = Math.cos(radian)*points[i].x-Math.sin(radian)*points[i].y; var currentY0 = Math.sin(radian)*points[i].x+Math.cos(radian)*points[i].y; i=1; var currentX1 = Math.cos(radian)*points[i].x-Math.sin(radian)*points[i].y; var currentY1 = Math.sin(radian)*points[i].x+Math.cos(radian)*points[i].y; i=2; var currentX2 = Math.cos(radian)*points[i].x-Math.sin(radian)*points[i].y; var currentY2 = Math.sin(radian)*points[i].x+Math.cos(radian)*points[i].y; draw(currentX0,currentY0,currentX1,currentY1,currentX2,currentY2); } function draw(currentX0,currentY0,currentX1,currentY1,currentX2,currentY2) { ctx.strokeStyle="#000000"; ctx.lineWidth=1; ctx.beginPath(); ctx.moveTo(centerX+currentX0, centerY+currentY0); ctx.lineTo(centerX+currentX1, centerY+currentY1); ctx.lineTo(centerX+currentX2, centerY+currentY2); ctx.lineTo(centerX+currentX0, centerY+currentY0); ctx.stroke(); }