Показать сообщение отдельно
  #1 (permalink)  
Старый 12.01.2015, 01:31
JSN JSN вне форума
Аспирант
Отправить личное сообщение для JSN Посмотреть профиль Найти все сообщения от JSN
 
Регистрация: 01.09.2012
Сообщений: 57

Часы Безье. Начало
Здравствуйте,
Я тут наткнулся на такие веселые часы, которые были анимированы при помощи кривых Безье на Processing.js. Вот я и решил попробовать сотворить если не точную копию, то хотя бы что-то похожее.
Вот что на данный момент написано
<html>
<head>
	<style>
	* {
		padding: 0px;
		margin: 0px;
	}
	.point {
		position: absolute;
		margin-left: -5px;
		margin-top: -5px;
		background: red;
		width: 10px;
		height: 10px;
		-webkit-border-radius: 10px;
		-moz-border-radius: 10px;
		-ms-border-radius: 10px;
		-o-border-radius: 10px;
		border-radius: 10px;
	}
	#bezier {
		outline: 1px solid black;
	}
	</style>
</head>
<body>
    <canvas id='bezier' width='1000' height='800'></canvas>
    <div onclick='makeNULL()'>clear line</div>
	<script>
		var f = [1, 1], p = [], path = [], create = true;
		function getBase(i, n, t) {
		    while (n > f.length - 1) {
		        f[f.length] = f[f.length - 1] * f.length;
		    }
		    return (f[n] / (f[i] * f[n - i])) * Math.pow(t, i) * Math.pow(1 - t, n - i);
		}
		function Point(x, y) {
			var self = this;
			self.x = x;
			self.y = y;
			self.move = function (xx, yy, pos) {
				var el = document.createElement('div');
				el.className = 'point';
				document.getElementsByTagName('body')[0].appendChild(el);
				switch (arguments.length) {
					case 0:
						console.log(self.x + ' ' + self.y);
					break;
					default:
						var steps = 20,
							stepX = (xx - self.x) / steps,
							stepY = (yy - self.y) / steps;
						//console.log(stepX + ' ' + stepY);
						self.x = self.x + stepX * pos;
						self.y = self.y + stepY * pos;
					}
			}
			return self;
		}
		function getCurve(pnt, step) {
			var line = [];
		    step = step ? step : 0.01;
		    for (var i = 0; i < 1 + step; i += step) {
		        i = ((i > 1) ? 1 : i);
		        var ind = line.length;
		        line[ind] = {x:0,y:0};   
		        var len = pnt.length;
		        for (var j = 0; j < pnt.length; j++) {
		            var b = getBase(j, pnt.length - 1, i);
		            line[ind].x += pnt[j].x * b;
		            line[ind].y += pnt[j].y * b;
		        }
		    }
		    return line;
		}
		function drawS(c, line) {
		    var i = 0;
		    c.moveTo(line[0].x, line[0].y);
		    c.clearRect(0, 0, 1000, 800);
		    c.beginPath();
		    var it = setInterval(function() {
		        if (i >= line.length - 2)
		            clearInterval(it);
		        c.moveTo(line[i].x, line[i].y);
		        c.lineTo(line[i + 1].x, line[i + 1].y);
        		c.stroke();
		        i++;
		    }, 10);
		    c.closePath();
		}
		function draw(c, line) {
		    c.beginPath();
		    for (var i = 0; i < line.length - 1; ++i) {
		        c.moveTo(line[i].x, line[i].y);
		        c.lineTo(line[i + 1].x, line[i + 1].y);
        		c.stroke();
        	}
		    c.closePath();
		}
		function init() {
		    line = [];
		    var canvas = document.getElementById('bezier');
		    var c = canvas.getContext('2d');
		    canvas.width = screen.width;
		    canvas.height = screen.height;
		    c.clearRect(0, 0, canvas.width, canvas.height);
		    c.fillStyle = '#000';
		    c.lineWidth = 1;
		    return c;
		}
		init();
		p[1] = [
				new Point(21, 54),
				new Point(34, 22),
				new Point(83, 3),
				new Point(49, -3),
				new Point(58, 80),
				new Point(56, 112),
				new Point(57, 136),
				new Point(26, 137),
				new Point(78, 130),
				new Point(-1, 133),
				new Point(-2, 133),
				new Point(70, 132),
				new Point(61, 132),
		];
		p[2] = [
				new Point(47, 38),
				new Point(57, 15),
				new Point(101, 16),
				new Point(124, 54),
				new Point(116, 112),
				new Point(67, 213),
				new Point(-2, 170),
				new Point(-1, 98),
				new Point(56, 83),
				new Point(83, 94),
				new Point(21, 93),
				new Point(97, 163),
				new Point(121, 119)
		];
		p[3] = [
				new Point(21, 32),
				new Point(37, 9),
				new Point(71, 16),
				new Point(110, 32),
				new Point(89, 66),
				new Point(53, 157),
				new Point(16, 91),
				new Point(21, 50),
				new Point(58, 3),
				new Point(146, 110),
				new Point(131, 83),
				new Point(90, 183),
				new Point(18, 147)
		];
		var c = init();
		path = p[1];
		draw(c, getCurve(path));
		function move (pd) {	
			var pos = 0, steps = 20;
			var it = setInterval(function () {
				if (pos++ >= steps) {
					path = pd;
					clearInterval(it);
				}
				for (var i = 0; i < path.length; i++) {
					path[i].move(pd[i].x, pd[i].y, pos);
				};	
				var c = init();
				draw(c, getCurve(path));
			}, 10);
		}
		var sec = 1;
		setInterval(function() {
			if (sec > 3)
				sec = 1;
			move(p[sec]);
			sec++;
		}, 1000);
	</script>
</body>
</html>

Тут я столкнулся с проблемой: браузер запускает скрипт и 1 плавно cменяет 2, затем два cменяет 3, но потом 2 вместо одного cменяет 3. Но это полбеды. Со временем на исполнение функции move занимает все больше и больше времени. Я догадываюсь, что я компьютерный насильник, но поясните, пожалуйста, почему она замедляется?
Заранее благодарен
P.S. Есть смысл записать в массивы готовые точки, а не опорные?

Последний раз редактировалось JSN, 12.01.2015 в 01:50.
Ответить с цитированием