]>
git.r.bdr.sh - rbdr/sorting-hat-renderer/blob - lib/components/wave_renderer.js
2 import DataService
from '../services/data';
11 michaelangelo: 'orange',
23 scale(value
, min
, max
) {
25 return ((value
- min
) / (max
- min
)) * (internals
.kMaxValue
- internals
.kMinValue
) - internals
.kMinValue
;
29 export default Vue
.component('posts', {
30 template: '<transition name="fade">' +
31 '<canvas v-show="state === 1" class="wave-renderer"></canvas>' +
34 data: DataService
.data
,
38 // Convert from the min / max value in the measurement to a
39 // predefined min value between 0 and 100 (see kMinValue and
40 // kMaxValue for actual values)
44 const keys
= Object
.keys(this.runningAverages
);
46 const averages
= keys
.reduce((averages
, averageCategory
) => {
48 const runningAverage
= this.runningAverages
[averageCategory
];
49 averages
[averageCategory
] = runningAverage
.average
;
53 const max
= Math
.max(...Object
.values(averages
));
54 const min
= Math
.min(...Object
.values(averages
));
56 const scaledAverages
= Object
.keys(averages
).reduce((scaledAverages
, averageCategory
) => {
58 const value
= averages
[averageCategory
];
59 scaledAverages
[averageCategory
] = internals
.scale(value
, min
, max
);
60 return scaledAverages
;
63 return scaledAverages
;
70 this.$el
.width
= window
.innerWidth
;
71 this.$el
.height
= window
.innerHeight
;
75 // Initiates the animation loop
79 // Make sure we resize, do an initial sizing
81 window
.addEventListener('resize', this.onResize
.bind(this));
84 // Start the whole animation (Sorry it's a mess)
86 const canvas
= this.$el
;
88 const context
= canvas
.getContext('2d');
89 const interval
= 1000 / internals
.kTargetFPS
;
91 let lastTimestamp
= 0;
93 const animationHandler
= (timestamp
) => {
95 window
.requestAnimationFrame(animationHandler
);
96 const delta
= timestamp
- lastTimestamp
;
98 if (delta
> interval
) {
100 const keys
= Object
.keys(this.scaledAverages
);
101 const values
= Object
.values(this.scaledAverages
);
102 const segments
= keys
.length
;
103 const period
= canvas
.width
/ segments
;
105 const fillGradient
= context
.createLinearGradient(0, 0, canvas
.width
, 0);
106 const gradientBandWidth
= 1 / segments
;
108 // Position the drawing cursor left-center of screen
110 context
.clearRect(0, 0, canvas
.width
, canvas
.height
);
112 context
.moveTo(0, canvas
.height
);
113 context
.lineTo(0, canvas
.height
/ 2);
115 // Iterate over the segments
117 for (let currentSegment
= 0; currentSegment
< segments
; ++currentSegment
) {
118 const segmentStart
= currentSegment
* period
;
119 const segmentEnd
= currentSegment
+ period
;
121 const category
= keys
[currentSegment
];
122 const magnitude
= values
[currentSegment
];
123 const segmentHeight
= Math
.round(Math
.random() * internals
.kRandomJitter
+ magnitude
* (canvas
.height
/ 2) / 100);
125 // Calculate the gradient using the correct color according to
128 const color
= internals
.kColors
[category
] || 'black';
129 let currentGradientPosition
= currentSegment
* gradientBandWidth
+ internals
.kGradientFade
;
130 fillGradient
.addColorStop(currentGradientPosition
, color
);
131 currentGradientPosition
= (currentSegment
+ 1) * gradientBandWidth
- internals
.kGradientFade
;
132 fillGradient
.addColorStop(currentGradientPosition
, color
);
134 // This draws the sine wave
136 for (let angle
= 0; angle
< 180; ++angle
) {
137 const currentPixel
= segmentStart
+ angle
* period
/ 180;
138 const currentAngle
= angle
+ 180 * (currentSegment
% 2);
139 const currentRadians
= currentAngle
* Math
.PI
/ 180;
140 const currentHeight
= segmentHeight
* Math
.sin(internals
.kFrequency
* currentRadians
);
142 context
.lineTo(currentPixel
, currentHeight
+ canvas
.height
/ 2);
146 context
.lineTo(canvas
.width
, canvas
.height
/ 2);
147 context
.lineTo(canvas
.width
, canvas
.height
);
148 context
.fillStyle
= fillGradient
;
151 lastTimestamp
= timestamp
;
155 window
.requestAnimationFrame(animationHandler
);