Создаем простую панель для рисования 3D
Сегодня мы собираемся вернуться к практическим занятиям по HTML5. Я думаю, что мы уже сделали хороший перерыв в наших уроках. В этом уроке я покажу вам, как создать панель для рисования которая вращается вокруг своей оси (на объекте холста HTML5). Каждый из ваших нарисованных фигур будет вращаться в псевдо 3D режиме. Для этого нам необходимо определить два объекта: точки и формы (каждая фигура состоит из нескольких пунктов). Основная идея — проектировать и вращать точки фигур, а также нарисовать кривую линию между этими точками.
Такую реализацию можно не много где применить, но основная идея состоит в том, чтобы показать вам некоторые возможности псевдо 3D. И так, приступим.
Шаг 1. HTML
Для начала нам необходимо подключить скрипты, и создать достаточно простую разметку, которая будет состоять из одной строчки, а именно вызов панели:
1 2 3 4 5 6 |
<script src="js/pointer.js"></script> <script src="js/main.js"></script> .... <canvas id="scene" height="600" width="800" tabindex="1"></canvas> |
Шаг 2. JS
Как обычно, в начале каждого JS кода, мы можем определить несколько глобальных переменных:
JS / main.js
1 2 3 4 5 6 |
// Переменные var canvas, ctx; // canvas и объекты var vPointer; // Рисуем указатель Pbject var aShapes = []; // Формы массива var iLMx = iLMy = 0; // Последний указатель позиции var vActShape; // Активные формы объекта |
Теперь мы можешь высчитать и указать первый уровень-точки:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
var Point = function (x, y, z) { this.x = x; this.y = y; this.z = z; this.x0 = x; this.z0 = z; this.xp = 0; this.yp = 0; this.zp = 0; this.fov = 2000; } Point.prototype.project = function () { this.zp = this.fov / (this.fov + this.z); this.xp = this.x * this.zp; this.yp = this.y * this.zp; } Point.prototype.rotate = function (ax, ay) { this.x = parseInt(Math.round(this.x0 * ax + this.z0 * ay)); this.z = parseInt(Math.round(this.x0 * -ay + this.z0 * ax)); } |
Для «Роint» объекта у нас есть целый набор внутренних свойств и только две функции: проект и вращение. «Shape» являются более сложным объектом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
// Форма объекта var Shape = function () { this.angle = 0; this.color = '#000'; this.halfheight = canvas.height / 2; this.halfwidth = canvas.width / 2; this.len = 0; this.points = []; return this; } // Добавляем точки Shape.prototype.addPoint = function (x, y, z) { this.points.push( new Point(Math.round(x), Math.round(y), Math.round(z)) ); this.len++; } // Вращение формы Shape.prototype.rotate = function () { this.angle += Math.PI / 180; // смещение на 1 градус (радианы в одном градусе) var ax = Math.cos(this.angle); var ay = Math.sin(this.angle); // Вращение всех точек и объектов формы for (var i = 0; i < this.len; i++) { this.points[i].rotate(ax, ay); } } Shape.prototype.draw = function () { // Точки проекции for (var i = 0; i < this.len; i++) { this.points[i].project(); } // Рисуем кривую линию между точками var p0 = this.points[0]; ctx.beginPath(); ctx.moveTo(p0.xp + this.halfwidth, p0.yp + this.halfheight); for (var i = 1, pl = this.points.length; i < pl; i++) { var apnt = this.points[i]; var xc = (p0.xp + apnt.xp) / 2; var yc = (p0.yp + apnt.yp) / 2; ctx.quadraticCurveTo(p0.xp + this.halfwidth, p0.yp + this.halfheight, xc + this.halfwidth, yc + this.halfheight); p0 = apnt; } ctx.lineWidth = 8; ctx.strokeStyle = this.color; ctx.lineCap = 'round'; // округлые заглушки ctx.stroke(); } |
Она имеет меньше параметров, но больше функций (AddPoint, вращать и рисовать). Теперь мы можем приступить к добавлению нескольких основных функций сцены: главную сцену (canvas), инициализация (sceneInit), функция визуализации (DrawScene) и генератор случайных цветов (getRandomColor):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
// Получаем случайный цвет function getRandomColor() { var letters = '0123456789ABCDEF'.split(''); var color = '#'; for (var i = 0; i < 6; i++ ) { color += letters[Math.round(Math.random() * 15)]; } return color; } // Рисуем основные функции сцены function drawScene() { ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); // Очистить canvas if (vPointer.bDown) { var iDx = iLMx - vPointer.X; var iDy = iLMy - vPointer.Y; var dif = Math.sqrt(iDx * iDx + iDy * iDy); // Разница между двумя последними точками if (dif > 5) { if (! vActShape) { aShapes.push( // подготовить новую форму объекта vActShape = new Shape() ); vActShape.color = getRandomColor(); } iLMx = vPointer.X; iLMy = vPointer.Y; vActShape.addPoint(vPointer.X - canvas.width * 0.5, vPointer.Y - canvas.height * 0.5, 0); } } else { // Как только мышь отпущена - Очистка if (vActShape) { vActShape = ''; iLMx = iLMy = 0; } // Вращение формы aShapes.forEach(function(sh) { sh.rotate(); }); } // Рисуем всех форм aShapes.forEach(function(sh) { sh.draw(); }); } // Инициализация function sceneInit() { // Подготовка холста и объектов контекста canvas = document.getElementById('scene'); // Изменение размера холста canvas.width = canvas.clientWidth; canvas.height = window.innerHeight; ctx = canvas.getContext('2d'); // Добавление двух пользовательских форм var oShape = new Shape(); oShape.addPoint(-200,-200,50); oShape.addPoint(0,0,0); oShape.addPoint(-400,200,0); oShape.addPoint(200,-400,-50); aShapes.push(oShape); var oShape2 = new Shape(); oShape2.addPoint(200,200,-50); oShape2.addPoint(0,0,0); oShape2.addPoint(400,-200,0); oShape2.addPoint(-200,400,50); aShapes.push(oShape2); //Указатель мыши обработчик событий vPointer = new CPointer(canvas); // Цикл основной сцены setInterval(drawScene, 20); } // Window OnLoad инициализации if (window.attachEvent) { window.attachEvent('onload', sceneInit); } else { if (window.onload) { var curronload = window.onload; var newonload = function() { curronload(); sceneInit(); }; window.onload = newonload; } else { window.onload = sceneInit; } } |
В sceneInit мы добавили две формы. Как вы уже заметили, для того, чтобы справиться с событиями мыши мы используем экземпляр класса CPointer. Вот он:
JS / pointer.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
CPointer = function (canvas) { var self = this; this.body = document.body; this.html = document.documentElement; this.elem = canvas; this.X = 0; this.Y = 0; this.Xi = 0; this.Yi = 0; this.Xr = 0; this.Yr = 0; this.startX = 0; this.startY = 0; this.bDrag = false; this.bMoved = false; this.bDown = false; this.bXi = 0; this.bYi = 0; this.sX = 0; this.sY = 0; this.left = canvas.offsetLeft; this.top = canvas.offsetTop; self.elem.onmousedown = function (e) { self.bDrag = false; self.bMoved = false; self.bDown = true; self.Xr = e.clientX; self.Yr = e.clientY; self.X = self.sX = self.Xr - self.left; self.Y = self.sY = self.Yr - self.top + ((self.html && self.html.scrollTop) || self.body.scrollTop); } self.elem.onmousemove = function(e) { self.Xr = (e.clientX !== undefined ? e.clientX : e.touches[0].clientX); self.Yr = (e.clientY !== undefined ? e.clientY : e.touches[0].clientY); self.X = self.Xr - self.left; self.Y = self.Yr - self.top + ((self.html && self.html.scrollTop) || self.body.scrollTop); if (self.bDown) { self.Xi = self.bXi + (self.X - self.sX); self.Yi = self.bYi - (self.Y - self.sY); } if (Math.abs(self.X - self.sX) > 2 || Math.abs(self.Y - self.sY) > 2) { self.bMoved = true; if (self.bDown) { if (! self.bDrag) { self.startX = self.sX; self.startY = self.sY; self.bDrag = true; } } else { self.sX = self.X; self.sY = self.Y; } } } self.elem.onmouseup = function() { self.bXi = self.Xi; self.bYi = self.Yi; if (! self.bMoved) { self.X = self.sX; self.Y = self.sY; } self.bDrag = false; self.bDown = false; self.bMoved = false; } } |
Вот и все. Готово!
Материал взят из зарубежного источника. И представлен исключительно в ознакомительных целях.
Читайте также:
Опубликовал Cooper 16.05.2013 в 15:49, в категории Веб-дизайн. Вы можете следить за комментариями через RSS 2.0. Вы можете перейти в конец записи и оставить комментарий. Пинги запрещены. |