このプログラムについて
Javascriptでcanvas要素に幾何学模様を描きます。模様を描くためには三角関数を使った計算をします。三角関数の解説もしていますが、わからなくてもプログラムは作ることができます。
必要なプログラミング知識
HTMLとCSSの基礎
Javascriptの基礎(変数や関数の使い方、DOMの操作方法など)
各部位の名前
次のように各部位の名前付けをします。英語名は変数名を表しています。
時計の針のようにクルクル回る線を回転針(needle)、その関節部分を節(node)、節の軌道を描いた線を軌道線(trajectory)とよぶことにします。
ファイルの作成
次のようにgeopattern-genフォルダを作成し、その中にHTMLファイル、CSSファイル、JSファイルを作成します。
settings.jsには幾何学模様の設定、canvas.jsにはcanvasを操作するための関数、functions.jsにはそれ以外の関数を作成していきます。
HTMLの作成
index.htmlに次のように書き込みます。
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="styles.css">
<script defer src="settings.js"></script>
<script defer src="canvas.js"></script>
<script defer src="functions.js"></script>
<script defer src="main.js"></script>
<div id="canvas-wrapper">
<canvas id="main-canvas"></canvas>
<canvas id="needle-canvas"></canvas>
<button id="draw-button">描く</button>
<button id="start-button">自動描画</button>
<button id="stop-button">中断</button>
<button id="reset-button">リセット</button>
head要素内のscriptは main.js
が最後になるようにしてください。また、scriptに defer
を付けないとHTML解析前にJavascriptを実行してしまうためエラーとなります。
canvas要素は2つ用意してあります。
id="main-canvas"
のほうには軌道線を描きます。回転針が回るごとに軌道線を付け足していきます。
id="needle-canvas"
のほうは回転針を描きます。回転針が回るごとにcanvasをすべてけして、そのあと新しい回転針を描きます。こうすることで回転針がクルクル回っているようにみえます。
CSSの作成
次にstyles.cssに次のように書き込みます。
border: 5px ridge darkorange;
2つのcanvasを重ね合わせるため、 needle-canvas
のほう position:absolute
にしています。これを無くすとそれぞれのcanvasがどのようなものを描いているのか確認することができます。
設定ファイルの作成
settings.jsに次のような設定を書いていきます。
変数名 | 説明 |
---|
canvasSize | canvas要素の大きさ |
drawInterval | 線を描く時間の間隔(単位はミリ秒)。大きくなるほどゆっくりと描くようになる。 |
bgColor | canvasの背景色 |
lineDataList | 線の設定の配列 |
線の設定はオブジェクトとして書きます。これには次のようなプロパティがあります。
変数名 | 説明 |
---|
radius | 線の長さ。radiusとは半径の意味 |
angle | 線を回転させる角度。マイナスの値にすると時計回りに回転する |
drawTrajectory | 軌道線を描くか否か |
color | 軌道線の色 |
それぞれの意味は次のようになります。
settings.jsに次のように書き込みます。
// 自動描画するときの時間の間隔(単位はミリ秒)
// const bgColor = '#fff';
const bgColor = '#F6AD55';
// const lineDataList = [
// // drawTrajectory: true,
描画コンテキストの初期設定
描画コンテキストとは、canvasに絵を描くための画用紙や絵の具が入っている道具箱のようなものです。これの初期設定をおこないます。
canvasの座標
canvasにおける座標は、左上を原点として下に行くほどy値が大きくなります。たとえば、widthとheightが600pxのcanvasの場合は次のようになります。
幾何学模様を描くには三角関数を使います。その場合、数学でよく使われる、中央が原点で上に行くほどy値が大きくなる次のような座標のほうがプログラムを書きやすくなります。
このようにcanvasの座標を変換していきます。
描画コンテキストを設定して取得する関数
canvas.jsに次のように書き込みます
* @param canvasId canvas要素のID
const initCanvasCtx = (canvasId) => {
const canvas = document.getElementById(canvasId);
canvas.width = canvasSize;
canvas.height = canvasSize;
const ctx = canvas.getContext("2d");
// 原点(0, 0)をcanvasの中央に移動する
ctx.translate(canvasSize / 2, canvasSize / 2);
座標位置の表し方
このプログラムでは座標位置をオブジェクトで表すことにします。
たとえば、x座標が200、y座標が300の位置を示すには次のようなオブジェクトを作ります。
const samplePos = { x: 200, y: 300 };
変数名に「pos」と付いているものはこのような位置を表すオブジェクトが入っていると思ってください。
線を描く関数の作成
canvas.jsに次のように書き込みます。
* @param startPos 線を引き始める座標位置
* @param endPos 線を引き終える座標位置
const drawLine = (startPos, endPos, color, width, ctx) => {
ctx.moveTo(startPos.x, startPos.y);
ctx.lineTo(endPos.x, endPos.y);
点を描く関数の作成
canvas.jsに次のように書き込みます。関数内で使われている radian360
の意味はあとで説明します。
const drawPoint = (pos, color, radius, ctx) => {
// 引数にはx座標、y座標、半径、開始角度、終了角度を渡す
ctx.arc(pos.x, pos.y, radius, 0, radian360);
軌道線を描く関数の作成
canvas.jsに次のように書き込みます。
* @param prevNodePosList 回転前のnodePosList
* @param nextNodePosList 回転後のnodePosList
* @param LineDataList 線情報の配列
const drawTrajectories = (prevNodePosList, nextNodePosList, LineDataList, ctx) => {
LineDataList.forEach((lineData, i) => {
if (lineData.drawTrajectory) {
// nodePosList[0]は{ x: 0, y: 0 }であるため、軌道線を描く必要なない
drawLine(prevNodePosList[i + 1], nextNodePosList[i + 1], lineData.color, 1, ctx);
回転針を描く関数の作成
canvas.jsに次のように書き込みます。
* @param nodePosList 節の座標位置の配列
* @param LineDataList 線設定の配列
const drawNeedle = (nodePosList, lineDataList, ctx) => {
lineDataList.forEach((lineData, i) => {
drawLine(nodePosList[i], nodePosList[i + 1], 'gray', 3, ctx);
// nodePosList[0]には{ x:0, y:0 }が入っている
drawPoint(nodePosList[0], 'gray', 3, ctx);
lineDataList.forEach((lineData, i) => {
if (lineData.drawTrajectory) {
// 軌道線を描く場合は、点をその色に染める、半径をやや大きくする
drawPoint(nodePosList[i + 1], lineData.color, 5, ctx);
drawPoint(nodePosList[i + 1], 'gray', 3, ctx);
canvasに描いたものをすべて消す関数の作成
canvas.jsに次のように書き込みます。
const clearCanvas = (ctx) => {
// 引数には消す範囲のx座標、y座標、横幅、縦幅を渡す
ctx.clearRect(-canvasSize / 2, -canvasSize / 2, canvasSize, canvasSize);
canvasを指定色で塗りつぶす関数の作成
canvas.jsに次のように書き込みます。
const fillBgCanvas = (color, ctx) => {
// 引数には塗りつぶす範囲のx座標、y座標、横幅、縦幅を渡す
ctx.fillRect(-canvasSize / 2, -canvasSize / 2, canvasSize, canvasSize);