Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 124 additions & 3 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,9 @@ Bezier curves are made form a start point, an end point each with a control poin
Arc
---

Exampe: animate along an arc
Example: animate along an arc

<pre>

<pre>
var arc_params = {
center: [285,185],
radius: 100,
Expand All @@ -62,6 +61,128 @@ $("my_elem").animate({path : new $.path.arc(arc_params)})
* end is the angle of the start point. 0 is "North", measured clockwise
* dir is the direction to move in. Only required if not obvious from start and end (e.g. if start is 100, end is 30, but you want to animate clockwise)

### Advanced Arcs ###

Example: add a spiral to the arc

<pre>
var arc_params = {
center: [285, 185],
spiral: [1, 100],
start: 30,
end: 200,
dir: -1
}

$('my_elem').animate({path : new $.path.arc(arc_params)})
</pre>

Example: use another path as the center of the arc

<pre>
var bezier_params = {
start: {
x: 185,
y: 185,
angle: 10
},
end: {
x:540,
y:110,
angle: -10,
length: 0.25
}
}

var arc_params = {
center: new $.path.bezier(bezier_params),
radius: 100,
start: 30,
end: 200,
dir: -1
}

$('my_elem').animate({path : new $.path.arc(arc_params)})
</pre>

Example: combine both the spiral and center paths
<pre>
var bezier_params = {
start: {
x: 185,
y: 185,
angle: 10
},
end: {
x:540,
y:110,
angle: -10,
length: 0.25
}
}

var arc_params = {
center: new $.path.bezier(bezier_params),
radius: [1, 100],
start: 30,
end: 200,
dir: -1
}

$('my_elem').animate({path : new $.path.arc(arc_params)})
</pre>

Rotation
---
Rotation can be added to any path by specifying a rotator.

Example: keep the top of the element facing forward on the path

<pre>
var bezier_params = {
start: {
x: 185,
y: 185,
angle: 10
},
end: {
x:540,
y:110,
angle: -10,
length: 0.25
},
rotator: new $.path.rotators.followPath()
}

$("my_elem").animate({path : new $.path.bezier(bezier_params)})
</pre>

Example: make the element spin
<pre>
var spin_params = {
start: 30,
end: 200,
dir: -1
}

var bezier_params = {
start: {
x: 185,
y: 185,
angle: 10
},
end: {
x:540,
y:110,
angle: -10,
length: 0.25
},
rotator: new $.path.rotators.spin(spin_params)
}

$("my_elem").animate({path : new $.path.bezier(bezier_params)})
</pre>

Other Paths
----

Expand Down
106 changes: 92 additions & 14 deletions jquery.path.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* jQuery css bezier animation support -- Jonah Fox
* version 0.0.1
* version 0.0.3
* Released under the MIT license.
*/
/*
Expand All @@ -14,7 +14,13 @@

;(function($){

$.path = {};
$.path = {
isPath: function(path) {
return path &&
path.css &&
path.css.constructor == Function;
}
};

var V = {
rotate: function(p, degrees) {
Expand All @@ -34,7 +40,9 @@
}
};

$.path.bezier = function( params, rotate ) {
$.path.bezier = function(params) {
this.x = params.start.x;
this.y = params.start.y;
params.start = $.extend( {angle: 0, length: 0.3333}, params.start );
params.end = $.extend( {angle: 0, length: 0.3333}, params.end );

Expand All @@ -60,10 +68,6 @@
/* p from 0 to 1 */
this.css = function(p) {
var f1 = this.f1(p), f2 = this.f2(p), f3 = this.f3(p), f4=this.f4(p), css = {};
if (rotate) {
css.prevX = this.x;
css.prevY = this.y;
}
css.x = this.x = ( this.p1[0]*f1 + this.p2[0]*f2 +this.p3[0]*f3 + this.p4[0]*f4 +.5 )|0;
css.y = this.y = ( this.p1[1]*f1 + this.p2[1]*f2 +this.p3[1]*f3 + this.p4[1]*f4 +.5 )|0;
css.left = css.x + "px";
Expand All @@ -72,11 +76,10 @@
};
};

$.path.arc = function(params, rotate) {
$.path.arc = function(params) {
for ( var i in params ) {
this[i] = params[i];
}

this.dir = this.dir || 1;

while ( this.start > this.end && this.dir > 0 ) {
Expand All @@ -87,27 +90,102 @@
this.start += 360;
}

if(this.spiral) {
if(this.spiral.constructor == Array && this.spiral.length > 1) {
this.radiusStart = this.spiral[0] || 1;
this.radiusEnd = this.spiral[1] || 1;
} else {
this.radiusStart = 1;
this.radiusEnd = (this.spiral.constructor == Array ? this.spiral[0] : this.spiral) || 1;
}
this.radius = this.radiusStart;
this.radiusDiff = Math.abs(this.radiusEnd - this.radiusStart);
}

if($.path.isPath(this.center)) {
this.centerPath = this.center;
this.center = [0,0];
}

this.css = function(p) {
var a = ( this.start * (p ) + this.end * (1-(p )) ) * Math.PI / 180,
css = {};

if (rotate) {
css.prevX = this.x;
css.prevY = this.y;
if(this.centerPath) {
var pos = this.centerPath.css(p);
this.center[0] = pos.x;
this.center[1] = pos.y;
}

css.x = this.x = ( Math.sin(a) * this.radius + this.center[0] +.5 )|0;
css.y = this.y = ( Math.cos(a) * this.radius + this.center[1] +.5 )|0;
css.left = css.x + "px";
css.top = css.y + "px";

if(this.spiral) {
this.radius = this.radiusStart + (this.radiusDiff - (this.radiusDiff * p));
}

return css;
};
};

// rotators
$.path.rotators = {
isRotator: function(rotator) {
return rotator &&
rotator.rotate &&
rotator.rotate.constructor == Function &&
rotator.unit;
},
units: {
degrees: 'deg',
gradians: 'grad',
radians: 'rad',
turns: 'turn'
}
};

$.path.rotators.followPath = function() {
this.unit = $.path.rotators.units.radians;
this.rotate = function(p, css, prevState) {
return Math.atan2(prevState.y - css.y, prevState.x - css.x);
};
};

$.path.rotators.spin = function (params) {
this.unit = $.path.rotators.units.degrees;
for ( var i in params ) {
this[i] = params[i];
}
this.dir = this.dir || 1;

while ( this.start > this.end && this.dir > 0 ) {
this.start -= 360;
}

while ( this.start < this.end && this.dir < 0 ) {
this.start += 360;
}

this.diff = this.end - this.start;

this.rotate = function(p, css, prevCss) {
var pos = this.start - (this.diff - (this.diff * p));
return pos % 360;
};
};

$.fx.step.path = function(fx) {
var prevState = $.extend(true, {}, fx.end);
var css = fx.end.css( 1 - fx.pos );
if ( css.prevX != null ) {
$.cssHooks.transform.set( fx.elem, "rotate(" + Math.atan2(css.prevY - css.y, css.prevX - css.x) + ")" );

// note: rotation requires the transform CSS hook (https://github.com/brandonaaron/jquery-cssHooks/blob/master/transform.js)
if($.path.rotators.isRotator(fx.end.rotator) && $.cssHooks.transform) {
var rotation = fx.end.rotator.rotate(1 - fx.pos, css, prevState);
$.cssHooks.transform.set( fx.elem, "rotate(" + rotation + fx.end.rotator.unit + ")" );
}

fx.elem.style.top = css.top;
fx.elem.style.left = css.left;
};
Expand Down