Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
7272 amit.gupta 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);