| 8842 |
anupam.sin |
1 |
// VERSION: 1.6 LAST UPDATE: 21.08.2010
|
|
|
2 |
/*
|
|
|
3 |
* THIS IS FREE SCRIPT BUT LEAVE THIS COMMENT IF
|
|
|
4 |
* YOU WANT USE THIS CODE ON YOUR SITE
|
|
|
5 |
*
|
|
|
6 |
* Made by Wilq32, wilq32@gmail.com, Wroclaw, Poland, 01.2009
|
|
|
7 |
* http://wilq32.blogspot.com
|
|
|
8 |
*
|
|
|
9 |
*/
|
|
|
10 |
/*
|
|
|
11 |
Description:
|
|
|
12 |
|
|
|
13 |
This is an final product of a Wilq32.PhotoEffect Snippet. Actually you can
|
|
|
14 |
use this simple and tiny script to get effect of rotated images directly
|
|
|
15 |
from client side (for ex. user generated content), and animate them using
|
|
|
16 |
own functions.
|
|
|
17 |
|
|
|
18 |
|
|
|
19 |
Notices:
|
|
|
20 |
|
|
|
21 |
Include script after including main jQuery. Whole plugin uses jQuery
|
|
|
22 |
namespace and should be compatible with older version (unchecked).
|
|
|
23 |
|
|
|
24 |
Usage:
|
|
|
25 |
|
|
|
26 |
jQuery(imgElement).rotate(angleValue)
|
|
|
27 |
jQuery(imgElement).rotate(parameters)
|
|
|
28 |
jQuery(imgElement).rotateAnimation(parameters)
|
|
|
29 |
jQuery(imgElement).rotateAnimation(parameters)
|
|
|
30 |
|
|
|
31 |
|
|
|
32 |
|
|
|
33 |
Returns:
|
|
|
34 |
|
|
|
35 |
jQueryRotateElement - !!! NOTICE !!! function return rotateElement
|
|
|
36 |
instance to help connect events with actually created 'rotation' element.
|
|
|
37 |
|
|
|
38 |
Parameters:
|
|
|
39 |
|
|
|
40 |
({angle:angleValue,
|
|
|
41 |
[animateAngle:animateAngleValue],
|
|
|
42 |
[maxAngle:maxAngleValue],
|
|
|
43 |
[minAngle:minAngleValue],
|
|
|
44 |
[callback:callbackFunction],
|
|
|
45 |
[animatedGif:animatedGifBoolean],
|
|
|
46 |
[bind:[{event: function},{event:function} ] })
|
|
|
47 |
jQuery(imgElement).rotateAnimation
|
|
|
48 |
|
|
|
49 |
Where:
|
|
|
50 |
|
|
|
51 |
- angleValue - clockwise rotation given in degrees,
|
|
|
52 |
- [animateAngleValue] - optional parameter, animate rotating into this value,
|
|
|
53 |
- [maxAngleValue] - optional parameter, maximum angle possible for animation,
|
|
|
54 |
- [minAngleValue] - optional parameter, minimum angle possible for animation,
|
|
|
55 |
- [callbackFunction] - optional function to run after animation is done
|
|
|
56 |
- [animatedGifBoolean](boolean) - optional set to display animated gif in firefox/chrome/safari
|
|
|
57 |
!!! this might slow down browser because it need to render image again and
|
|
|
58 |
again to display animation,
|
|
|
59 |
- [bind: [ {event: function}...] -optional parameter, list of events binded
|
|
|
60 |
to newly created rotateable object
|
|
|
61 |
|
|
|
62 |
Examples:
|
|
|
63 |
|
|
|
64 |
$(document).ready(function()
|
|
|
65 |
{
|
|
|
66 |
$('#image').rotate(-25);
|
|
|
67 |
});
|
|
|
68 |
|
|
|
69 |
$(document).ready(function()
|
|
|
70 |
{
|
|
|
71 |
$('#image2').rotate({angle:5});
|
|
|
72 |
});
|
|
|
73 |
|
|
|
74 |
$(document).ready(function()
|
|
|
75 |
{
|
|
|
76 |
var rot=$('#image3').rotate({maxAngle:25,minAngle:-55,
|
|
|
77 |
bind:
|
|
|
78 |
[
|
|
|
79 |
{"mouseover":function(){rot[0].rotateAnimation(85);}},
|
|
|
80 |
{"mouseout":function(){rot[0].rotateAnimation(-35);}}
|
|
|
81 |
]
|
|
|
82 |
});
|
|
|
83 |
});
|
|
|
84 |
*/
|
|
|
85 |
|
|
|
86 |
(function($) {
|
|
|
87 |
var supportedCSS,styles=document.getElementsByTagName("head")[0].style,toCheck="transformProperty WebkitTransform OTransform".split(" "); //MozTransform <- firefox works slower with css!!!
|
|
|
88 |
for (var a=0;a<toCheck.length;a++) if (styles[toCheck[a]] !== undefined) supportedCSS = toCheck[a];
|
|
|
89 |
var IE = "v"=="\v";
|
|
|
90 |
|
|
|
91 |
jQuery.fn.extend({
|
|
|
92 |
ImageRotate:function(parameters)
|
|
|
93 |
{
|
|
|
94 |
// If this element is already a Wilq32.PhotoEffect object, skip creation
|
|
|
95 |
if (this.Wilq32&&this.Wilq32.PhotoEffect) return;
|
|
|
96 |
// parameters might be applied to many objects - so because we use them later - a fresh instance is needed
|
|
|
97 |
var paramClone = $.extend(true, {}, parameters);
|
|
|
98 |
return (new Wilq32.PhotoEffect(this.get(0),paramClone))._temp;
|
|
|
99 |
},
|
|
|
100 |
rotate:function(parameters)
|
|
|
101 |
{
|
|
|
102 |
if (this.length===0||typeof parameters=="undefined") return;
|
|
|
103 |
if (typeof parameters=="number") parameters={angle:parameters};
|
|
|
104 |
var returned=[];
|
|
|
105 |
for (var i=0,i0=this.length;i<i0;i++)
|
|
|
106 |
{
|
|
|
107 |
var element=this.get(i);
|
|
|
108 |
if (typeof element.Wilq32 == "undefined")
|
|
|
109 |
returned.push($($(element).ImageRotate(parameters)));
|
|
|
110 |
else
|
|
|
111 |
{
|
|
|
112 |
element.Wilq32.PhotoEffect._rotate(parameters.angle);
|
|
|
113 |
}
|
|
|
114 |
}
|
|
|
115 |
return returned;
|
|
|
116 |
},
|
|
|
117 |
|
|
|
118 |
rotateAnimation:function(parameters)
|
|
|
119 |
{
|
|
|
120 |
if (this.length===0||typeof parameters=="undefined") return;
|
|
|
121 |
if (typeof parameters=="number") parameters={animateAngle:parameters};
|
|
|
122 |
var returned=[];
|
|
|
123 |
for (var i=0,i0=this.length;i<i0;i++)
|
|
|
124 |
{
|
|
|
125 |
var element=this.get(i);
|
|
|
126 |
if (typeof element.Wilq32 == "undefined")
|
|
|
127 |
returned.push($($(element).ImageRotate(parameters)));
|
|
|
128 |
else
|
|
|
129 |
{
|
|
|
130 |
element.Wilq32.PhotoEffect.rotateAnimation(parameters);
|
|
|
131 |
}
|
|
|
132 |
}
|
|
|
133 |
return returned;
|
|
|
134 |
}
|
|
|
135 |
|
|
|
136 |
});
|
|
|
137 |
|
|
|
138 |
// Library agnostic interface
|
|
|
139 |
|
|
|
140 |
Wilq32=window.Wilq32||{};
|
|
|
141 |
Wilq32.PhotoEffect=(function(){
|
|
|
142 |
function setupParameters(img,parameters){
|
|
|
143 |
this._img = img;
|
|
|
144 |
this._parameters = parameters || {};
|
|
|
145 |
this._parameters.angle = this._angle = parameters.angle || 0;
|
|
|
146 |
this._parameters.animateAngle = typeof parameters.animateAngle=="number" ? parameters.animateAngle : this._angle;
|
|
|
147 |
|
|
|
148 |
}
|
|
|
149 |
if (supportedCSS) {
|
|
|
150 |
return function(img,parameters){
|
|
|
151 |
setupParameters.call(this,img,parameters);
|
|
|
152 |
img.Wilq32 = {
|
|
|
153 |
PhotoEffect: this
|
|
|
154 |
};
|
|
|
155 |
// TODO: needed to have a _temp variable accessible outside - used for object retrieval,
|
|
|
156 |
// needs refactor + change name (temp is not self descriptive)
|
|
|
157 |
// also need better passing values between functions - to FIX (remove _temp and _img at all)
|
|
|
158 |
this._temp = this._img;
|
|
|
159 |
this._BindEvents(img,this._parameters.bind);
|
|
|
160 |
this._rotate(this._parameters.angle);
|
|
|
161 |
if (this._parameters.angle!=this._parameters.animateAngle) this.rotateAnimation(this._parameters);
|
|
|
162 |
};
|
|
|
163 |
} else {
|
|
|
164 |
return function(img,parameters) {
|
|
|
165 |
setupParameters.call(this,img,parameters);
|
|
|
166 |
// Make sure that class and id are also copied - just in case you would like to refeer to an newly created object
|
|
|
167 |
this._parameters.className=img.className;
|
|
|
168 |
this._parameters.id=img.getAttribute('id');
|
|
|
169 |
|
|
|
170 |
this._temp=document.createElement('span');
|
|
|
171 |
this._temp.style.display="inline-block";
|
|
|
172 |
this._temp.Wilq32 =
|
|
|
173 |
{
|
|
|
174 |
PhotoEffect: this
|
|
|
175 |
};
|
|
|
176 |
img.parentNode.insertBefore(this._temp,img);
|
|
|
177 |
|
|
|
178 |
if (img.complete) {
|
|
|
179 |
this._Loader();
|
|
|
180 |
} else {
|
|
|
181 |
var self=this;
|
|
|
182 |
// TODO: Remove jQuery dependency
|
|
|
183 |
jQuery(this._img).bind("load", function()
|
|
|
184 |
{
|
|
|
185 |
self._Loader();
|
|
|
186 |
});
|
|
|
187 |
}
|
|
|
188 |
};
|
|
|
189 |
}
|
|
|
190 |
})();
|
|
|
191 |
|
|
|
192 |
Wilq32.PhotoEffect.prototype={
|
|
|
193 |
|
|
|
194 |
rotateAnimation : function(parameters){
|
|
|
195 |
this._parameters.animateAngle = parameters.animateAngle;
|
|
|
196 |
this._parameters.callback = parameters.callback || this._parameters.callback || function(){};
|
|
|
197 |
this._animateStart();
|
|
|
198 |
},
|
|
|
199 |
|
|
|
200 |
_BindEvents:function(element,events){
|
|
|
201 |
if (events)
|
|
|
202 |
{
|
|
|
203 |
for (var a in events) if (events.hasOwnProperty(a))
|
|
|
204 |
for (var b in events[a]) if (events[a].hasOwnProperty(b))
|
|
|
205 |
// TODO: Remove jQuery dependency
|
|
|
206 |
jQuery(element).bind(b,events[a][b]);
|
|
|
207 |
}
|
|
|
208 |
},
|
|
|
209 |
|
|
|
210 |
_Loader:(function()
|
|
|
211 |
{
|
|
|
212 |
if (IE)
|
|
|
213 |
return function()
|
|
|
214 |
{
|
|
|
215 |
var width=this._img.width;
|
|
|
216 |
var height=this._img.height;
|
|
|
217 |
this._img.parentNode.removeChild(this._img);
|
|
|
218 |
|
|
|
219 |
this._vimage = this.createVMLNode('image');
|
|
|
220 |
this._vimage.src=this._img.src;
|
|
|
221 |
this._vimage.style.height=height+"px";
|
|
|
222 |
this._vimage.style.width=width+"px";
|
|
|
223 |
this._vimage.style.position="absolute"; // FIXES IE PROBLEM - its only rendered if its on absolute position!
|
|
|
224 |
this._vimage.style.top = "0px";
|
|
|
225 |
this._vimage.style.left = "0px";
|
|
|
226 |
|
|
|
227 |
/* Group minifying a small 1px precision problem when rotating object */
|
|
|
228 |
this._container = this.createVMLNode('group');
|
|
|
229 |
this._container.style.width=width;
|
|
|
230 |
this._container.style.height=height;
|
|
|
231 |
this._container.style.position="absolute";
|
|
|
232 |
this._container.setAttribute('coordsize',width-1+','+(height-1)); // This -1, -1 trying to fix that ugly problem
|
|
|
233 |
this._container.appendChild(this._vimage);
|
|
|
234 |
|
|
|
235 |
this._temp.appendChild(this._container);
|
|
|
236 |
this._temp.style.position="relative"; // FIXES IE PROBLEM
|
|
|
237 |
this._temp.style.width=width+"px";
|
|
|
238 |
this._temp.style.height=height+"px";
|
|
|
239 |
this._temp.setAttribute('id',this._parameters.id);
|
|
|
240 |
this._temp.className=this._parameters.className;
|
|
|
241 |
|
|
|
242 |
this._BindEvents(this._temp,this._parameters.bind);
|
|
|
243 |
_finally.call(this);
|
|
|
244 |
|
|
|
245 |
};
|
|
|
246 |
else
|
|
|
247 |
return function ()
|
|
|
248 |
{
|
|
|
249 |
this._temp.setAttribute('id',this._parameters.id);
|
|
|
250 |
this._temp.className=this._parameters.className;
|
|
|
251 |
|
|
|
252 |
this._width=this._img.width;
|
|
|
253 |
this._height=this._img.height;
|
|
|
254 |
this._widthHalf=this._width/2; // used for optimisation
|
|
|
255 |
this._heightHalf=this._height/2;// used for optimisation
|
|
|
256 |
|
|
|
257 |
var _widthMax=Math.sqrt((this._height)*(this._height) + (this._width) * (this._width));
|
|
|
258 |
|
|
|
259 |
this._widthAdd = _widthMax - this._width;
|
|
|
260 |
this._heightAdd = _widthMax - this._height; // widthMax because maxWidth=maxHeight
|
|
|
261 |
this._widthAddHalf=this._widthAdd/2; // used for optimisation
|
|
|
262 |
this._heightAddHalf=this._heightAdd/2;// used for optimisation
|
|
|
263 |
|
|
|
264 |
this._img.parentNode.removeChild(this._img);
|
|
|
265 |
|
|
|
266 |
|
|
|
267 |
this._canvas=document.createElement('canvas');
|
|
|
268 |
this._canvas.setAttribute('width',this._width);
|
|
|
269 |
this._canvas.style.position="relative";
|
|
|
270 |
this._canvas.style.left = -this._widthAddHalf + "px";
|
|
|
271 |
this._canvas.style.top = -this._heightAddHalf + "px";
|
|
|
272 |
this._canvas.Wilq32 = this._temp.Wilq32;
|
|
|
273 |
|
|
|
274 |
this._temp.appendChild(this._canvas);
|
|
|
275 |
this._temp.style.width=this._width+"px";
|
|
|
276 |
this._temp.style.height=this._height+"px";
|
|
|
277 |
|
|
|
278 |
this._BindEvents(this._canvas,this._parameters.bind);
|
|
|
279 |
this._cnv=this._canvas.getContext('2d');
|
|
|
280 |
_finally.call(this);
|
|
|
281 |
};
|
|
|
282 |
function _finally(){
|
|
|
283 |
this._rotate(this._parameters.angle);
|
|
|
284 |
if (this._parameters.angle!=this._parameters.animateAngle) this.rotateAnimation(this._parameters);
|
|
|
285 |
}
|
|
|
286 |
|
|
|
287 |
})(),
|
|
|
288 |
|
|
|
289 |
_animateStart:function()
|
|
|
290 |
{
|
|
|
291 |
if (this._timer) {
|
|
|
292 |
clearTimeout(this._timer);
|
|
|
293 |
}
|
|
|
294 |
this._animate();
|
|
|
295 |
},
|
|
|
296 |
_animate:function()
|
|
|
297 |
{
|
|
|
298 |
var checkEnd = !!(Math.round(this._angle * 100 - this._parameters.animateAngle * 100)) == 0 && !!this._timer;
|
|
|
299 |
|
|
|
300 |
if (this._parameters.callback && checkEnd){
|
|
|
301 |
this._parameters.callback();
|
|
|
302 |
}
|
|
|
303 |
|
|
|
304 |
// TODO: Bug for animatedGif for static rotation ? (to test)
|
|
|
305 |
if (checkEnd && !this._parameters.animatedGif)
|
|
|
306 |
{
|
|
|
307 |
clearTimeout(this._timer);
|
|
|
308 |
}
|
|
|
309 |
else
|
|
|
310 |
{
|
|
|
311 |
if (this._canvas||this._vimage||this._img) {
|
|
|
312 |
// TODO: implement easing and speed of animation
|
|
|
313 |
this._angle-=(this._angle-this._parameters.animateAngle)*0.1;
|
|
|
314 |
if (typeof this._parameters.minAngle!="undefined") this._angle=Math.max(this._angle,this._parameters.minAngle);
|
|
|
315 |
if (typeof this._parameters.maxAngle!="undefined") this._angle=Math.min(this._angle,this._parameters.maxAngle);
|
|
|
316 |
this._rotate((~~(this._angle*10))/10);
|
|
|
317 |
}
|
|
|
318 |
var self = this;
|
|
|
319 |
this._timer = setTimeout(function()
|
|
|
320 |
{
|
|
|
321 |
self._animate.call(self);
|
|
|
322 |
}, 10);
|
|
|
323 |
}
|
|
|
324 |
},
|
|
|
325 |
|
|
|
326 |
_rotate : (function()
|
|
|
327 |
{
|
|
|
328 |
var rad = Math.PI/180;
|
|
|
329 |
if (IE)
|
|
|
330 |
return function(angle)
|
|
|
331 |
{
|
|
|
332 |
this._container.style.rotation=angle+"deg";
|
|
|
333 |
};
|
|
|
334 |
else if (supportedCSS)
|
|
|
335 |
return function(angle){
|
|
|
336 |
this._img.style[supportedCSS]="rotate("+angle+"deg)";
|
|
|
337 |
};
|
|
|
338 |
else
|
|
|
339 |
return function(angle)
|
|
|
340 |
{
|
|
|
341 |
|
|
|
342 |
if (!this._img.width||typeof angle!="number") return;
|
|
|
343 |
angle=(angle%360)* rad;
|
|
|
344 |
// clear canvas
|
|
|
345 |
this._canvas.width = this._width+this._widthAdd;
|
|
|
346 |
this._canvas.height = this._height+this._heightAdd;
|
|
|
347 |
|
|
|
348 |
//TODO: Implement scaling for fixed image size
|
|
|
349 |
//this._cnv.scale(0.8,0.8); // SCALE - if needed ;)
|
|
|
350 |
|
|
|
351 |
// REMEMBER: all drawings are read from backwards.. so first function is translate, then rotate, then translate, translate..
|
|
|
352 |
this._cnv.translate(this._widthAddHalf,this._heightAddHalf); // at least center image on screen
|
|
|
353 |
this._cnv.translate(this._widthHalf,this._heightHalf); // we move image back to its orginal
|
|
|
354 |
this._cnv.rotate(angle); // rotate image
|
|
|
355 |
this._cnv.translate(-this._widthHalf,-this._heightHalf); // move image to its center, so we can rotate around its center
|
|
|
356 |
this._cnv.drawImage(this._img, 0, 0); // First - we draw image
|
|
|
357 |
};
|
|
|
358 |
|
|
|
359 |
})()
|
|
|
360 |
};
|
|
|
361 |
|
|
|
362 |
if (IE)
|
|
|
363 |
{
|
|
|
364 |
Wilq32.PhotoEffect.prototype.createVMLNode=(function(){
|
|
|
365 |
document.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");
|
|
|
366 |
try {
|
|
|
367 |
!document.namespaces.rvml && document.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
|
|
|
368 |
return function (tagName) {
|
|
|
369 |
return document.createElement('<rvml:' + tagName + ' class="rvml">');
|
|
|
370 |
};
|
|
|
371 |
} catch (e) {
|
|
|
372 |
return function (tagName) {
|
|
|
373 |
return document.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
|
|
|
374 |
};
|
|
|
375 |
}
|
|
|
376 |
})();
|
|
|
377 |
}
|
|
|
378 |
|
|
|
379 |
})(jQuery);
|