Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(181)

Side by Side Diff: client/samples/spirodraw/Spirodraw.dart

Issue 9303020: Move all samples but swarm from client/samples/ to samples/ . (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 #library('spirodraw');
6
7 #import('dart:dom');
8 #source("ColorPicker.dart");
9 // TODO(732): Reenable when this works in the VM.
10 // #resource("spirodraw.css");
11
12 void main() {
13 new Spirodraw().go();
14 }
15
16 class Spirodraw {
17
18 static double PI2 = Math.PI * 2;
19 Document doc;
20 // Scale factor used to scale wheel radius from 1-10 to pixels
21 int RUnits, rUnits, dUnits;
22 // Fixed radius, wheel radius, pen distance in pixels
23 double R, r, d;
24 HTMLInputElement fixedRadiusSlider, wheelRadiusSlider,
25 penRadiusSlider, penWidthSlider, speedSlider;
26 HTMLSelectElement inOrOut;
27 HTMLLabelElement numTurns;
28 HTMLDivElement mainDiv;
29 num lastX, lastY;
30 int height, width, xc, yc;
31 int maxTurns;
32 HTMLCanvasElement frontCanvas, backCanvas;
33 CanvasRenderingContext2D front, back;
34 HTMLCanvasElement paletteElement;
35 ColorPicker colorPicker;
36 String penColor = "red";
37 int penWidth;
38 double rad = 0.0;
39 double stepSize;
40 bool animationEnabled = true;
41 int numPoints;
42 double speed;
43 bool run;
44
45 Spirodraw() {
46 doc = window.document;
47 inOrOut = doc.getElementById("in_out");
48 fixedRadiusSlider = doc.getElementById("fixed_radius");
49 wheelRadiusSlider = doc.getElementById("wheel_radius");
50 penRadiusSlider = doc.getElementById("pen_radius");
51 penWidthSlider = doc.getElementById("pen_width");
52 speedSlider = doc.getElementById("speed");
53 numTurns = doc.getElementById("num_turns");
54 mainDiv = doc.getElementById("main");
55 frontCanvas = doc.getElementById("canvas");
56 front = frontCanvas.getContext("2d");
57 backCanvas = doc.createElement("canvas");
58 back = backCanvas.getContext("2d");
59 paletteElement = doc.getElementById("palette");
60 window.addEventListener('resize', (event) => onResize(), true);
61 initControlPanel();
62 }
63
64 void go() {
65 onResize();
66 }
67
68 void onResize() {
69 height = window.innerHeight;
70 width = window.innerWidth - 270;
71 yc = height~/2;
72 xc = width~/2;
73 frontCanvas.height = height;
74 frontCanvas.width = width;
75 backCanvas.height = height;
76 backCanvas.width = width;
77 clear();
78 }
79
80 void initControlPanel() {
81 inOrOut.addEventListener('change', (event) => refresh(), true);
82 fixedRadiusSlider.addEventListener('change', (event) => refresh(), true);
83 wheelRadiusSlider.addEventListener('change', (event) => refresh(), true);
84 speedSlider.addEventListener('change', (event) => onSpeedChange(), true);
85 penRadiusSlider.addEventListener('change', (event) => refresh(), true);
86 penWidthSlider.addEventListener('change', (event) => onPenWidthChange(), tru e);
87 colorPicker = new ColorPicker(paletteElement);
88 colorPicker.addListener((String color) => onColorChange(color));
89 doc.getElementById("start").addEventListener('click', (event) => start(), tr ue);
90 doc.getElementById("stop").addEventListener('click', (event) => stop(), true );
91 doc.getElementById("clear").addEventListener('click', (event) => clear(), tr ue);
92 doc.getElementById("lucky").addEventListener('click', (event) => lucky(), tr ue);
93 }
94
95 void onColorChange(String color) {
96 penColor = color;
97 drawFrame(rad);
98 }
99
100 void onSpeedChange() {
101 speed = speedSlider.valueAsNumber;
102 stepSize = calcStepSize();
103 }
104
105 void onPenWidthChange() {
106 penWidth = penWidthSlider.valueAsNumber;
107 drawFrame(rad);
108 }
109
110 void refresh() {
111 stop();
112 // Reset
113 lastX = lastY = 0;
114 // Compute fixed radius
115 // based on starting diameter == min / 2, fixed radius == 10 units
116 int min = Math.min(height, width);
117 double pixelsPerUnit = min / 40;
118 RUnits = fixedRadiusSlider.valueAsNumber;
119 R = RUnits * pixelsPerUnit;
120 // Scale inner radius and pen distance in units of fixed radius
121 rUnits = wheelRadiusSlider.valueAsNumber;
122 r = rUnits * R/RUnits * Math.parseInt(inOrOut.value);
123 dUnits = penRadiusSlider.valueAsNumber;
124 d = dUnits * R/RUnits;
125 numPoints = calcNumPoints();
126 maxTurns = calcTurns();
127 onSpeedChange();
128 numTurns.innerText = "0" + "/" + maxTurns;
129 penWidth = penWidthSlider.valueAsNumber;
130 drawFrame(0.0);
131 }
132
133 int calcNumPoints() {
134 if ((dUnits==0) || (rUnits==0))
135 // Empirically, treat it like an oval
136 return 2;
137 int gcf_ = gcf(RUnits, rUnits);
138 int n = RUnits ~/ gcf_;
139 int d_ = rUnits ~/ gcf_;
140 if (n % 2 == 1)
141 // odd
142 return n;
143 else if (d_ %2 == 1)
144 return n;
145 else
146 return n~/2;
147 }
148
149 // TODO return optimum step size in radians
150 double calcStepSize() => speed / 100 * maxTurns / numPoints;
151
152 void drawFrame(double theta) {
153 if (animationEnabled) {
154 front.clearRect(0, 0, width, height);
155 front.drawImage(backCanvas, 0, 0);
156 drawFixed();
157 }
158 drawWheel(theta);
159 }
160
161 void animate(int time) {
162 if (run && rad <= maxTurns * PI2) {
163 rad+=stepSize;
164 drawFrame(rad);
165 int nTurns = (rad / PI2).toInt();
166 numTurns.innerText = '${nTurns}/$maxTurns';
167 window.webkitRequestAnimationFrame(animate, frontCanvas);
168 } else {
169 stop();
170 }
171 }
172
173 void start() {
174 refresh();
175 rad = 0.0;
176 run = true;
177 window.webkitRequestAnimationFrame(animate, frontCanvas);
178 }
179
180 int calcTurns() {
181 // compute ratio of wheel radius to big R then find LCM
182 if ((dUnits==0) || (rUnits==0))
183 return 1;
184 int ru = rUnits.abs();
185 int wrUnits = RUnits + rUnits;
186 int g = gcf (wrUnits, ru);
187 return (ru ~/ g).toInt();
188 }
189
190 void stop() {
191 run = false;
192 // Show drawing only
193 front.clearRect(0, 0, width, height);
194 front.drawImage(backCanvas, 0, 0);
195 // Reset angle
196 rad = 0.0;
197 }
198
199 void clear() {
200 stop();
201 back.clearRect(0, 0, width, height);
202 refresh();
203 }
204
205 /**
206 * Choose random settings for wheel and pen, but
207 * leave fixed radius alone as it often changes
208 * things too much.
209 */
210 void lucky() {
211 wheelRadiusSlider.valueAsNumber = Math.random() * 9;
212 penRadiusSlider.valueAsNumber = Math.random() * 9;
213 penWidthSlider.valueAsNumber = 1 + Math.random() * 9;
214 colorPicker.selectedColor = Math.random() * 215;
215 start();
216 }
217
218 void drawFixed() {
219 if (animationEnabled) {
220 front.beginPath();
221 front.setLineWidth(2);
222 front.strokeStyle = "gray";
223 front.arc(xc, yc, R, 0, PI2, true);
224 front.closePath();
225 front.stroke();
226 }
227 }
228
229 /**
230 * Draw the wheel with its center at angle theta
231 * with respect to the fixed wheel
232 *
233 * @param theta
234 */
235 void drawWheel(double theta) {
236 double wx = xc + ((R + r) * Math.cos(theta));
237 double wy = yc - ((R + r) * Math.sin(theta));
238 if (animationEnabled) {
239 if (rUnits>0) {
240 // Draw ring
241 front.beginPath();
242 front.arc(wx, wy, r.abs(), 0, PI2, true);
243 front.closePath();
244 front.stroke();
245 // Draw center
246 front.setLineWidth(1);
247 front.beginPath();
248 front.arc(wx, wy, 3, 0, PI2, true);
249 front.fillStyle = "black";
250 front.fill();
251 front.closePath();
252 front.stroke();
253 }
254 }
255 drawTip(wx, wy, theta);
256 }
257
258 /**
259 * Draw a rotating line that shows the wheel rolling and leaves
260 * the pen trace
261 *
262 * @param wx X coordinate of wheel center
263 * @param wy Y coordinate of wheel center
264 * @param theta Angle of wheel center with respect to fixed circle
265 */
266 void drawTip(double wx, double wy, double theta) {
267 // Calc wheel rotation angle
268 double rot = (r==0) ? theta : theta * (R+r) / r;
269 // Find tip of line
270 double tx = wx + d * Math.cos(rot);
271 double ty = wy - d * Math.sin(rot);
272 if (animationEnabled) {
273 front.beginPath();
274 front.fillStyle = penColor;
275 front.arc(tx, ty, penWidth/2+2, 0, PI2, true);
276 front.fill();
277 front.moveTo(wx, wy);
278 front.strokeStyle = "black";
279 front.lineTo(tx, ty);
280 front.closePath();
281 front.stroke();
282 }
283 drawSegmentTo(tx, ty);
284 }
285
286 void drawSegmentTo(double tx, double ty) {
287 if (lastX > 0) {
288 back.beginPath();
289 back.strokeStyle = penColor;
290 back.setLineWidth(penWidth);
291 back.moveTo(lastX, lastY);
292 back.lineTo(tx, ty);
293 back.closePath();
294 back.stroke();
295 }
296 lastX = tx;
297 lastY = ty;
298 }
299
300 }
301
302 int gcf(int n, int d) {
303 if (n==d)
304 return n;
305 int max = Math.max(n, d);
306 for (int i = max ~/ 2; i > 1; i--)
307 if ((n % i == 0) && (d % i == 0))
308 return i;
309 return 1;
310 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698