]>
Commit | Line | Data |
---|---|---|
1 | 'use strict'; | |
2 | ||
3 | ((window) => { | |
4 | ||
5 | const kColorIteratorLimit = 256; | |
6 | const kRedSpeed = 0.1; | |
7 | const kGreenSpeed = 0.2; | |
8 | const kBlueSpeed = 0.15; | |
9 | ||
10 | /** | |
11 | * Renders a Heart, has its own canvas, which will be placed in the element | |
12 | * set by calling #render. | |
13 | * | |
14 | * @class HeartRenderer | |
15 | * @param {object} config configuration, extends any member of the renderer | |
16 | */ | |
17 | const HeartRenderer = class HeartRenderer { | |
18 | ||
19 | constructor(config) { | |
20 | ||
21 | /** | |
22 | * The instance of the heart renderer being used | |
23 | * | |
24 | * @memberof HeartRenderer | |
25 | * @instance | |
26 | * @name canvas | |
27 | * @type HTMLCanvasElement | |
28 | * @default A brand new full width and height canvas | |
29 | */ | |
30 | this.canvas = window.document.createElement('canvas'); | |
31 | this.canvas.style.height = '100%'; | |
32 | this.canvas.style.width = '100%'; | |
33 | ||
34 | /** | |
35 | * The maximum fps that will be used | |
36 | * | |
37 | * @memberof HeartRenderer | |
38 | * @instance | |
39 | * @name fps | |
40 | * @type Number | |
41 | * @default 60 | |
42 | */ | |
43 | this.fps = 60; | |
44 | ||
45 | this._animating = false; // The status of the animation. | |
46 | this._previousFrameTime = Date.now(); // The timestamp of the last frame for fps control | |
47 | this._currentColor = { // The current color that will be painted | |
48 | red: 100, | |
49 | blue: 0, | |
50 | green: 50 | |
51 | }; | |
52 | ||
53 | Object.assign(this, config); | |
54 | } | |
55 | ||
56 | /** | |
57 | * Attaches the canvas to an HTML element | |
58 | * | |
59 | * @memberof HeartRenderer | |
60 | * @function render | |
61 | * @instance | |
62 | * @param {HTMLElement} element the element where we will attach our canvas | |
63 | */ | |
64 | render(element) { | |
65 | ||
66 | element.appendChild(this.canvas); | |
67 | } | |
68 | ||
69 | /** | |
70 | * Gets the context from the current canvas and starts the animation process | |
71 | * | |
72 | * @memberof HeartRenderer | |
73 | * @function activate | |
74 | * @instance | |
75 | */ | |
76 | activate() { | |
77 | ||
78 | const context = this.canvas.getContext('2d'); | |
79 | this._startAnimating(context); | |
80 | } | |
81 | ||
82 | /** | |
83 | * Stops the animation process | |
84 | * | |
85 | * @memberof HeartRenderer | |
86 | * @function deactivate | |
87 | * @instance | |
88 | */ | |
89 | deactivate() { | |
90 | ||
91 | this._stopAnimating(); | |
92 | } | |
93 | ||
94 | // Starts the animation loop | |
95 | _startAnimating(context) { | |
96 | ||
97 | this._frameDuration = 1000 / this.fps; | |
98 | this._animating = true; | |
99 | ||
100 | this._animate(context); | |
101 | } | |
102 | ||
103 | // Stops the animation on the next frame. | |
104 | _stopAnimating() { | |
105 | ||
106 | this._animating = false; | |
107 | } | |
108 | ||
109 | // Runs the animation step controlling the FPS | |
110 | _animate(context) { | |
111 | ||
112 | if (!this._animating) { | |
113 | return; | |
114 | } | |
115 | ||
116 | window.requestAnimationFrame(this._animate.bind(this, context)); | |
117 | ||
118 | const currentFrameTime = Date.now(); | |
119 | const delta = currentFrameTime - this._previousFrameTime; | |
120 | ||
121 | if (delta > this._frameDuration) { | |
122 | this._previousFrameTime = Date.now(); | |
123 | this._animateStep(context, delta); | |
124 | } | |
125 | } | |
126 | ||
127 | // The actual animation processing function. | |
128 | _animateStep(context, delta) { | |
129 | ||
130 | this._currentColor.red = Math.round(this._currentColor.red + delta * kRedSpeed) % kColorIteratorLimit; | |
131 | this._currentColor.green = Math.round(this._currentColor.green + delta * kGreenSpeed) % kColorIteratorLimit; | |
132 | this._currentColor.blue = Math.round(this._currentColor.blue + delta * kBlueSpeed) % kColorIteratorLimit; | |
133 | ||
134 | context.fillStyle = `rgb(${this._currentColor.red}, ${this._currentColor.green}, ${this._currentColor.blue})`; | |
135 | context.fillRect(0, 0, this.canvas.scrollWidth, this.canvas.scrollHeight); | |
136 | } | |
137 | }; | |
138 | ||
139 | ||
140 | window.HeartRenderer = HeartRenderer; | |
141 | })(window); |