Permalink
Browse files

Add rotate option + lint the code

  • Loading branch information...
1 parent 37ccab5 commit 65c0117d81d17ad6062b6d114e5a6178e55ca408 louisremi committed May 16, 2011
Showing with 86 additions and 72 deletions.
  1. +86 −72 jquery.path.js
View
158 jquery.path.js
@@ -14,88 +14,102 @@
;(function($){
- $.path = {}
-
+ $.path = {};
var V = {
rotate: function(p, degrees) {
- var radians = degrees * 3.141592654 / 180
- var c = Math.cos(radians), s = Math.sin(radians)
- return [c*p[0] - s*p[1], s*p[0] + c*p[1] ]
+ var radians = degrees * Math.PI / 180,
+ c = Math.cos(radians),
+ s = Math.sin(radians);
+ return [c*p[0] - s*p[1], s*p[0] + c*p[1]];
},
scale: function(p, n) {
- return [n*p[0], n*p[1]]
+ return [n*p[0], n*p[1]];
},
add: function(a, b) {
- return [a[0]+b[0], a[1]+b[1]]
+ return [a[0]+b[0], a[1]+b[1]];
},
minus: function(a, b) {
- return [a[0]-b[0], a[1]-b[1]]
+ return [a[0]-b[0], a[1]-b[1]];
+ }
+ };
+
+ $.path.bezier = function( params, rotate ) {
+ params.start = $.extend( {angle: 0, length: 0.3333}, params.start );
+ params.end = $.extend( {angle: 0, length: 0.3333}, params.end );
+
+ this.p1 = [params.start.x, params.start.y];
+ this.p4 = [params.end.x, params.end.y];
+
+ var v14 = V.minus( this.p4, this.p1 ),
+ v12 = V.scale( v14, params.start.length ),
+ v41 = V.scale( v14, -1 ),
+ v43 = V.scale( v41, params.end.length );
+
+ v12 = V.rotate( v12, params.start.angle );
+ this.p2 = V.add( this.p1, v12 );
+
+ v43 = V.rotate(v43, params.end.angle );
+ this.p3 = V.add( this.p4, v43 );
+
+ this.f1 = function(t) { return (t*t*t); };
+ this.f2 = function(t) { return (3*t*t*(1-t)); };
+ this.f3 = function(t) { return (3*t*(1-t)*(1-t)); };
+ this.f4 = function(t) { return ((1-t)*(1-t)*(1-t)); };
+
+ /* 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";
+ css.top = css.y + "px";
+ return css;
+ };
+ };
+
+ $.path.arc = function(params, rotate) {
+ for ( var i in params ) {
+ this[i] = params[i];
}
- }
-
- $.path.bezier = function( params ) {
- params.start = $.extend({angle: 0, length: 0.3333}, params.start )
- params.end = $.extend({angle: 0, length: 0.3333}, params.end )
-
- this.p1 = [params.start.x, params.start.y];
- this.p4 = [params.end.x, params.end.y];
-
- var v14 = V.minus(this.p4, this.p1)
- var v12 = V.scale(v14, params.start.length)
- v12 = V.rotate(v12, params.start.angle)
- this.p2 = V.add(this.p1, v12)
-
- var v41 = V.scale(v14, -1)
- var v43 = V.scale(v41, params.end.length)
- v43 = V.rotate(v43, params.end.angle)
- this.p3 = V.add(this.p4, v43)
-
- this.f1 = function(t) { return (t*t*t); }
- this.f2 = function(t) { return (3*t*t*(1-t)); }
- this.f3 = function(t) { return (3*t*(1-t)*(1-t)); }
- this.f4 = function(t) { return ((1-t)*(1-t)*(1-t)); }
-
- /* 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)
- var x = this.p1[0]*f1 + this.p2[0]*f2 +this.p3[0]*f3 + this.p4[0]*f4;
- var y = this.p1[1]*f1 + this.p2[1]*f2 +this.p3[1]*f3 + this.p4[1]*f4;
- return {top: y + "px", left: x + "px"}
- }
- }
-
- $.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)
- this.start -= 360
-
- while(this.start < this.end && this.dir < 0)
- this.start += 360
-
-
- this.css = function(p) {
- var a = this.start * (p ) + this.end * (1-(p ))
- a = a * 3.1415927 / 180 // to radians
-
- var x = Math.sin(a) * this.radius + this.center[0]
- var y = Math.cos(a) * this.radius + this.center[1]
- return {top: y + "px", left: x + "px"}
- }
-
- };
-
-
- $.fx.step.path = function(fx){
- var css = fx.end.css(1 - fx.pos)
- for(var i in css)
- fx.elem.style[i] = css[i];
- }
-})(jQuery);
+ 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.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;
+ }
+ 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";
+ return css;
+ };
+ };
+
+ $.fx.step.path = function(fx) {
+ 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) + ")" );
+ }
+ fx.elem.style.top = css.top;
+ fx.elem.style.left = css.left;
+ };
+})(jQuery);

4 comments on commit 65c0117

@DanielSchaffer

Can you add some examples of using the rotate option? I'd like to use it, but I couldn't get it to work, and there's nothing in the documentation about it.

@socialblogsite

Ditto. "rotate" doesn't work as a parameter of any of the used functions.
Possible missing code? Keep reading:

I'm trying to store somewhere the value of the last step angle, to pick-up the next animation right where this one was stop()ed, and I can't get it to work. (Without manually coding the whole step in my code (which defeats the whole purpose of this plugin)
(I don't want to rotate the elements itself)

The closest I've been is adding a css.rightMargin to fx.elem.style and later removing the px from the value… but after hours of trying to send the angle right to the element.data or as a custom $.cssHooks["currAngle"]… so now I just noticed the element is NEVER rotated, because prevX is NEVER setup.
I tried setting rotate: true everywhere, no success. Where should it go?

Do you think a better way to send it to the element? (keeping the elegancy of this plugin)

@DanielSchaffer

@socialblogsite Check out my fork - https://github.com/DanielSchaffer/jquery.path (note: I submitted a pull request here 2 weeks ago, but haven't seen any response yet)

I've added the ability to rotate, including what I believe to have been the intended functionality for this (keeping the element "faced forward" along the path), and also adding a spin using options similar to the arc path. Please note that using rotation requires the transform css hook (https://github.com/brandonaaron/jquery-cssHooks/blob/master/transform.js) - the "rotate" code here is also dependent on it, though it's not documented anywhere.

If my fork doesn't get you where you need to go on its own, I've also added the concept of a separate "rotator" module that can be used with any path, so you should be able to add your own rotator that does what you need.

@socialblogsite

Oh, thanks.
I did add the proper cssHook for the property I created… but never tried deleting yours, which was probably preventing the whole script from working.
Ohhh… now I realize I use jquery.transform for that!!
I believed the cssHook for transform was included in the new version of jQuery :(

Does the separate "rotator" module provide the step-by-step angle to be used somewhere else?

…cause I don't need to rotate something else, nor get another value animated. I just need to output (or hook into some part of path functions to retrieve it ?) the angle at the time the animation is stopped in any way.

I first aimed to calculate the angle (again) from the current position from the outside, but it ended up being a pain when combined with an extra rotation I'm added to the whole thing (you can see it at the page in construction http://flakeyfish.com/hangouts/ )
(so far it works in chrome and you need a to be logged into facebook for it to work) (renders 20 friends of yours in an animated wheel)

As you can see, I modified the original jquery.path.js to send the value as marginRight, since it's irrelevant anyway for a floated element ;)
as I found out css properties unknown by the browser are ignored anyway (I thought they would work at least in jQuery context regardless of being rendered or not)

I'm not an expert coder other than css and enough Wordpress to do what you see there, so the code you see there is more than sloppy, hehe. I'm sure all that script and the whole path plugin could have been replaced by 10 lines of code, but… I've got what I needed :)

Thanks for your answer, Daniel.

Please sign in to comment.