フロントサイドエンジニアという選択肢

HTMLコーダー → ECサイト運営 → システムエンジニア という経歴の著者がフロントサイトエンジニアという職業に今後の活路を見出し、その道に進むために取得した技術を貯めておくブログ

Canvas上で、ベジェ曲線に沿ってオブジェクトを動かすための機能を作ってみた

BezierCurveObjectという名前のオブジェクトを作成しました。3次ベジェ曲線を描画するために必要な引数をつかってインスタンス化します。
結果のみ言いますと、実際に何かを動かすのではなく、動かすために必要な座標や角度を取得することができるオブジェクトです。

 細かい説明やサンプルはGitHubの方に上げてあるので、興味のある方はご自由にご覧ください

github.com

ソースコードは以下の通りです。

function BezierCurveObject(startX, startY, controlAX, controlAY, controlBX, controlBY, endX, endY){
	var
		_pointData = [{x:startX, y:startY}],
		_currentPoint = 0,
		_currentDerection = 0;
	
	this.atEndInOnewey = false;
	
	// 0:一度だけ移動して、終点で止まる
	// 1:始点と終点を往復する
	// 2:終点についたら最初に戻る
	this.repeatType = 0;
	
	// ベジェ曲線の描画
	this.stroke = function(context){
		context.beginPath();
		context.moveTo(startX, startY);
		context.bezierCurveTo(controlAX, controlAY, controlBX, controlBY, endX, endY);
		context.stroke();
	}
	
	// 曲線に沿った座標の一覧を作成する
	// 曲線の始点から終点までの距離をlengthで割って
	// それぞれの座標を格納する配列を返す
	this.createPointData = function(length){
		var 
			ax, bx, cx, 
			ay, by, cy,
			speed = 1/(length-1),
			t = speed;

		cx = 3 * (controlAX - startX);
		bx = 3 * (controlBX - controlAX) - cx;
		ax = endX - startX - cx - bx;
		
		cy = 3 * (controlAY - startY);
		by = 3 * (controlBY - controlAY) - cy;
		ay = endY - startY - cy - by;
		
		for(var i=0; i<(length-1); i++){
			_pointData.push({
				x:ax*(t*t*t) + bx*(t*t) + cx*t + startX,
				y:ay*(t*t*t) + by*(t*t) + cy*t + startY
			});
			t += speed;
		}
		
		return _pointData;
	}
	
	// 次の座標を取得する
	this.getNextPoint = function(){
		var ret = {
			x:_pointData[_currentPoint].x,
			y:_pointData[_currentPoint].y
		}
		_currentPoint++;
		if(_pointData.length > _currentPoint){
			return ret;
		}
		else{
			switch(this.repeatType){
				case 0: // onewey
					this.atEndInOnewey = true;
					_currentPoint--;
					return {x:endX, y:endY};
					break;
				case 1: // reverse
					_currentPoint = 1;
					_pointData.reverse();
					return ret;
					break;
				case 2: // repeat
					_currentPoint = 0;
					return ret;
					break;
				default :
					throw Error('repeatTypeの指定が間違っています');
			}
		}
	}
	
	// 現在の進行方向の角度を取得する
	this.getDirectionRadian = function(){
		// 次の座標があれば_currentDerectionを更新
		if(_pointData[_currentPoint + 1]){
			var _nextPoint = _pointData[_currentPoint + 1];
			_currentDerection = Math.atan2(
				_nextPoint.y - _pointData[_currentPoint].y,
				_nextPoint.x - _pointData[_currentPoint].x
			);
		}
		return _currentDerection;
	}
}