├── index.html
└── fan.js
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Fan
9 |
10 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/fan.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This is the test task requested by DEGO Interactive.
3 | *
4 | * @link http://www.dego.lv/ru/careers/coder-needed
5 | * @author Andrew Silin
6 | * @version 1.0
7 | */
8 | (function(){
9 |
10 | /**
11 | * @type {String} ID of the DOM contaier element.
12 | */
13 | var container = 'container';
14 |
15 | /**
16 | * @type {Object} Fader layer absolute position object.
17 | * This object has only x and y properties. Example: {x: 100, y: 200}
18 | */
19 | var flap;
20 |
21 | /**
22 | * @type {Kinetic.Animation} Propeller layer animation instance.
23 | */
24 | var anim;
25 |
26 | /**
27 | * @type {Number} Min. y axis speed control fader drag bounds.
28 | */
29 | var minY;
30 |
31 | /**
32 | * @type {Number} Max. y axis speed control fader drag bounds.
33 | */
34 | var maxY;
35 |
36 | /**
37 | * @type {Float} Fan propeller animation speed.
38 | */
39 | var speed;
40 |
41 | /**
42 | * Define fan layers and shapes.
43 | * It's pretty much self-explanatory here...
44 | */
45 | var stage = new Kinetic.Stage({
46 | container: container,
47 | width: 600,
48 | height: 600
49 | });
50 |
51 | var propellerLayer = new Kinetic.Layer({
52 | x: 250,
53 | y: 200
54 | });
55 |
56 | var towerLayer = new Kinetic.Layer({
57 | x: 250,
58 | y: 200
59 | });
60 |
61 | var faderLayer = new Kinetic.Layer({
62 | x: 500,
63 | y: 200
64 | });
65 |
66 | var blade1 = new Kinetic.Ellipse({
67 | width: 160,
68 | height: 30,
69 | fill: '#001914',
70 | offset: [-80, 0]
71 | });
72 |
73 | var blade2 = new Kinetic.Ellipse({
74 | x: 0,
75 | y: 0,
76 | width: 160,
77 | height: 30,
78 | fill: '#001914',
79 | offset: [80, 0]
80 | });
81 |
82 | var rotor = new Kinetic.Circle({
83 | x: 0,
84 | y: 0,
85 | radius: 25,
86 | fill: '#008D78'
87 | });
88 |
89 | var tower = new Kinetic.Path({
90 | data: 'M 0 0 L 70 300 L 0 240 L -70 300 z',
91 | fill: '#E6E6E6'
92 | });
93 |
94 | var track = new Kinetic.Rect({
95 | width: 6,
96 | height: 200,
97 | fill: '#E6E6E6',
98 | offset: [3, -12]
99 | });
100 |
101 | var fader = new Kinetic.Rect({
102 | width: 50,
103 | height: 25,
104 | y: 200,
105 | fill: '#001914',
106 | draggable: true,
107 | offset: [25, 0],
108 | dragBoundFunc: function(pos) {
109 | return {
110 | x: this.getAbsolutePosition().x,
111 | y: (pos.y > maxY)? maxY : (pos.y < minY)? minY : pos.y
112 | };
113 | }
114 | });
115 |
116 | var fast = new Kinetic.Text({
117 | text: 'FAST',
118 | fontStyle: 'bold',
119 | fontSize: 13,
120 | align: 'center',
121 | fill: '#D2D2D2',
122 | width: 100,
123 | offset: [50, 20]
124 | });
125 |
126 | var slow = new Kinetic.Text({
127 | text: 'SLOW',
128 | fontStyle: 'bold',
129 | fontSize: 13,
130 | align: 'center',
131 | fill: '#D2D2D2',
132 | width: 100,
133 | offset: [50, -(track.getHeight() + 30)]
134 | });
135 |
136 | /**
137 | * Compile all layers and shapes together to form the resulting image.
138 | * It's pretty much self-explanatory here also...
139 | */
140 | towerLayer.add(tower);
141 |
142 | faderLayer.add(track);
143 | faderLayer.add(fader);
144 | faderLayer.add(slow);
145 | faderLayer.add(fast);
146 |
147 | propellerLayer.add(blade1);
148 | propellerLayer.add(blade2);
149 | propellerLayer.add(rotor);
150 |
151 | stage.add(towerLayer);
152 | stage.add(faderLayer);
153 | stage.add(propellerLayer);
154 |
155 | /**
156 | * Get fan speed, based on current fader position.
157 | * Resulting value may be used to control fan rotation animation speed.
158 | *
159 | * @returns {Float} Fan speed.
160 | */
161 | function getSpeed()
162 | {
163 | return (track.getHeight() - fader.getY() + 1) / track.getHeight();
164 | }
165 |
166 | //Set initial speed based on fader position
167 | speed = getSpeed();
168 |
169 | flap = faderLayer.getAbsolutePosition();
170 | minY = flap.y;
171 | maxY = minY + track.getHeight();
172 |
173 | /**
174 | * Define fader drag event handler.
175 | * This allows user to change fan rotation speed while draging
176 | * speed conrol fader.
177 | */
178 | fader.on('dragmove', function(e) {
179 | speed = getSpeed();
180 | });
181 |
182 | /**
183 | * Define fader track click event handler.
184 | * This allows user to click on speed control track(groove)
185 | * instead of draging fader itself to change fan rotation speed.
186 | */
187 | track.on('click', function(e) {
188 |
189 | /**
190 | * Calculate fader y position depending on where
191 | * user had clicked on the fader track shape.
192 | */
193 | fader.setY(e.layerY - flap.y + track.getOffsetY());
194 |
195 | faderLayer.draw(); //Redraw fader layer
196 | fader.fire('dragmove'); //Emulate drag on fader
197 | });
198 |
199 | /**
200 | * Define propeller layer rotation animation.
201 | */
202 | anim = new Kinetic.Animation(function(frame) {
203 | propellerLayer.rotate(speed);
204 | }, propellerLayer);
205 |
206 | //Start animation after the script is loaded.
207 | anim.start();
208 |
209 | })();
--------------------------------------------------------------------------------