| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 |
- /*
- * Sonic 0.3
- * --
- * https://github.com/padolsey/Sonic
- */
- (function(){
- var emptyFn = function(){};
- function Sonic(d) {
- this.converter = d.converter;
- this.data = d.path || d.data;
- this.imageData = [];
- this.multiplier = d.multiplier || 1;
- this.padding = d.padding || 0;
- this.fps = d.fps || 25;
- this.stepsPerFrame = ~~d.stepsPerFrame || 1;
- this.trailLength = d.trailLength || 1;
- this.pointDistance = d.pointDistance || .05;
- this.domClass = d.domClass || 'sonic';
- this.backgroundColor = d.backgroundColor || 'rgba(0,0,0,0)';
- this.fillColor = d.fillColor;
- this.strokeColor = d.strokeColor;
- this.stepMethod = typeof d.step == 'string' ?
- stepMethods[d.step] :
- d.step || stepMethods.square;
- this._setup = d.setup || emptyFn;
- this._teardown = d.teardown || emptyFn;
- this._preStep = d.preStep || emptyFn;
- this.pixelRatio = d.pixelRatio || null;
- this.width = d.width;
- this.height = d.height;
- this.fullWidth = this.width + 2 * this.padding;
- this.fullHeight = this.height + 2 * this.padding;
- this.domClass = d.domClass || 'sonic';
- this.setup();
- }
- var argTypes = Sonic.argTypes = {
- DIM: 1,
- DEGREE: 2,
- RADIUS: 3,
- OTHER: 0
- };
- var argSignatures = Sonic.argSignatures = {
- arc: [1, 1, 3, 2, 2, 0],
- bezier: [1, 1, 1, 1, 1, 1, 1, 1],
- line: [1,1,1,1]
- };
- var pathMethods = Sonic.pathMethods = {
- bezier: function(t, p0x, p0y, p1x, p1y, c0x, c0y, c1x, c1y) {
-
- t = 1-t;
- var i = 1-t,
- x = t*t,
- y = i*i,
- a = x*t,
- b = 3 * x * i,
- c = 3 * t * y,
- d = y * i;
- return [
- a * p0x + b * c0x + c * c1x + d * p1x,
- a * p0y + b * c0y + c * c1y + d * p1y
- ]
- },
- arc: function(t, cx, cy, radius, start, end) {
- var point = (end - start) * t + start;
- var ret = [
- (Math.cos(point) * radius) + cx,
- (Math.sin(point) * radius) + cy
- ];
- ret.angle = point;
- ret.t = t;
- return ret;
- },
- line: function(t, sx, sy, ex, ey) {
- return [
- (ex - sx) * t + sx,
- (ey - sy) * t + sy
- ]
- }
- };
- var stepMethods = Sonic.stepMethods = {
-
- square: function(point, i, f, color, alpha) {
- this._.fillRect(point.x - 3, point.y - 3, 6, 6);
- },
- fader: function(point, i, f, color, alpha) {
- this._.beginPath();
- if (this._last) {
- this._.moveTo(this._last.x, this._last.y);
- }
- this._.lineTo(point.x, point.y);
- this._.closePath();
- this._.stroke();
- this._last = point;
- }
- }
- Sonic.prototype = {
- calculatePixelRatio: function(){
- var devicePixelRatio = window.devicePixelRatio || 1;
- var backingStoreRatio = this._.webkitBackingStorePixelRatio
- || this._.mozBackingStorePixelRatio
- || this._.msBackingStorePixelRatio
- || this._.oBackingStorePixelRatio
- || this._.backingStorePixelRatio
- || 1;
- return devicePixelRatio / backingStoreRatio;
- },
- setup: function() {
- var args,
- type,
- method,
- value,
- data = this.data;
- this.canvas = document.createElement('canvas');
- this._ = this.canvas.getContext('2d');
- if(this.pixelRatio == null){
- this.pixelRatio = this.calculatePixelRatio();
- }
- this.canvas.className = this.domClass;
- if(this.pixelRatio != 1){
- this.canvas.style.height = this.fullHeight + 'px';
- this.canvas.style.width = this.fullWidth + 'px';
- this.fullHeight *= this.pixelRatio;
- this.fullWidth *= this.pixelRatio;
- this.canvas.height = this.fullHeight;
- this.canvas.width = this.fullWidth;
- this._.scale(this.pixelRatio, this.pixelRatio);
- } else{
- this.canvas.height = this.fullHeight;
- this.canvas.width = this.fullWidth;
- }
- this.points = [];
- for (var i = -1, l = data.length; ++i < l;) {
- args = data[i].slice(1);
- method = data[i][0];
- if (method in argSignatures) for (var a = -1, al = args.length; ++a < al;) {
- type = argSignatures[method][a];
- value = args[a];
- switch (type) {
- case argTypes.RADIUS:
- value *= this.multiplier;
- break;
- case argTypes.DIM:
- value *= this.multiplier;
- value += this.padding;
- break;
- case argTypes.DEGREE:
- value *= Math.PI/180;
- break;
- };
- args[a] = value;
- }
- args.unshift(0);
- for (var r, pd = this.pointDistance, t = pd; t <= 1; t += pd) {
-
- // Avoid crap like 0.15000000000000002
- t = Math.round(t*1/pd) / (1/pd);
- args[0] = t;
- r = pathMethods[method].apply(null, args);
- this.points.push({
- x: r[0],
- y: r[1],
- progress: t
- });
- }
- }
- this.frame = 0;
- if (this.converter && this.converter.setup) {
- this.converter.setup(this);
- }
- },
- prep: function(frame) {
- if (frame in this.imageData) {
- return;
- }
- this._.clearRect(0, 0, this.fullWidth, this.fullHeight);
- this._.fillStyle = this.backgroundColor;
- this._.fillRect(0, 0, this.fullWidth, this.fullHeight);
- var points = this.points,
- pointsLength = points.length,
- pd = this.pointDistance,
- point,
- index,
- frameD;
- this._setup();
- for (var i = -1, l = pointsLength*this.trailLength; ++i < l && !this.stopped;) {
- index = frame + i;
- point = points[index] || points[index - pointsLength];
- if (!point) continue;
- this.alpha = Math.round(1000*(i/(l-1)))/1000;
- this._.globalAlpha = this.alpha;
- if (this.fillColor) {
- this._.fillStyle = this.fillColor;
- }
- if (this.strokeColor) {
- this._.strokeStyle = this.strokeColor;
- }
- frameD = frame/(this.points.length-1);
- indexD = i/(l-1);
- this._preStep(point, indexD, frameD);
- this.stepMethod(point, indexD, frameD);
- }
- this._teardown();
- this.imageData[frame] = (
- this._.getImageData(0, 0, this.fullWidth, this.fullWidth)
- );
- return true;
- },
- draw: function() {
-
- if (!this.prep(this.frame)) {
- this._.clearRect(0, 0, this.fullWidth, this.fullWidth);
- this._.putImageData(
- this.imageData[this.frame],
- 0, 0
- );
- }
- if (this.converter && this.converter.step) {
- this.converter.step(this);
- }
- if (!this.iterateFrame()) {
- if (this.converter && this.converter.teardown) {
- this.converter.teardown(this);
- this.converter = null;
- }
- }
- },
- iterateFrame: function() {
-
- this.frame += this.stepsPerFrame;
-
- if (this.frame >= this.points.length) {
- this.frame = 0;
- return false;
- }
- return true;
- },
- play: function() {
- this.stopped = false;
- var hoc = this;
- this.timer = setInterval(function(){
- hoc.draw();
- }, 1000 / this.fps);
- },
- stop: function() {
- this.stopped = true;
- this.timer && clearInterval(this.timer);
- }
- };
- window.Sonic = Sonic;
- }());
|