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