digitorum.ru

Как меня найти

Профиль

icq: 4415944

Рисуем кривые Безье по canvas.

html5, javascript

Как обычно лень писать, поэтому вот результат.

П.С. теория тут, архив вот.

bezier.js

/*
 * Кривые Безье 
 */
var Bezier = function() {}

/*
 * Получить точку
 * @param float x
 * @param float y
 * @return object
 */
Bezier.prototype.getPoint = function(x, y) {
	return {
		x: x,
		y: y
	};
}

/*
 * Добавить точки для отрисовки
 * @param array points
 */
Bezier.prototype.pushPoints = function(points) {
	this.points = points;
}

/*
 * Точки для отрисовки
 * @var array
 */
Bezier.prototype.points = [ ];

/*
 * Линейная
 * @param float t
 * @return object
 */
Bezier.prototype.linear = function(t) {
	return this.getPoint(
		(1 - t) * this.points[0].x + t * this.points[1].x,
		(1 - t) * this.points[0].y + t * this.points[1].y
	);
}

/*
 * Квадратичная
 * @param float t
 * @return object
 */
Bezier.prototype.quadratic = function(t) {
	return this.getPoint(
		(1 - t) * (1 - t) * this.points[0].x + 2 * (1 - t) * t * this.points[1].x + t * t * this.points[2].x,
		(1 - t) * (1 - t) * this.points[0].y + 2 * (1 - t) * t * this.points[1].y + t * t * this.points[2].y
	);
}

/*
 * Кубическая
 * @param float t
 * @return object
 */
Bezier.prototype.cubic = function(t) {
	return this.getPoint(
		(1 - t) * (1 - t) * (1 - t) * this.points[0].x + 3 * (1 - t) * (1 - t) * t * this.points[1].x + 3 * (1 - t) * t * t * this.points[2].x + t * t * t * this.points[3].x,
		(1 - t) * (1 - t) * (1 - t) * this.points[0].y + 3 * (1 - t) * (1 - t) * t * this.points[1].y + 3 * (1 - t) * t * t * this.points[2].y + t * t * t * this.points[3].y
	);
}

 

bezier-canvas.html

<html>
	<head>
		<title></title>
		<style>
			body {
				background-color: #2d2d30;
			}
			
			canvas {
				background-color: #ffffff;
				width: 600px;
				height: 600px;
				display: block;
				margin: 0 0 10px 0;
			}
			
			.legend {
				background-color: #e6e7e8;
				width: 590px;
				padding: 5px;
			}
			
			.black {
				color: #000;
			}
			
			.blue {
				color: #0000ff;
			}
			
			.green {
				color: #008000;
			}
		</style>
		<script src="bezier.js" type="text/javascript"></script>
	</head>
	<body>
		<canvas id="bezirer"></canvas>
		<div class="legend">
			<p class="black">Исходный график</p>
			<p class="blue">Безье второго порядка</p>
			<p class="green">Безье третьего порядка</p>
		</div>
		<script>
			
			(function() {
				
				// скрипт не оптимизирован (!)
				
				// опорные точки
				var points = [
					[0, 0],
					[200, 50],
					[400, 400],
					[600, 30]
				];
				// шаг для рассчета кривой Безье
				var step = 0.01;
				// "Время"
				var t = 0;
				// точка
				var point;
				// Bezier
				var bezier = new Bezier();
				// канвас
				var canvas = document.getElementById('bezirer');
				// контекст
				var context = canvas.getContext("2d");
				
				// настройки канваса
				canvas.width = 600;
				canvas.height = 600;
				
				// отрисовка нормального графика
				context.lineWidth = 2;
				context.strokeStyle = '#000000';
				context.moveTo(0, 0);
				context.beginPath();
				for(var i = 0; i<points.length; ++i) {
					context.lineTo(points[i][0], points[i][1]);
				}
				context.stroke();
				
				// отрисовка квадратичного графика
				context.lineWidth = 2;
				context.strokeStyle = '#0000ff';
				context.moveTo(0, 0);
				context.beginPath();
				t = 0;
				bezier.pushPoints([
					bezier.getPoint(points[0][0], points[0][1]),
					bezier.getPoint(points[1][0], points[1][1]),
					bezier.getPoint(points[2][0], points[2][1])
				]);
				do {
					point = bezier.quadratic(t);
					context.lineTo(point.x, point.y);
					t = parseFloat((t + step).toFixed(2));
				} while (t <= 1)
				context.stroke();
				
				// отрисовка кубического графика
				context.lineWidth = 2;
				context.strokeStyle = '#008000';
				context.moveTo(0, 0);
				context.beginPath();
				t = 0;
				bezier.pushPoints([
					bezier.getPoint(points[0][0], points[0][1]),
					bezier.getPoint(points[1][0], points[1][1]),
					bezier.getPoint(points[2][0], points[2][1]),
					bezier.getPoint(points[3][0], points[3][1])
				]);
				do {
					point = bezier.cubic(t);
					context.lineTo(point.x, point.y);
					t = parseFloat((t + step).toFixed(2));
				} while (t <= 1)
				context.stroke();
			})();
			
		</script>
	</body>
</html>