-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathclap-at-the-globe.html
142 lines (119 loc) · 4.23 KB
/
clap-at-the-globe.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Clap at the globe</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<link href="https://api.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.js"></script>
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
let initLoad = true;
mapboxgl.accessToken = 'pk.eyJ1IjoidGp1a2Fub3Z0IiwiYSI6ImNrNTdxempkZTBmeTczZmxqdmxmNHlqczAifQ.a_BL5RTprJKXwaTzbsPeyw';
const map = new mapboxgl.Map({
container: 'map',
projection: 'globe',
style: 'mapbox://styles/tjukanovt/cl4f572r5000414q5y1dspdsm',
zoom: 3,
center: [120,-10]
});
map.on('load', () => {
const bins = 16;
const maxHeight = 200;
const binWidth = maxHeight / bins;
if (initLoad) {
initLoad = false;
map.setFog({
color: '#fff',
'horizon-blend': 0.1,
'high-color': '#b34f01',
'star-intensity': 0.1,
'space-color': '#000ff'
});
}
// Older browsers might not implement mediaDevices at all, so we set an empty object first
if (navigator.mediaDevices === undefined) {
navigator.mediaDevices = {};
}
// Some browsers partially implement mediaDevices. We can't just assign an object
// with getUserMedia as it would overwrite existing properties.
// Here, we will just add the getUserMedia property if it's missing.
if (navigator.mediaDevices.getUserMedia === undefined) {
navigator.mediaDevices.getUserMedia = (constraints) => {
// First get ahold of the legacy getUserMedia, if present
const getUserMedia =
navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
// Some browsers just don't implement it - return a rejected promise with an error
// to keep a consistent interface
if (!getUserMedia) {
return Promise.reject(
new Error(
'getUserMedia is not implemented in this browser'
)
);
}
// Otherwise, wrap the call to the old navigator.getUserMedia with a Promise
return new Promise((resolve, reject) => {
getUserMedia.call(navigator, constraints, resolve, reject);
});
};
}
navigator.mediaDevices
.getUserMedia({ audio: true })
.then((stream) => {
// Set up a Web Audio AudioContext and AnalyzerNode, configured to return the
// same number of bins of audio frequency data.
const audioCtx = new (window.AudioContext ||
window.webkitAudioContext)();
const analyser = audioCtx.createAnalyser();
analyser.minDecibels = -90;
analyser.maxDecibels = -10;
analyser.smoothingTimeConstant = 0.85;
const source = audioCtx.createMediaStreamSource(stream);
source.connect(analyser);
analyser.fftSize = bins * 2;
const dataArray = new Uint8Array(bins);
function draw(now) {
analyser.getByteFrequencyData(dataArray);
// Use that data to drive updates to the fill-extrusion-height property.
let avg = 0;
for (let i = 0; i < bins; i++) {
avg += dataArray[i];
map.setFog({
'horizon-blend': (10 + 4 * i + dataArray[i])/500,
color: 'rgba(' + Math.round(((10 + 4 * i + dataArray[i]))*3) + ',' + Math.round(((10 + 4 * i + dataArray[i]))) + ',' + Math.round(((10 + 4 * i + dataArray[i]))+20) + ',' + 1 + ')'
});
console.log((10 + 4 * i + dataArray[i]) /500)
let translate = [0,-(10 + 4 * i + dataArray[i]) /5]
map.setPaintProperty(
`country-label`,
'text-translate',
translate
);
}
avg /= bins;
// Animate the map bearing and light color over time, and make the light more
// intense when the audio is louder.
const hue = (now / 100) % 360;
const saturation = Math.min(50 + avg / 4, 100);
map.setLight({
color: `hsl(${hue},${saturation}%,50%)`,
intensity: Math.min(1, (avg / 256) * 10)
});
requestAnimationFrame(draw);
}
requestAnimationFrame(draw);
})
.catch((err) => {
console.log('The following gUM error occurred:', err);
});
});
</script>
</body>
</html>