xinyb
2024-09-19 18ffbca9acaccd5099a7a63652f52210f59a7e40
提交 | 用户 | age
a6a76f 1 // VERSION: 2.3 LAST UPDATE: 11.07.2013
F 2 /*
3  * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
4  *
5  * Made by Wilq32, wilq32@gmail.com, Wroclaw, Poland, 01.2009
6  * Website: http://jqueryrotate.com
7  */
8
9 (function($) {
10     var supportedCSS,supportedCSSOrigin, styles=document.getElementsByTagName("head")[0].style,toCheck="transformProperty WebkitTransform OTransform msTransform MozTransform".split(" ");
11     for (var a = 0; a < toCheck.length; a++) if (styles[toCheck[a]] !== undefined) { supportedCSS = toCheck[a]; }
12     if (supportedCSS) {
13       supportedCSSOrigin = supportedCSS.replace(/[tT]ransform/,"TransformOrigin");
14       if (supportedCSSOrigin[0] == "T") supportedCSSOrigin[0] = "t";
15     }
16
17     // Bad eval to preven google closure to remove it from code o_O
18     eval('IE = "v"=="\v"');
19
20     jQuery.fn.extend({
21         rotate:function(parameters)
22         {
23           if (this.length===0||typeof parameters=="undefined") return;
24           if (typeof parameters=="number") parameters={angle:parameters};
25           var returned=[];
26           for (var i=0,i0=this.length;i<i0;i++)
27           {
28             var element=this.get(i);
29             if (!element.Wilq32 || !element.Wilq32.PhotoEffect) {
30
31               var paramClone = $.extend(true, {}, parameters);
32               var newRotObject = new Wilq32.PhotoEffect(element,paramClone)._rootObj;
33
34               returned.push($(newRotObject));
35             }
36             else {
37               element.Wilq32.PhotoEffect._handleRotation(parameters);
38             }
39           }
40           return returned;
41         },
42         getRotateAngle: function(){
43           var ret = [0];
44           for (var i=0,i0=this.length;i<i0;i++)
45           {
46             var element=this.get(i);
47             if (element.Wilq32 && element.Wilq32.PhotoEffect) {
48               ret[i] = element.Wilq32.PhotoEffect._angle;
49             }
50           }
51           return ret;
52         },
53         stopRotate: function(){
54           for (var i=0,i0=this.length;i<i0;i++)
55           {
56             var element=this.get(i);
57             if (element.Wilq32 && element.Wilq32.PhotoEffect) {
58               clearTimeout(element.Wilq32.PhotoEffect._timer);
59             }
60           }
61         }
62     });
63
64     // Library agnostic interface
65
66     Wilq32=window.Wilq32||{};
67     Wilq32.PhotoEffect=(function(){
68
69       if (supportedCSS) {
70         return function(img,parameters){
71           img.Wilq32 = {
72             PhotoEffect: this
73           };
74
75           this._img = this._rootObj = this._eventObj = img;
76           this._handleRotation(parameters);
77         }
78       } else {
79         return function(img,parameters) {
80           this._img = img;
81           this._onLoadDelegate = [parameters];
82
83           this._rootObj=document.createElement('span');
84           this._rootObj.style.display="inline-block";
85           this._rootObj.Wilq32 =
86             {
87               PhotoEffect: this
88             };
89           img.parentNode.insertBefore(this._rootObj,img);
90
91           if (img.complete) {
92             this._Loader();
93           } else {
94             var self=this;
95             // TODO: Remove jQuery dependency
96             jQuery(this._img).bind("load", function(){ self._Loader(); });
97           }
98         }
99       }
100     })();
101
102     Wilq32.PhotoEffect.prototype = {
103       _setupParameters : function (parameters){
104         this._parameters = this._parameters || {};
105         if (typeof this._angle !== "number") { this._angle = 0 ; }
106         if (typeof parameters.angle==="number") { this._angle = parameters.angle; }
107         this._parameters.animateTo = (typeof parameters.animateTo === "number") ? (parameters.animateTo) : (this._angle);
108
109         this._parameters.step = parameters.step || this._parameters.step || null;
110         this._parameters.easing = parameters.easing || this._parameters.easing || this._defaultEasing;
111         this._parameters.duration = 'duration' in parameters ? parameters.duration : parameters.duration || this._parameters.duration || 1000;
112         this._parameters.callback = parameters.callback || this._parameters.callback || this._emptyFunction;
113         this._parameters.center = parameters.center || this._parameters.center || ["50%","50%"];
114         if (typeof this._parameters.center[0] == "string") {
115           this._rotationCenterX = (parseInt(this._parameters.center[0],10) / 100) * this._imgWidth * this._aspectW;
116         } else {
117           this._rotationCenterX = this._parameters.center[0];
118         }
119         if (typeof this._parameters.center[1] == "string") {
120           this._rotationCenterY = (parseInt(this._parameters.center[1],10) / 100) * this._imgHeight * this._aspectH;
121         } else {
122           this._rotationCenterY = this._parameters.center[1];
123         }
124
125         if (parameters.bind && parameters.bind != this._parameters.bind) { this._BindEvents(parameters.bind); }
126       },
127       _emptyFunction: function(){},
128       _defaultEasing: function (x, t, b, c, d) { return -c * ((t=t/d-1)*t*t*t - 1) + b },
129       _handleRotation : function(parameters, dontcheck){
130         if (!supportedCSS && !this._img.complete && !dontcheck) {
131           this._onLoadDelegate.push(parameters);
132           return;
133         }
134         this._setupParameters(parameters);
135         if (this._angle==this._parameters.animateTo) {
136           this._rotate(this._angle);
137         }
138         else {
139           this._animateStart();
140         }
141       },
142
143       _BindEvents:function(events){
144         if (events && this._eventObj)
145         {
146           // Unbinding previous Events
147           if (this._parameters.bind){
148             var oldEvents = this._parameters.bind;
149             for (var a in oldEvents) if (oldEvents.hasOwnProperty(a))
150               // TODO: Remove jQuery dependency
151               jQuery(this._eventObj).unbind(a,oldEvents[a]);
152           }
153
154         this._parameters.bind = events;
155         for (var a in events) if (events.hasOwnProperty(a))
156           // TODO: Remove jQuery dependency
157           jQuery(this._eventObj).bind(a,events[a]);
158         }
159       },
160
161       _Loader:(function()
162       {
163         if (IE)
164           return function() {
165             var width=this._img.width;
166             var height=this._img.height;
167             this._imgWidth = width;
168             this._imgHeight = height;
169             this._img.parentNode.removeChild(this._img);
170
171             this._vimage = this.createVMLNode('image');
172             this._vimage.src=this._img.src;
173             this._vimage.style.height=height+"px";
174             this._vimage.style.width=width+"px";
175             this._vimage.style.position="absolute"; // FIXES IE PROBLEM - its only rendered if its on absolute position!
176             this._vimage.style.top = "0px";
177             this._vimage.style.left = "0px";
178             this._aspectW = this._aspectH = 1;
179
180             /* Group minifying a small 1px precision problem when rotating object */
181             this._container = this.createVMLNode('group');
182             this._container.style.width=width;
183             this._container.style.height=height;
184             this._container.style.position="absolute";
185             this._container.style.top="0px";
186             this._container.style.left="0px";
187             this._container.setAttribute('coordsize',width-1+','+(height-1)); // This -1, -1 trying to fix ugly problem with small displacement on IE
188             this._container.appendChild(this._vimage);
189
190             this._rootObj.appendChild(this._container);
191             this._rootObj.style.position="relative"; // FIXES IE PROBLEM
192             this._rootObj.style.width=width+"px";
193             this._rootObj.style.height=height+"px";
194             this._rootObj.setAttribute('id',this._img.getAttribute('id'));
195             this._rootObj.className=this._img.className;
196             this._eventObj = this._rootObj;
197             var parameters;
198             while (parameters = this._onLoadDelegate.shift()) {
199               this._handleRotation(parameters, true);
200             }
201           }
202           else return function () {
203             this._rootObj.setAttribute('id',this._img.getAttribute('id'));
204             this._rootObj.className=this._img.className;
205
206             this._imgWidth=this._img.naturalWidth;
207             this._imgHeight=this._img.naturalHeight;
208             var _widthMax=Math.sqrt((this._imgHeight)*(this._imgHeight) + (this._imgWidth) * (this._imgWidth));
209             this._width = _widthMax * 3;
210             this._height = _widthMax * 3;
211
212             this._aspectW = this._img.offsetWidth/this._img.naturalWidth;
213             this._aspectH = this._img.offsetHeight/this._img.naturalHeight;
214
215             this._img.parentNode.removeChild(this._img);
216
217
218             this._canvas=document.createElement('canvas');
219             this._canvas.setAttribute('width',this._width);
220             this._canvas.style.position="relative";
221             this._canvas.style.left = -this._img.height * this._aspectW + "px";
222             this._canvas.style.top = -this._img.width * this._aspectH + "px";
223             this._canvas.Wilq32 = this._rootObj.Wilq32;
224
225             this._rootObj.appendChild(this._canvas);
226             this._rootObj.style.width=this._img.width*this._aspectW+"px";
227             this._rootObj.style.height=this._img.height*this._aspectH+"px";
228             this._eventObj = this._canvas;
229
230             this._cnv=this._canvas.getContext('2d');
231             var parameters;
232             while (parameters = this._onLoadDelegate.shift()) {
233               this._handleRotation(parameters, true);
234             }
235           }
236       })(),
237
238       _animateStart:function()
239       {
240         if (this._timer) {
241           clearTimeout(this._timer);
242         }
243         this._animateStartTime = +new Date;
244         this._animateStartAngle = this._angle;
245         this._animate();
246       },
247       _animate:function()
248       {
249         var actualTime = +new Date;
250         var checkEnd = actualTime - this._animateStartTime > this._parameters.duration;
251
252         // TODO: Bug for animatedGif for static rotation ? (to test)
253         if (checkEnd && !this._parameters.animatedGif)
254         {
255           clearTimeout(this._timer);
256         }
257         else
258         {
259           if (this._canvas||this._vimage||this._img) {
260             var angle = this._parameters.easing(0, actualTime - this._animateStartTime, this._animateStartAngle, this._parameters.animateTo - this._animateStartAngle, this._parameters.duration);
261             this._rotate((~~(angle*10))/10);
262           }
263           if (this._parameters.step) {
264             this._parameters.step(this._angle);
265           }
266           var self = this;
267           this._timer = setTimeout(function()
268           {
269             self._animate.call(self);
270           }, 10);
271         }
272
273       // To fix Bug that prevents using recursive function in callback I moved this function to back
274       if (this._parameters.callback && checkEnd){
275         this._angle = this._parameters.animateTo;
276         this._rotate(this._angle);
277         this._parameters.callback.call(this._rootObj);
278       }
279       },
280
281       _rotate : (function()
282       {
283         var rad = Math.PI/180;
284         if (IE)
285           return function(angle)
286         {
287           this._angle = angle;
288           this._container.style.rotation=(angle%360)+"deg";
289           this._vimage.style.top = -(this._rotationCenterY - this._imgHeight/2) + "px";
290           this._vimage.style.left = -(this._rotationCenterX - this._imgWidth/2) + "px";
291           this._container.style.top = this._rotationCenterY - this._imgHeight/2 + "px";
292           this._container.style.left = this._rotationCenterX - this._imgWidth/2 + "px";
293
294         }
295           else if (supportedCSS)
296           return function(angle){
297             this._angle = angle;
298             this._img.style[supportedCSS]="rotate("+(angle%360)+"deg)";
299             this._img.style[supportedCSSOrigin]=this._parameters.center.join(" ");
300           }
301           else
302             return function(angle)
303           {
304             this._angle = angle;
305             angle=(angle%360)* rad;
306             // clear canvas
307             this._canvas.width = this._width;//+this._widthAdd;
308             this._canvas.height = this._height;//+this._heightAdd;
309
310             // REMEMBER: all drawings are read from backwards.. so first function is translate, then rotate, then translate, translate..
311             this._cnv.translate(this._imgWidth*this._aspectW,this._imgHeight*this._aspectH);    // at least center image on screen
312             this._cnv.translate(this._rotationCenterX,this._rotationCenterY);            // we move image back to its orginal
313             this._cnv.rotate(angle);                                        // rotate image
314             this._cnv.translate(-this._rotationCenterX,-this._rotationCenterY);        // move image to its center, so we can rotate around its center
315             this._cnv.scale(this._aspectW,this._aspectH); // SCALE - if needed ;)
316             this._cnv.drawImage(this._img, 0, 0);                            // First - we draw image
317           }
318
319       })()
320       }
321
322       if (IE)
323       {
324         Wilq32.PhotoEffect.prototype.createVMLNode=(function(){
325           document.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");
326           try {
327             !document.namespaces.rvml && document.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
328             return function (tagName) {
329               return document.createElement('<rvml:' + tagName + ' class="rvml">');
330             };
331           } catch (e) {
332             return function (tagName) {
333               return document.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
334             };
335           }
336         })();
337       }
338
339 })(jQuery);