File size: 9,451 Bytes
9e14a34
8448041
 
9e14a34
9cb88ff
8448041
9cb88ff
8448041
9cb88ff
 
 
 
 
 
 
9e14a34
9cb88ff
 
 
 
 
9e14a34
0747f83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9e14a34
 
 
 
 
a9f5b1e
9e14a34
 
 
 
 
 
644e87e
a9f5b1e
9e14a34
 
 
 
 
 
 
 
8448041
 
 
9e14a34
 
 
 
8448041
9e14a34
8448041
 
9cb88ff
9e14a34
9cb88ff
 
 
 
5daada1
9cb88ff
 
cadab89
a9f5b1e
 
 
 
cadab89
 
 
 
9cb88ff
 
 
8448041
9cb88ff
 
 
 
 
 
 
 
 
 
 
a9f5b1e
 
 
9cb88ff
a9f5b1e
 
 
9cb88ff
 
 
 
 
8448041
9cb88ff
 
8448041
9cb88ff
 
 
8448041
9cb88ff
 
 
 
 
 
 
 
 
8448041
9cb88ff
 
 
8448041
9cb88ff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5daada1
 
 
9cb88ff
 
 
 
 
 
 
 
 
 
 
5daada1
9cb88ff
 
5daada1
 
 
 
9cb88ff
 
 
cadab89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9cb88ff
 
0747f83
 
9e14a34
9cb88ff
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
// 加载语言
let zh_CN = ($("title").text() == "音频可视化圆环特效");

// 初始化文件
function clearInputFiles(inputId) {
    let inputElement = document.getElementById(inputId);
    if (inputElement.files && inputElement.files.length > 0) {
        let reader = new FileReader();
        reader.readAsArrayBuffer(inputElement.files[0]);
        reader.onload = function () {
            inputElement.value = '';
        };
    }
}

// 还原背景图
function recover_bg() {
    $(".bg").css("background-image", "url(./src/bg.jpg)");
    clearInputFiles("bgFile");
}

// 加载全屏按钮
function openFullscreen(elem) {
    if (elem.requestFullscreen) {
        elem.requestFullscreen();
    } else if (elem.mozRequestFullScreen) { // Firefox
        elem.mozRequestFullScreen();
    } else if (elem.webkitRequestFullscreen) { // Chrome, Safari and Opera
        elem.webkitRequestFullscreen();
    } else if (elem.msRequestFullscreen) { // IE/Edge
        elem.msRequestFullscreen();
    }
}

// exit fullscreen
function closeFullscreen() {
    if (document.exitFullscreen) {
        document.exitFullscreen();
    } else if (document.mozCancelFullScreen) { // Firefox
        document.mozCancelFullScreen();
    } else if (document.webkitExitFullscreen) { // Chrome, Safari and Opera
        document.webkitExitFullscreen();
    } else if (document.msExitFullscreen) { // IE/Edge
        document.msExitFullscreen();
    }
}

function loadFullscreen() {
    // fullscreen related
    document.getElementById("fullscreen").addEventListener("click", function () {
        if (document.fullscreenElement) {
            closeFullscreen();
        } else {
            openFullscreen(document.documentElement);
        }
    });

    document.addEventListener('fullscreenchange', function () {
        if (document.fullscreenElement) {
            document.getElementById("fullscreen").innerText = zh_CN ? "退出全屏" : "Exit fullscreen";
        } else {
            document.getElementById("fullscreen").innerText = zh_CN ? "全屏" : "Fullscreen";
        }
    });
}

// 检查设备类型
function checkDeviceType() {
    const userAgent = navigator.userAgent || window.opera;
    if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent)) {
        let warning = zh_CN ? "请使用 PC 端浏览器查看!" : "Please view on PC browsers!"
        $("body").remove();
        $("html").append(`<body><h1 style="text-align: center; font-size: xxx-large;">${warning}</h1></body>`);
        return false;
    }
    return true;
}

window.onload = function () {
    if (!checkDeviceType()) return;
    wrap.width = window.innerWidth - 1;
    wrap.height = window.innerHeight - 1;
    let canvasCtx = wrap.getContext("2d");
    let AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext;
    let audioContext = new AudioContext();
    canvasCtx.shadowColor = "white";
    canvasCtx.shadowBlur = 10;

    $("#home").click(function () {
        recover_bg();
    });

    $('#upl').hover(function () {
        $(this).removeClass("first");
    });

    $('#bgFile').change(function () {
        if (this.files.length <= 0) return;
        if (this.files[0].size > 5242880) {
            alert(zh_CN ? '文件大小超过 5M' : 'File size larger than 5M');
            return;
        }
        let file = this.files[0];
        let reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = function () {
            $('.bg').css('background-image', 'url(' + reader.result + ')');
        };
    });

    $('#musicFile').change(function () {
        if (this.files.length == 0) {
            $("#tip").text(zh_CN ? "上传待可视化的音频👉" : "Upload audio to be visualized👉");
            return;
        }
        audioContext.close();
        audioContext = new AudioContext();
        $("#startStop").val(zh_CN ? '暂停' : 'Pause');
        let file = $('#musicFile')[0].files[0];
        let fileReader = new FileReader();
        fileReader.readAsArrayBuffer(file);
        fileReader.onload = function (e) {
            let count = 0;
            $('#tip').text(zh_CN ? '开始解码' : 'Start decoding')
            let timer = setInterval(function () {
                count++;
                $('#tip').text((zh_CN ? '正在解码中, 已耗时 ' : 'In decoding, already used ') + count + 's')
            }, 1000)
            audioContext.decodeAudioData(e.target.result, function (buffer) {
                clearInterval(timer)
                $('#tip').text((zh_CN ? '解码成功, 总耗时 ' : 'Decoded successfully, total time ') + count + 's');
                let audioBufferSourceNode = audioContext.createBufferSource();
                let analyser = audioContext.createAnalyser();
                audioBufferSourceNode.connect(analyser);
                analyser.connect(audioContext.destination);
                audioBufferSourceNode.buffer = buffer;
                audioBufferSourceNode.start();
                startStop.onclick = function () {
                    if (audioContext.state === 'running') {
                        audioContext.suspend().then(function () {
                            $("#startStop").val(zh_CN ? '播放' : 'Play');
                        });
                    } else if (audioContext.state === 'suspended') {
                        audioContext.resume().then(function () {
                            $("#startStop").val(zh_CN ? '暂停' : 'Pause');
                        });
                    }
                }
                let oW = wrap.width;
                let oH = wrap.height;
                let color1 = canvasCtx.createLinearGradient(oW / 2, oH / 2 - 10, oW / 2, oH / 2 - 150);
                color1.addColorStop(0, '#1E90FF');
                color1.addColorStop(.25, '#FF7F50');
                color1.addColorStop(.5, '#8A2BE2');
                color1.addColorStop(.75, '#4169E1');
                color1.addColorStop(1, '#00FFFF');
                let color2 = canvasCtx.createLinearGradient(0, 0, oW, oH);
                color2.addColorStop(0, '#1E90FF');
                color2.addColorStop(.25, '#FFD700');
                color2.addColorStop(.5, '#8A2BE2');
                color2.addColorStop(.75, '#4169E1');
                color2.addColorStop(1, '#FF0000');
                let output = new Uint8Array(180);
                let du = 2;
                let R = 200;
                let W = 2;
                (function drawSpectrum() {
                    analyser.getByteFrequencyData(output);
                    canvasCtx.clearRect(0, 0, wrap.width, wrap.height);
                    for (let i = 0; i < 360; i++) {
                        let value = output[i] / 10;
                        canvasCtx.beginPath();
                        canvasCtx.lineWidth = W;
                        Rv1 = (R - value);
                        Rv2 = (R + value);
                        canvasCtx.moveTo((Math.sin((i * du) / 180 * Math.PI) * Rv1 + oW / 2), -Math.cos((i * du) / 180 * Math.PI) * Rv1 + oH / 2);
                        canvasCtx.lineTo((Math.sin((i * du) / 180 * Math.PI) * Rv2 + oW / 2), -Math.cos((i * du) / 180 * Math.PI) * Rv2 + oH / 2);
                        canvasCtx.strokeStyle = color1;
                        canvasCtx.stroke();
                    }
                    canvasCtx.font = "italic bold 20px Microsoft Yahei";
                    canvasCtx.fillStyle = color2;
                    canvasCtx.textAlign = "center";
                    canvasCtx.textBaseline = "middle";
                    canvasCtx.fillText(file.name.split('.mp3')[0], oW / 2, oH / 2);
                    requestAnimationFrame(drawSpectrum);
                })();

                $(window).resize(function () {
                    wrap.width = window.innerWidth - 1;
                    wrap.height = window.innerHeight - 1;
                    let oW = wrap.width;
                    let oH = wrap.height;
                    (function drawSpectrum() {
                        analyser.getByteFrequencyData(output);
                        canvasCtx.clearRect(0, 0, wrap.width, wrap.height);
                        for (let i = 0; i < 360; i++) {
                            let value = output[i] / 10;
                            canvasCtx.beginPath();
                            canvasCtx.lineWidth = W;
                            Rv1 = (R - value);
                            Rv2 = (R + value);
                            canvasCtx.moveTo((Math.sin((i * du) / 180 * Math.PI) * Rv1 + oW / 2), -Math.cos((i * du) / 180 * Math.PI) * Rv1 + oH / 2);
                            canvasCtx.lineTo((Math.sin((i * du) / 180 * Math.PI) * Rv2 + oW / 2), -Math.cos((i * du) / 180 * Math.PI) * Rv2 + oH / 2);
                            canvasCtx.strokeStyle = color1;
                            canvasCtx.stroke();
                        }
                        canvasCtx.font = "italic bold 20px Microsoft Yahei";
                        canvasCtx.fillStyle = color2;
                        canvasCtx.textAlign = "center";
                        canvasCtx.textBaseline = "middle";
                        canvasCtx.fillText(file.name.split('.mp3')[0], oW / 2, oH / 2);
                        requestAnimationFrame(drawSpectrum);
                    })();
                });
            })
        }
    });

    loadFullscreen();
}