早期写过一个web壁纸,其中令我最不满意的就是可视化频谱的实现,因为看起来特别僵硬 😶🌫️
https://steamcommunity.com/sharedfiles/filedetails/?id=2762672832
About
Wallpaper Engine中音频的返回格式其实就是两组数组,一组左声道,另一组是右声道,没记错的话我这边应该只取了其中之一,并且这边的实现是用的Canvas,只记得写了一大把的js代码,光圆角就搜了老半天
然而就目前来说,我对Canvas依然不是很熟悉,令人感叹
另外,导致僵硬的原因是因为高度是直接变化的,缺少了过渡
于是我用 Js + CSS 实现了一波 🤔
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="container">
<div class="line-container">
<div class="line" id="line_1"></div>
<div class="line" id="line_2"></div>
<div class="line" id="line_3"></div>
<div class="line" id="line_4"></div>
<div class="line" id="line_5"></div>
<div class="line" id="line_6"></div>
<div class="line" id="line_7"></div>
<div class="line" id="line_8"></div>
<div class="line" id="line_9"></div>
<div class="line" id="line_10"></div>
<div class="line" id="line_11"></div>
<div class="line" id="line_12"></div>
<div class="line" id="line_13"></div>
<div class="line" id="line_14"></div>
<div class="line" id="line_15"></div>
</div>
</div>
</body>
<script>
window.onload = () => {
setInterval(() => {
generate()
}, 100)
}
const generate = () => {
for (let i = 0; i < 15; i++) {
let h = random(500, 0)
let line = document.querySelector('#line_' + (i + 1))
line.style.height = h + 'px'
}
}
const random = (Max, Min) => {
let Range = Max - Min;
let Rand = Math.random();
return Min + Math.round(Rand * Range);
}
</script>
<style>
body {
margin: unset;
}
#container {
height: 550px;
display: flex;
justify-content: center;
position: relative;
}
.line-container {
display: flex;
gap: 15px;
align-items: flex-end;
}
.line {
width: 15px;
border-radius: 10px;
background-color: rgba(141, 114, 225, .5);
box-shadow: 0 0 8px rgba(141, 114, 225, .4);
transition: all .4s;
}
</style>
</html>
虽然用这种方式实现起来要简单很多,但是论实现效果的上限那必然还是Canvas,有时间再买本书看看捏 😴
...
于是我买了
to demo ~这边是一个使用canvas实现的demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Canvas Demo</title>
</head>
<body>
<canvas id="AudioCanvas"></canvas>
</body>
<script>
let audioCanvas
let audioCanvasCtx
let lineMaxH = 200
// 音柱宽度, 右外边距, 音柱数量, 缓动系数
let lineW = 5, margiRight = 5, num = 20, easing = 0.03
// 记录上一个高度
let lastH = []
window.onload = () => {
audioCanvas = document.querySelector('#AudioCanvas')
audioCanvas.width = window.innerWidth
audioCanvas.height = window.innerHeight
audioCanvasCtx = audioCanvas.getContext('2d')
audioCanvasCtx.save();
// (function handle() {
// window.requestAnimationFrame(handle)
//
// })();
setInterval(() => {
let audioArray = genArray()
// 总宽
let allW = (num * (lineW + margiRight)) - margiRight
// 起始点
let beginPointY = window.innerHeight - 100
let x = (window.innerWidth / 2) - (allW / 2)
audioCanvasCtx.clearRect(0, 0, audioCanvas.width, audioCanvas.height)
for (let i = 0; i < audioArray.length; ++i) {
let newH = audioArray[i];
if (!lastH[i]) lastH[i] = 0
let v = (newH - lastH[i]) * easing
lastH[i] += v
fillLine(audioCanvasCtx, x, beginPointY, lineW, lastH[i], 'white')
x += (lineW + margiRight)
}
}, 10)
}
const genArray = () => {
let arr = []
for (let i = 0; i < 10; i++) {
arr.push(random(lineMaxH, 0))
}
return arr;
}
const random = (Max, Min) => {
let Range = Max - Min;
let Rand = Math.random();
return Min + Math.round(Rand * Range);
}
const fillLine = (ctx, x, y, w, h, color) => {
// 绘制方形
ctx.save()
ctx.translate(x, y)
ctx.scale(1, -1)
ctx.fillStyle = color;
ctx.beginPath();
ctx.fillRect(0, 0, w, h)
ctx.closePath();
ctx.fill();
ctx.restore();
// 绘制顶部圆
ctx.save()
ctx.translate(x, y - h)
ctx.scale(1, -1)
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc((w / 2), 0, (w / 2), 0, 360 * Math.PI / 180, false);
ctx.closePath();
ctx.fill();
ctx.restore();
// 绘制底部圆
ctx.save()
ctx.translate(x, y)
ctx.scale(1, -1)
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc((w / 2), 0, (w / 2), 0, 360 * Math.PI / 180, false);
ctx.closePath();
ctx.fill();
ctx.restore();
}
</script>
<style>
body {
background: black;
margin: unset;
}
canvas {
height: 100vh;
width: 100vw;
position: absolute;
top: 0;
}
</style>
</html>
并且我重新上传了一版到创意工坊
Comments | NOTHING