├── 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 | })(); --------------------------------------------------------------------------------