Advertisement
Guest User

Untitled

a guest
May 24th, 2015
229
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.44 KB | None | 0 0
  1. "use strict";
  2.  
  3. var ready = require("elements/domready");
  4.  
  5. var get = function(one, two, three, four, t) {
  6.  
  7. var v = 1 - t,
  8. b1 = t * t * t,
  9. b2 = 3 * t * t * v,
  10. b3 = 3 * t * v * v,
  11. b4 = v * v * v;
  12.  
  13. return four * b1 + three * b2 + two * b3 + one * b4;
  14. };
  15.  
  16. var clamp = function(n, min, max) {
  17. if (n < min) return min;
  18. if (n > max) return max;
  19. return n;
  20. };
  21.  
  22. var bezier = function(vectors, epsilon) {
  23.  
  24. if (vectors.length % 3 !== 1) throw new Error("invalid input");
  25.  
  26. for (var i = 0; i < vectors.length - 1; i += 3) {
  27.  
  28. var c0 = vectors[i],
  29. c1 = vectors[i + 1],
  30. c2 = vectors[i + 2],
  31. c3 = vectors[i + 3];
  32.  
  33. if (i === 0) c0.x = 0; // clamp the first 0 to x 0
  34. else c0.x = clamp(c0.x, 0, 1);
  35.  
  36. if (i === vectors.length - 4) c3.x = 1;
  37. else c3.x = clamp(c3.x, c0.x, 1);
  38.  
  39. // clamp the rest
  40. c1.x = clamp(c1.x, c0.x, c3.x);
  41. c2.x = clamp(c2.x, c0.x, c3.x);
  42. }
  43.  
  44. return function(x) {
  45.  
  46. var c0, c1, c2, c3;
  47.  
  48. for (var i = 0; i < vectors.length - 1; i += 3) {
  49. c0 = vectors[i];
  50. c1 = vectors[i + 1];
  51. c2 = vectors[i + 2];
  52. c3 = vectors[i + 3];
  53. if (x >= c0.x && x <= c3.x) break;
  54. }
  55.  
  56. var lower = 0, upper = 1, t = x, xt;
  57.  
  58. if (x < lower) return get(c0.y, c1.y, c2.y, c3.y, lower);
  59. if (x > upper) return get(c0.y, c1.y, c2.y, c3.y, upper);
  60.  
  61. while (lower < upper) {
  62. xt = get(c0.x, c1.x, c2.x, c3.x, t);
  63. if (Math.abs(xt - x) < epsilon) return get(c0.y, c1.y, c2.y, c3.y, t);
  64. if (x > xt) lower = t;
  65. else upper = t;
  66. t = (upper - lower) * 0.5 + lower;
  67. }
  68.  
  69. // Failure
  70. return get(c0.y, c1.y, c2.y, c3.y, t);
  71.  
  72. };
  73.  
  74. };
  75.  
  76. var Transition = require("transition");
  77.  
  78. var width = 900;
  79. var height = 900;
  80.  
  81. var boxLeft = 100,
  82. boxTop = 300;
  83.  
  84. var boxWidth = 600,
  85. boxHeight = 300;
  86.  
  87. var convertVectorsToPixels = function(vectors) {
  88. return vectors.map(function(v) {
  89. return { x: boxLeft + (v.x * boxWidth), y: boxTop + ((-v.y + 1) * boxHeight) };
  90. });
  91. };
  92.  
  93. // note: the cubic-bezier curve has its Y axis inverted
  94. var convertVectorsToPercentages = function(vectors) {
  95. return vectors.map(function(v) {
  96. return { x: (v.x - boxLeft) / boxWidth, y: -((v.y - boxTop) / boxHeight) + 1 };
  97. });
  98. };
  99.  
  100. var pixelVectors = convertVectorsToPixels([
  101. { x: 0, y: 0 }, { x: 0, y: 1 }, { x: 0.5, y: 1 }, { x: 0.5, y: 0 },
  102. { x: 0.5, y: 1 }, { x: 1, y: 1 }, { x: 1, y: 0 }
  103. ]);
  104.  
  105. var lerp = function(from, to, delta) {
  106. return (to - from) * delta + from;
  107. };
  108.  
  109. var equation;
  110.  
  111. var simplify = function(n, places) {
  112. return Number(n).toFixed(places).replace(/\.?0+$/, '');
  113. };
  114.  
  115. var render = function(ctx) {
  116.  
  117. var vectors = convertVectorsToPercentages(pixelVectors);
  118. equation = bezier(vectors, 0.0001); // vectors are now clamped
  119. pixelVectors = convertVectorsToPixels(vectors); // convert again for clamping
  120.  
  121. var i, c0, c1, c2, c3;
  122.  
  123. // clear canvas
  124. ctx.clearRect(0, 0, width, height);
  125.  
  126. // draw main box
  127. ctx.strokeStyle = 'rgba(255, 255, 255, 0.2)';
  128. ctx.lineWidth = 1;
  129. ctx.beginPath();
  130. ctx.rect(boxLeft, boxTop, boxWidth, boxHeight);
  131. ctx.closePath();
  132. ctx.stroke();
  133.  
  134.  
  135. // draw bezier curves
  136. ctx.strokeStyle = "red";
  137. c0 = pixelVectors[0];
  138.  
  139. ctx.beginPath();
  140. ctx.moveTo(c0.x, c0.y);
  141. for (i = 1; i < pixelVectors.length - 1; i += 3) {
  142. c1 = pixelVectors[i];
  143. c2 = pixelVectors[i + 1];
  144. c3 = pixelVectors[i + 2];
  145. ctx.bezierCurveTo(c1.x, c1.y, c2.x, c2.y, c3.x, c3.y);
  146. }
  147. ctx.stroke();
  148.  
  149. // draw control lines
  150. ctx.strokeStyle = "green";
  151.  
  152. for (i = 0; i < pixelVectors.length - 1; i += 3) {
  153. c0 = pixelVectors[i];
  154. c1 = pixelVectors[i + 1];
  155. c2 = pixelVectors[i + 2];
  156. c3 = pixelVectors[i + 3];
  157.  
  158. ctx.beginPath();
  159. ctx.moveTo(c0.x, c0.y);
  160. ctx.lineTo(c1.x, c1.y);
  161. ctx.closePath();
  162. ctx.stroke();
  163.  
  164. ctx.beginPath();
  165. ctx.moveTo(c3.x, c3.y);
  166. ctx.lineTo(c2.x, c2.y);
  167. ctx.closePath();
  168. ctx.stroke();
  169. }
  170.  
  171. // draw control handles
  172.  
  173. for (i = 0; i < pixelVectors.length; i++) {
  174. ctx.fillStyle = activePoint === i ? "cyan" : "green";
  175. var p = pixelVectors[i];
  176. ctx.beginPath();
  177. ctx.arc(p.x, p.y, 5 , 0, Math.PI * 2);
  178. ctx.closePath();
  179. ctx.fill();
  180. }
  181.  
  182. document.querySelector("#curve").textContent = "cubicBezier([" + vectors.map(function(p) {
  183. return "{ x: " + simplify(p.x, 2) + ", y: " + simplify(p.y, 2) + "}";
  184. }).join(", ") + "], 0.0001)";
  185.  
  186. var res = 40;
  187.  
  188. var points = [];
  189.  
  190. for (i = 0; i < res; i++) {
  191. var pct = i / (res - 1);
  192. var x = boxLeft + (pct * boxWidth);
  193.  
  194. var line = [{ x: x, y: boxTop + boxHeight }, { x: x, y: boxTop }];
  195.  
  196. ctx.strokeStyle = "rgba(255, 255, 255, 0.05)";
  197. ctx.beginPath();
  198. ctx.moveTo(line[0].x, line[0].y);
  199. ctx.lineTo(line[1].x, line[1].y);
  200. ctx.closePath();
  201. ctx.stroke();
  202.  
  203. var y = boxTop + ((-equation(pct) + 1) * boxHeight);
  204.  
  205. points.push({ x: x, y: y });
  206. }
  207.  
  208. // draw computed points
  209.  
  210. ctx.fillStyle = "blue";
  211. points.forEach(function(p) {
  212. ctx.beginPath();
  213. ctx.arc(p.x, p.y, 2, 0, Math.PI * 2);
  214. ctx.closePath();
  215. ctx.fill();
  216. });
  217. };
  218.  
  219. var activePoint;
  220.  
  221. var contained = function(p, box) {
  222. return p.x >= box.left && p.x <= box.right && p.y >= box.top && p.y <= box.bottom;
  223. };
  224.  
  225. var findCurvePoint = function(p) {
  226. var found;
  227.  
  228. for (var i = 0; i < pixelVectors.length; i++) {
  229. var cp = pixelVectors[i];
  230.  
  231. var box = { left: cp.x - 10, right: cp.x + 10, top: cp.y - 10, bottom: cp.y + 10 };
  232. if (contained(p, box)) {
  233. found = i;
  234. break;
  235. }
  236. }
  237.  
  238. activePoint = found;
  239. };
  240.  
  241. ready(function() {
  242. var canvas = document.querySelector("#curves");
  243. canvas.width = width;
  244. canvas.height = height;
  245. var ctx = canvas.getContext("2d");
  246.  
  247. render(ctx);
  248.  
  249. document.addEventListener("mousedown", function(event) {
  250. findCurvePoint({ x: event.pageX, y: event.pageY });
  251. if (activePoint != null) render(ctx);
  252. }, false);
  253.  
  254. document.addEventListener("mouseup", function() {
  255.  
  256. if (activePoint != null) {
  257. activePoint = null;
  258. render(ctx);
  259. }
  260. }, false);
  261.  
  262. document.addEventListener("mousemove", function(event) {
  263. if (activePoint == null) return;
  264. pixelVectors[activePoint] = { x: event.pageX, y: event.pageY };
  265. event.preventDefault();
  266. render(ctx);
  267.  
  268. }, false);
  269.  
  270. document.querySelector("#add").addEventListener("click", function() {
  271. var vectors = convertVectorsToPercentages(pixelVectors);
  272.  
  273. var segments = (vectors.length - 1) / 3 + 1;
  274. var ratio = 1 - (1 / segments);
  275.  
  276. for (var i = 0; i < vectors.length; i++) {
  277. var c = vectors[i];
  278. c.x *= ratio;
  279. }
  280.  
  281. vectors.push({ x: ratio, y: 1 }, { x: 1, y: 1 }, {x: 1, y: 0 });
  282. pixelVectors = convertVectorsToPixels(vectors);
  283.  
  284. render(ctx);
  285. }, false);
  286.  
  287. var sprite = document.querySelector("#sprite");
  288.  
  289. document.querySelector("#fade-in").addEventListener("click", function() {
  290. var start = 0, end = 1;
  291.  
  292. var transition = new Transition(5000, equation, function(delta) {
  293. sprite.style.opacity = lerp(start, end, delta);
  294. });
  295. transition.start();
  296. }, false);
  297.  
  298. document.querySelector("#fade-out").addEventListener("click", function() {
  299. var start = 1, end = 0;
  300.  
  301. var transition = new Transition(5000, equation, function(delta) {
  302. sprite.style.opacity = lerp(start, end, delta);
  303. });
  304. transition.start();
  305. }, false);
  306.  
  307. document.querySelector("#rise").addEventListener("click", function() {
  308. var start = 800, end = 100;
  309. sprite.style.opacity = 1;
  310.  
  311. var transition = new Transition(5000, equation, function(delta) {
  312. sprite.style.top = lerp(start, end, delta) + "px";
  313. });
  314. transition.start();
  315. }, false);
  316.  
  317. document.querySelector("#fall").addEventListener("click", function() {
  318. var start = 100, end = 800;
  319. sprite.style.opacity = 1;
  320.  
  321. var transition = new Transition(5000, equation, function(delta) {
  322. sprite.style.top = lerp(start, end, delta) + "px";
  323. });
  324. transition.start();
  325. }, false);
  326.  
  327. });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement