Давайте порисуем на HTML5 и canvas


Привет 3w-люди!

Сегодня мы будем рисовать… в браузере!
Все ок, поехали дальше.

HTML5


Рисовать будем с помощью canvas'a, ну и для этого нам нужно знать JS и иметь браузер с поддержкой HTML5.

Основа


Ну для основы нам нужна HTML документ с правильным !DOCTYPE'ом и всемогущий canvas:


<!DOCTYPE html>
<html>
	<head>
		<title></title>
		<meta charset="UTF-8" />
		<script type="text/javascript">
		
		</script>
	</head>
	<body>
		<canvas id="canvas" width="600" height="400">
			Мой охренительно классный Canvas не работает... И все из-за тебя %browser% (IE)!
		</canvas>
	</body>
</html>

Тут все банально просто, голова: заголовок, кодировка, и JS; тело: и канвас (холст).
Приступим к моей любимой функции load().

Код:

function rand(min,max) {
	var argc = arguments.length;
	if (argc === 0) {
		min = 0;
		max = 2147483647;
	} else if (argc === 1) {
		throw new Error('Warning: rand() expects exactly 2 parameters, 1 given');
	}
	return Math.floor(Math.random() * (max - min + 1)) + min;
}

// Функция rand с phpjs :http://phpjs.org/functions/rand:498
// Потом понадобится.

var canvas, ctx; // Канвас и контекст для него,
				 // Короче там где рисовать будем.

var w, h; // Размер канваса, Ширина и Высота блока.

function load() {
	canvas = document.getElementById("canvas");
	
	w = canvas.clientWidth;
	h = canvas.clientHeight;
	
	ctx = canvas.getContext("2d");
	
	// Рисуем черный квадрат, для заднего фона!
	ctx.fillStyle = "Black";
	ctx.fillRect(0,0,w,h);
}

window.addEventListener("DOMContentLoaded",load);

Здесь все практически знакомо: создаем переменные canvas, ctx, w, и h, далее функция load() где мы устанавливаем canvas, узнаем ширину и высоту canvas'a, создаем контекст для того что б порисовать на канвасе, ну и рисуем квадрат.
Последняя строку устанавливает handler'a на загрузку контента.

Квадраты


Основные функции для работы с квадратами являются:

.fillRect(x, y, ширина, высота) — закрашиваем квадрат;
.strokeRect(x, y, ширина, высота) — обводим квадрат.

также для того что б поменять цвет мы можем указать в свойства:

.fillStyle — свойство, указывает цвет заливки фигуры;
.strokeStyle — свойство, указывает цвет обводки.

Также хоче заметить что цвет может указыватся в 4 формах:

ctx.fillStyle = "Black"; // HTML название цвета
ctx.fillStyle = "#000000"; // Hex цвета
ctx.fillStyle = "rgb(0,0,0)"; // RGB, прям как в CSS
ctx.fillStyle = "rgba(0,0,0,1)"; // И RGBA, тоже самое что и RGB, только можно цвету установить прозрачность.

А для большего понимание, давайте нарисуем куча квадратов:

Пример №1:
canvas = document.getElementById("canvas");

w = canvas.clientWidth;
h = canvas.clientHeight;

ctx = canvas.getContext("2d");

// Рисуем черный квадрат, для заднего фона!
ctx.fillStyle = "Black";
ctx.fillRect(0,0,w,h);

for(var i = 0; i <= 5; i++) {
	var x, y;
	x = rand(0,w);
	y = rand(0,h);
	
	width = w - x;
	height = h - y;
	
	ctx.fillStyle = "rgb("+rand(0,255)+","+rand(0,255)+","+rand(0,255)+")";
	ctx.fillRect(x,y,width,height);
}



В итоге мы увидим нечто интересное, 5 прямоугольников сгенерируются с разными цветами, координатами, шириной и высотой.
Хотя может быть и некоторые при кроят друг друга.

Все поняли Малевичи?
Теперь линии.

О всемогущий отрезок


Перед тем как начнем пользоваться функциями, мы должны знать, как правильно рисовать линии.

Вот такая ротация(порядок) функций:

.beginPath() -> .moveTo(x,y) -> .lineTo(x,y) (n-раз) -> .closePath() (Необязательно) -> .fill() ИЛИ .stroke() ИЛИ оба

А теперь подробное описание:

.beginPath() — начинает «путь», так сказать, создает контекст для линии.
.moveTo(x,y) — двигает курсор в x,y (Используется один раз во время контекста).
.lineTo(x,y) — двигает точку в x,y и двигает курсор на x,y, можно указывать линии сколько угодно пока не вызван .closePath(), .fill или .stroke()
.closePath() — заканчивает «путь», заканчивает контекст и двигает курсор там, где указали в .moveTo(x,y) (Необязательно).
.fill() — звучит очевидно, залить контур который мы проделали во время контекста.
.stroke() — тоже очевидно, обвести контур.

А теперь примерчик: (за комментируйте код из предыдущего примера что б увидеть этот пример)

Пример №2:
ctx.strokeStyle = "#aaaaff";
for (var i = 1; i <= 20; i++) {
	ctx.beginPath();
	
	ctx.moveTo(i*(w/20),0);
	ctx.lineTo(i*(w/20),h);
	
	ctx.stroke();
}

for (var i = 1; i <= 20; i++) {
	ctx.beginPath();
	
	ctx.moveTo(0,i*(h/20));
	ctx.lineTo(w,i*(h/20));
	
	ctx.stroke();
}

ctx.strokeStyle = "#00ff00";
ctx.beginPath();

ctx.moveTo(0,h/2);
for (var i = 1; i <= 20; i++) {
	ctx.lineTo(i*(w/20),rand(0,h));
}
ctx.stroke();



Здесь мы рисуем случайный график.

Безье и Квадратичная Кривая


А теперь перейдем к линиям посложнее:

Безье — одним словом кривая, но для любопытных ссылочка на статью в википедии.

Ротация такая же как и у обычных линий… НО по другому:

.beginPath() -> .moveTo(x,y) -> .bezierCurveTo(p1x,p1y,p2x,p2y,x,y) ИЛИ .quadraticCurveTo(p1x,p1y,x,y) (n-раз) -> .closePath() (Необязательно) -> .fill() ИЛИ .stroke() ИЛИ оба

А теперь описание:



.bezierCurveTo(p1x,p1y,p2x,p2y,x,y) — создает кривую бизье, x,y конец линии, p1x,p1y,p2x,p2y эти точки способствуют трансформации. (Картинка хорошо объяснит, смотрите только на p1 и p2)
.quadraticCurveTo(p1x,p1y,x,y) — создает квадратную кривую линию, x,y конец линии, а p1x,p1y способствуют трансформации, как и с бизье, только одна точка модифицирует.

А теперь примерчик (не забываем за комментировать Пример №2):

Пример №3:
ctx.strokeStyle = "white";
ctx.beginPath();
ctx.moveTo(w/2-100, h/2);
ctx.bezierCurveTo(w/2-100, h/2-100, w/2+100, h/2-100, w/2+100, h/2);
ctx.moveTo(w/2-100, h/2);
ctx.quadraticCurveTo(w/2, h/2+100, w/2+100, h/2);
ctx.stroke();



Похоже немного на нос.

Ну вот и все ребята)
В следующий раз попробуем Asteroids написать

И напоследок функция для рисования кругов:

(до load()
function circle(x,y,radx,rady) {
	ctx.beginPath();
	
	ctx.moveTo(x+radx,y);
	
	for(var d = 0; d <= Math.PI*2; d += Math.PI/180) {
		var cos = radx * Math.cos(d);
		var sin = rady * Math.sin(d);
		
		ctx.lineTo(x+cos,y+sin);
		//document.write(cos+":c + "+sin+":s 
");
	}
	
	ctx.closePath();
	ctx.stroke();
}

Комментируем пример №3 и вставляем вот это:

ctx.strokeStyle = "white";
circle(w/2,h/2,100,100);

Вот и все.
Весь код:

<!DOCTYPE html>
<html>
	<head>
		<title></title>
		<meta charset="UTF-8" />
		<script type="text/javascript">
			function circle(x,y,radx,rady) {
				ctx.beginPath();
				
				ctx.moveTo(x+radx,y);
				
				for(var d = 0; d <= Math.PI*2; d += Math.PI/180) {
					var cos = radx * Math.cos(d);
					var sin = rady * Math.sin(d);
					
					ctx.lineTo(x+cos,y+sin);
				}
				
				ctx.closePath();
				ctx.stroke();
			}
			
			function rand(min,max) {
				var argc = arguments.length;
				if (argc === 0) {
					min = 0;
					max = 2147483647;
				} else if (argc === 1) {
					throw new Error('Warning: rand() expects exactly 2 parameters, 1 given');
				}
				return Math.floor(Math.random() * (max - min + 1)) + min;
			}

			
			var canvas, ctx; // Канвас и контекст для него,
							 // Короче там где рисовать будем.
			
			var w, h; // Размер канваса, Ширина и Высота блока.
			
			function load() {
				canvas = document.getElementById("canvas");
				
				w = canvas.clientWidth;
				h = canvas.clientHeight;
				
				ctx = canvas.getContext("2d");
				
				// Рисуем черный квадрат, для заднего фона!
				ctx.fillStyle = "Black";
				ctx.fillRect(0,0,w,h);
				
				/* Пример №1
				for(var i = 0; i <= 5; i++) {
					var x, y;
					x = rand(0,w);
					y = rand(0,h);
					
					width = w - x;
					height = h - y;
					
					ctx.fillStyle = "rgb("+rand(0,255)+","+rand(0,255)+","+rand(0,255)+")";
					ctx.fillRect(x,y,width,height);
				}*/
				
				/* Пример №2
				ctx.strokeStyle = "#aaaaff";
 				for (var i = 1; i <= 20; i++) {
 					ctx.beginPath();
 					
 					ctx.moveTo(i*(w/20),0);
 					ctx.lineTo(i*(w/20),h);
 					
 					ctx.stroke();
 				}
 				
 				for (var i = 1; i <= 20; i++) {
 					ctx.beginPath();
 					
 					ctx.moveTo(0,i*(h/20));
 					ctx.lineTo(w,i*(h/20));
 					
 					ctx.stroke();
 				}
 				
 				ctx.strokeStyle = "#00ff00";
 				ctx.beginPath();
 				
 				ctx.moveTo(0,h/2);
 				for (var i = 1; i <= 20; i++) {
 					ctx.lineTo(i*(w/20),rand(0,h));
 				}
 				ctx.stroke(); */
				
				/* Пример №3
				ctx.strokeStyle = "white";
 				ctx.beginPath();
 				ctx.moveTo(w/2-100, h/2);
 				ctx.bezierCurveTo(w/2-100, h/2-100, w/2+100, h/2-100, w/2+100, h/2);
 				ctx.moveTo(w/2-100, h/2);
 				ctx.quadraticCurveTo(w/2, h/2+100, w/2+100, h/2);
 				ctx.stroke(); */

				// Круг
				ctx.strokeStyle = "white";
				circle(w/2,h/2,100,100);
			}
			
			window.addEventListener("DOMContentLoaded",load);
		</script>
	</head>
	<body>
		<canvas id="canvas" width="600" height="400">
			Мой охренительно классный Canvas не работает... И все из-за тебя %browser% (IE)!
		</canvas>
	</body>
</html>

7 комментариев

avatar
  • GOR
С графиком, который на кардиограмму похож, очень понравилось. Сейчас буду пробовать сидеть)))
avatar
Не плохо но мне кажется лучше это реализовывать на php тогда безразницы какой там браузер и html.
avatar
С вами полностью согласен, но вот только это пример, и использования HTML5 canvas как генератор графика не стоит.

Статья прицелена на Геймдев)
avatar
Надо было бы ещё пример с анимацией сделать, а так хорошая статья :) +1
avatar
Анимация будет) Только позже)
avatar
  • GOR
Конечно, не с первого раза, но все вышло)) Порадовала меня процедура)
avatar
Спасибо ребят за отзыв)
Статья рассчитывалась не на графики и бизнес chart'ы а именно на Геймдев ;)

В следующий раз попробуем Asteroids написать ;)

Ясно?)