Last active
August 30, 2017 09:29
-
-
Save imk2o/51dadedd681c256390b45dda1406a8de to your computer and use it in GitHub Desktop.
Canvasアニメーションテンプレ #HTML #PHH
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="ja"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<meta http-equiv="X-UA-Compatible" content="ie=edge"> | |
<title>HTML Canvas Animation</title> | |
<script src="canvas_animation.js"></script> | |
<style type="text/css"> | |
canvas { border: 1px solid black; } | |
</style> | |
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" crossorigin="anonymous"></script> | |
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> | |
</head> | |
<body> | |
<div class="well"> | |
<button id="restart_button" class="btn btn-info">リスタート</button> | |
<button id="stop_button" class="btn btn-warning">停止</button> | |
</div> | |
<div> | |
<canvas id="canvas1" width="600" height="400"></canvas> | |
</div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
document.addEventListener('DOMContentLoaded', function() { | |
// リスタートボタンのクリックを監視 | |
const restart_button = document.getElementById('restart_button'); | |
restart_button.addEventListener('click', function() { | |
start(); | |
}); | |
// 停止ボタンのクリックを監視 | |
const stop_button = document.getElementById('stop_button'); | |
stop_button.addEventListener('click', function() { | |
window.cancelAnimationFrame(request_id); | |
request_id = null; | |
}); | |
// 描画とアニメーションを開始 | |
start(); | |
}); | |
let request_id = null; | |
let startTimestamp; | |
let lastTimestamp; | |
function start() { | |
startTimestamp = null; | |
lastTimestamp = null; | |
if (request_id == null) { | |
request_id = window.requestAnimationFrame(draw); | |
} | |
} | |
function draw(timestamp) { | |
// 経過時間を求める | |
if (startTimestamp == null) { | |
startTimestamp = timestamp; | |
lastTimestamp = timestamp; | |
} | |
//// 描画開始からの経過時間(秒) | |
let progress = (timestamp - startTimestamp) / 1000; | |
//// 前回の描画からの経過時間(秒) | |
let delta = (timestamp - lastTimestamp) / 1000; | |
// canvasの取得 | |
const canvas = document.getElementById('canvas1'); | |
const canvas_width = Number.parseInt(canvas.getAttribute('width')); | |
const canvas_height = Number.parseInt(canvas.getAttribute('height')); | |
const ctx = canvas.getContext('2d'); | |
// canvasをクリア | |
ctx.clearRect(0, 0, canvas_width, canvas_height); | |
// 罫線を表示 (邪魔ならコメントアウトしてよい) | |
debugDrawGrid(ctx, canvas_width, canvas_height); | |
// 1フレームを描画 | |
drawFrame(ctx, progress, delta, canvas_width, canvas_height); | |
// 経過時間の表示 (邪魔ならコメントアウトしてよい) | |
debugDrawTime(ctx, progress, delta); | |
// 一定時間後、再度draw()を呼び出すようリクエストする | |
lastTimestamp = timestamp; | |
request_id = window.requestAnimationFrame(draw); | |
} | |
// 1フレームを描画 | |
// ctx: canvas 2D コンテキスト | |
// progress: 開始からの経過時間 | |
// delta: 前回の描画からの経過時間 | |
// canvas_width: キャンバスの幅 | |
// canvas_height: キャンバスの高さ | |
function drawFrame(ctx, progress, delta, canvas_width, canvas_height) { | |
//////////////////////////////////////////////////////////// | |
// TODO: ここに描画とアニメーション処理を追加... | |
ctx.fillStyle = 'rgb(240, 0, 0)'; | |
let x = 10 * progress; | |
let y = x; | |
ctx.fillRect(x, y, 100, 100); | |
//////////////////////////////////////////////////////////// | |
} | |
// 以下、デバッグ用 //////////////////////////////////////////////////////////// | |
function debugDrawGrid(ctx, width, height) { | |
const grid_width = 10; | |
const grid_height = 10; | |
const grid_scale = 10; | |
const small_grid_color = 'rgb(160, 160, 160)'; | |
const large_grid_color = 'rgb(255, 160, 160)'; | |
ctx.save(); | |
ctx.lineWidth = 1; | |
// 水平線 | |
for (let y = 0; y < height; y += grid_height) { | |
ctx.strokeStyle = (y % (grid_height * grid_scale) == 0) ? large_grid_color : small_grid_color; | |
ctx.beginPath(); | |
ctx.moveTo(0, y); | |
ctx.lineTo(width, y); | |
ctx.stroke(); | |
} | |
// 垂直線 | |
for (let x = 0; x < width; x += grid_width) { | |
ctx.strokeStyle = (x % (grid_width * grid_scale) == 0) ? large_grid_color : small_grid_color; | |
ctx.beginPath(); | |
ctx.moveTo(x, 0); | |
ctx.lineTo(x, height); | |
ctx.stroke(); | |
} | |
ctx.restore(); | |
} | |
function debugDrawTime(ctx, progress, delta) { | |
const text_size = 16; | |
ctx.save(); | |
ctx.fillStyle = 'rgb(80, 80, 255)'; | |
ctx.font = `${text_size}pt serif`; | |
ctx.fillText(`progress: ${progress.toFixed(3)}sec, delta: ${delta.toFixed(3)}sec`, 0, text_size); | |
ctx.restore(); | |
} | |
// HSVの値からカラースタイルを生成する。 | |
// | |
// h: 色相(0 〜 1, 1より大きな値の場合も0〜1の範囲で循環する) | |
// s: 彩度(0 〜 1) | |
// v: 明度(0 〜 1) | |
// a: 不透明度(0 〜 1, 省略時は1) | |
function styleWithHSV(h, s, v, a = 1) { | |
const i = Math.floor(h * 6); | |
const f = h * 6 - i; | |
const p = v * (1 - s); | |
const q = v * (1 - f * s); | |
const t = v * (1 - (1 - f) * s); | |
let r, g, b; | |
switch (i % 6) { | |
case 0: r = v, g = t, b = p; break; | |
case 1: r = q, g = v, b = p; break; | |
case 2: r = p, g = v, b = t; break; | |
case 3: r = p, g = q, b = v; break; | |
case 4: r = t, g = p, b = v; break; | |
case 5: r = v, g = p, b = q; break; | |
} | |
return `rgba(${Math.round(r * 255)}, ${Math.round(g * 255)}, ${Math.round(b * 255)}, ${a})`; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment