eads@18
|
1 <!DOCTYPE html> |
eads@18
|
2 |
eads@18
|
3 <!-- |
eads@18
|
4 |
eads@18
|
5 Copyright 2006 Google Inc. |
eads@18
|
6 |
eads@18
|
7 Licensed under the Apache License, Version 2.0 (the "License"); |
eads@18
|
8 you may not use this file except in compliance with the License. |
eads@18
|
9 You may obtain a copy of the License at |
eads@18
|
10 |
eads@18
|
11 http://www.apache.org/licenses/LICENSE-2.0 |
eads@18
|
12 |
eads@18
|
13 Unless required by applicable law or agreed to in writing, software |
eads@18
|
14 distributed under the License is distributed on an "AS IS" BASIS, |
eads@18
|
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
eads@18
|
16 See the License for the specific language governing permissions and |
eads@18
|
17 limitations under the License. |
eads@18
|
18 |
eads@18
|
19 --> |
eads@18
|
20 |
eads@18
|
21 <html> |
eads@18
|
22 <head> |
eads@18
|
23 <title></title> |
eads@18
|
24 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> |
eads@18
|
25 <!--[if IE]><script type="text/javascript" src="../excanvas.js"></script><![endif]--> |
eads@18
|
26 <style type="text/css"> |
eads@18
|
27 |
eads@18
|
28 body { |
eads@18
|
29 overflow: hidden; |
eads@18
|
30 width: 100%; |
eads@18
|
31 height: 100%; |
eads@18
|
32 margin: 0; |
eads@18
|
33 } |
eads@18
|
34 |
eads@18
|
35 #image-rotator { |
eads@18
|
36 position: absolute; |
eads@18
|
37 left: 0; |
eads@18
|
38 top: 0; |
eads@18
|
39 width: 100%; |
eads@18
|
40 height: 100%; |
eads@18
|
41 } |
eads@18
|
42 |
eads@18
|
43 #image-rotator .tool-bar { |
eads@18
|
44 text-align: center; |
eads@18
|
45 } |
eads@18
|
46 |
eads@18
|
47 .tool-bar button { |
eads@18
|
48 margin: 0.5em 0.5em 0 0; |
eads@18
|
49 } |
eads@18
|
50 |
eads@18
|
51 #image-rotator img, |
eads@18
|
52 #image-rotator canvas { |
eads@18
|
53 position: absolute; |
eads@18
|
54 } |
eads@18
|
55 |
eads@18
|
56 </style> |
eads@18
|
57 <script type="text/javascript"> |
eads@18
|
58 |
eads@18
|
59 function sawFunc(a) { |
eads@18
|
60 var PI = Math.PI; |
eads@18
|
61 var PI2 = PI / 2; |
eads@18
|
62 // make sure a is within 0 to PI |
eads@18
|
63 a = a % PI; |
eads@18
|
64 if (a < 0) { |
eads@18
|
65 a += PI; |
eads@18
|
66 } |
eads@18
|
67 if (a < PI2) { |
eads@18
|
68 return a / PI2; |
eads@18
|
69 } else { |
eads@18
|
70 return (PI - a) / PI2; |
eads@18
|
71 } |
eads@18
|
72 } |
eads@18
|
73 |
eads@18
|
74 function easeInEaseOut(t) { |
eads@18
|
75 var t2 = t * t; |
eads@18
|
76 return 3 * t2 - 2 * t * t2; |
eads@18
|
77 } |
eads@18
|
78 |
eads@18
|
79 function ImageRotator(el, src, w, h) { |
eads@18
|
80 this.element = el; |
eads@18
|
81 this.toolBar = el.getElementsByTagName("div")[0]; |
eads@18
|
82 this.canvas = el.getElementsByTagName("canvas")[0]; |
eads@18
|
83 var images = el.getElementsByTagName("img"); |
eads@18
|
84 this.image = images[images.length - 1]; |
eads@18
|
85 var btns = el.getElementsByTagName("button"); |
eads@18
|
86 this.btnCw = btns[0]; |
eads@18
|
87 this.btnCcw = btns[1]; |
eads@18
|
88 var self = this; |
eads@18
|
89 this.btnCcw.onclick = function () { |
eads@18
|
90 self.rotateCcw(); |
eads@18
|
91 }; |
eads@18
|
92 this.btnCw.onclick = function () { |
eads@18
|
93 self.rotateCw(); |
eads@18
|
94 }; |
eads@18
|
95 this.image.onload = function (e) { |
eads@18
|
96 self.onImageLoad(e); |
eads@18
|
97 }; |
eads@18
|
98 this.image.onerror = function (e) { |
eads@18
|
99 self.onImageError(e); |
eads@18
|
100 }; |
eads@18
|
101 this.image.onabort = function (e) { |
eads@18
|
102 self.onImageAbort(e); |
eads@18
|
103 }; |
eads@18
|
104 this.setImage(src, w, h); |
eads@18
|
105 this.layout(); |
eads@18
|
106 |
eads@18
|
107 var onResize = function () { |
eads@18
|
108 self.layout(); |
eads@18
|
109 }; |
eads@18
|
110 var onLoad = function () { |
eads@18
|
111 self.onWindowLoad(); |
eads@18
|
112 }; |
eads@18
|
113 if (window.addEventListener) { |
eads@18
|
114 window.addEventListener("resize", onResize, false); |
eads@18
|
115 window.addEventListener("load", onLoad, false); |
eads@18
|
116 } else if (window.attachEvent) { |
eads@18
|
117 window.attachEvent("onresize", onResize); |
eads@18
|
118 window.attachEvent("onload", onLoad); |
eads@18
|
119 } |
eads@18
|
120 } |
eads@18
|
121 |
eads@18
|
122 ImageRotator.prototype = { |
eads@18
|
123 getLoaded: function () { |
eads@18
|
124 return this.imageLoaded && this.windowLoaded; |
eads@18
|
125 }, |
eads@18
|
126 setImage: function (src, w, h) { |
eads@18
|
127 this.imageLoaded = false; |
eads@18
|
128 this.image.src = src; |
eads@18
|
129 this.imageWidth = w; |
eads@18
|
130 this.imageHeight = h; |
eads@18
|
131 }, |
eads@18
|
132 |
eads@18
|
133 layout: function () { |
eads@18
|
134 var PI2 = Math.PI / 2; |
eads@18
|
135 var h = this.element.clientHeight; |
eads@18
|
136 var w = this.element.clientWidth; |
eads@18
|
137 var th = this.toolBar.offsetHeight; |
eads@18
|
138 h -= this.toolBar.offsetHeight; |
eads@18
|
139 if (!this.ctx || !this.getLoaded()) { |
eads@18
|
140 this.btnCw.disabled = true; |
eads@18
|
141 this.btnCcw.disabled = true; |
eads@18
|
142 this.canvas.style.display = "none"; |
eads@18
|
143 this.image.style.display = "block"; |
eads@18
|
144 var ratio = Math.min(w / this.imageWidth, h / this.imageHeight, 1); |
eads@18
|
145 var imgW = this.imageWidth * ratio; |
eads@18
|
146 var imgH = this.imageHeight * ratio; |
eads@18
|
147 var y = th + (h - imgH) / 2; |
eads@18
|
148 var x = (w - imgW) / 2; |
eads@18
|
149 this.image.style.left = Math.round(x) + "px"; |
eads@18
|
150 this.image.style.top = Math.round(y) + "px"; |
eads@18
|
151 this.image.style.width = Math.round(imgW) + "px"; |
eads@18
|
152 this.image.style.height = Math.round(imgH) + "px"; |
eads@18
|
153 } else { |
eads@18
|
154 this.btnCw.disabled = this.isAnimating_; |
eads@18
|
155 this.btnCcw.disabled = this.isAnimating_; |
eads@18
|
156 this.canvas.style.display = "block"; |
eads@18
|
157 this.image.style.display = "none"; |
eads@18
|
158 |
eads@18
|
159 this.canvas.style.left = 0 + "px"; |
eads@18
|
160 this.canvas.style.top = th + "px"; |
eads@18
|
161 this.canvas.style.width = w + "px"; |
eads@18
|
162 this.canvas.width = w; |
eads@18
|
163 this.canvas.style.height = h + "px"; |
eads@18
|
164 this.canvas.height = h; |
eads@18
|
165 |
eads@18
|
166 this.ctx.save(); |
eads@18
|
167 this.ctx.clearRect(0, 0, w, h); |
eads@18
|
168 this.ctx.translate(w / 2, h / 2); |
eads@18
|
169 this.ctx.rotate(this.rotation); |
eads@18
|
170 // 0 -> 1, sin(0) = 0 |
eads@18
|
171 // PI / 2 -> H / W, sin(PI/2) = 1 |
eads@18
|
172 |
eads@18
|
173 // sin(PI/2) = 1 -> limit factor is w and imgH |
eads@18
|
174 |
eads@18
|
175 var iw = this.imageWidth; |
eads@18
|
176 var ih = this.imageHeight; |
eads@18
|
177 var scale; |
eads@18
|
178 if (iw <= w && iw <= h && ih <= h && ih <= w) { |
eads@18
|
179 scale = 1; |
eads@18
|
180 } else { |
eads@18
|
181 var sinr = sawFunc(this.rotation); |
eads@18
|
182 var cosr = sawFunc(this.rotation + PI2); |
eads@18
|
183 var ratio1 = sinr * Math.min(w / ih, h / iw); |
eads@18
|
184 var ratio2 = cosr * Math.min(w / iw, h / ih); |
eads@18
|
185 var ratio = Math.min(1, ratio1 + ratio2); |
eads@18
|
186 scale = ratio; |
eads@18
|
187 } |
eads@18
|
188 this.ctx.scale(scale, scale); |
eads@18
|
189 this.ctx.translate(-iw / 2, -ih / 2); |
eads@18
|
190 this.ctx.drawImage(this.image, 0, 0, iw, ih); |
eads@18
|
191 this.ctx.restore(); |
eads@18
|
192 } |
eads@18
|
193 }, |
eads@18
|
194 |
eads@18
|
195 rotation: 0, |
eads@18
|
196 animationDuration: 500, |
eads@18
|
197 |
eads@18
|
198 rotateCcw: function () { |
eads@18
|
199 if (!this.isAnimating_) { |
eads@18
|
200 this.startTime_ = (new Date).valueOf(); |
eads@18
|
201 this.currentAngle_ = this.rotation; |
eads@18
|
202 this.deltaAngle_ = Math.PI / 2; |
eads@18
|
203 this.isAnimating_ = true; |
eads@18
|
204 this.animCounter_ = 0; |
eads@18
|
205 this.rotate_(); |
eads@18
|
206 } |
eads@18
|
207 }, |
eads@18
|
208 |
eads@18
|
209 rotateCw: function () { |
eads@18
|
210 if (!this.isAnimating_) { |
eads@18
|
211 this.startTime_ = (new Date).valueOf(); |
eads@18
|
212 this.currentAngle_ = this.rotation; |
eads@18
|
213 this.deltaAngle_ = -Math.PI / 2; |
eads@18
|
214 this.isAnimating_ = true; |
eads@18
|
215 this.animCounter_ = 0; |
eads@18
|
216 this.rotate_(); |
eads@18
|
217 } |
eads@18
|
218 }, |
eads@18
|
219 |
eads@18
|
220 rotate_: function () { |
eads@18
|
221 if (this.isAnimating_) { |
eads@18
|
222 var t = easeInEaseOut(Math.min(1, (new Date - this.startTime_) / |
eads@18
|
223 this.animationDuration)); |
eads@18
|
224 this.rotation = t * this.deltaAngle_ + this.currentAngle_; |
eads@18
|
225 if (t < 1) { |
eads@18
|
226 var self = this; |
eads@18
|
227 window.setTimeout(function () { |
eads@18
|
228 self.rotate_(); |
eads@18
|
229 }, 10); |
eads@18
|
230 } else { |
eads@18
|
231 this.isAnimating_ = false; |
eads@18
|
232 } |
eads@18
|
233 this.layout(); |
eads@18
|
234 } |
eads@18
|
235 }, |
eads@18
|
236 |
eads@18
|
237 onImageLoad: function (e) { |
eads@18
|
238 this.imageLoaded = true; |
eads@18
|
239 this.initCanvas(); |
eads@18
|
240 }, |
eads@18
|
241 onImageError: function (e) { |
eads@18
|
242 this.imageLoaded = false; |
eads@18
|
243 }, |
eads@18
|
244 onImageAbort: function (e) { |
eads@18
|
245 this.imageLoaded = false; |
eads@18
|
246 }, |
eads@18
|
247 onWindowLoad: function (e) { |
eads@18
|
248 this.windowLoaded = true; |
eads@18
|
249 this.initCanvas(); |
eads@18
|
250 }, |
eads@18
|
251 |
eads@18
|
252 initCanvas: function () { |
eads@18
|
253 if (!this.ctx && this.getLoaded()) { |
eads@18
|
254 // IE recreates the element? |
eads@18
|
255 this.canvas = this.element.getElementsByTagName("canvas")[0]; |
eads@18
|
256 this.ctx = this.canvas.getContext("2d"); |
eads@18
|
257 |
eads@18
|
258 if (!this.ctx) { |
eads@18
|
259 return; |
eads@18
|
260 } |
eads@18
|
261 this.layout(); |
eads@18
|
262 } |
eads@18
|
263 } |
eads@18
|
264 }; |
eads@18
|
265 |
eads@18
|
266 </script> |
eads@18
|
267 </head> |
eads@18
|
268 <body> |
eads@18
|
269 |
eads@18
|
270 <div id="image-rotator"> |
eads@18
|
271 <div class="tool-bar"> |
eads@18
|
272 <button>Rotate Left</button><button>Rotate Right</button> |
eads@18
|
273 </div> |
eads@18
|
274 <canvas id="c"></canvas> |
eads@18
|
275 <img src="" alt=""> |
eads@18
|
276 </div> |
eads@18
|
277 <script type="text/javascript"> |
eads@18
|
278 new ImageRotator(document.getElementById("image-rotator"), |
eads@18
|
279 "ff.jpg", 608, 380); |
eads@18
|
280 </script> |
eads@18
|
281 |
eads@18
|
282 </body> |
eads@18
|
283 </html> |
eads@18
|
284 |