示波器插件测试
<style>#papa { margin: auto; width: 760px; height: 460px; background: gray; box-shadow: 3px 3px 20px #000; position: relative; }
</style>
<div id="papa"></div>
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=1324441790.mp3" autoplay loop></audio>
<script>
(function() {
(function(mkPlayer) {let defaults = {ypData: new Array(600).fill(0).map((v, k) => Math.floor(Math.random() * 200) + 10),player_css: 'bottom: 15px; left: 50%; transform: translate(-50%); ',playerCode: `<style>#mplayer { --color1: red; --color2: pink; --ww: 200; --hh: 80; position: absolute; cursor: pointer; }</style><canvas id="mplayer"></canvas>`,};let playCode = (user_config) => {let data = Object.assign({}, defaults, user_config);papa.innerHTML += data.playerCode;mplayer.style.cssText += data.player_css;let ctx = mplayer.getContext('2d');let getCssVal = (e,v) => getComputedStyle(e).getPropertyValue(v);let w = mplayer.width = getCssVal(mplayer,'--ww').replace(/[^0-9]/ig,''), h = mplayer.height = getCssVal(mplayer,'--hh').replace(/[^0-9]/ig,''), idx = 0;let slice = w / data.ypData.length, vmax = Math.max.apply(null, data.ypData);mplayer.onmousemove = (e) => { mplayer.title = e.offsetY < h * 0.8 ? toMin(aud.duration * e.offsetX / w) : '暂停/播放'; };mplayer.onclick = (e) => {if(e.offsetY < h * 0.8) {let ac = aud.duration * e.offsetX / w;idx = Math.round(data.ypData.length * ac / aud.duration);aud.currentTime = ac;} else {aud.paused ? aud.play() : aud.pause();}};aud.addEventListener('timeupdate', () => {idx = Math.round(data.ypData.length * aud.currentTime / aud.duration);if(idx > data.ypData.length - 1) idx = data.ypData.length - 1;draw();});let draw = () => {ctx.clearRect(0,0,w,h);ctx.strokeStyle = getCssVal(mplayer,'--color1');ctx.fillStyle = getCssVal(mplayer,'--color2');ctx.font = '14px sans-serif';ctx.shadowOffsetX = ctx.shadowOffsetY = 1;ctx.shadowBlur = 2;ctx.shadowColor = '#555';ctx.textAlign = 'center';ctx.beginPath();for(j = 0; j <= idx; j ++) {ctx.lineTo(slice*j, h - data.ypData * h / vmax);}ctx.stroke();ctx.beginPath();ctx.strokeStyle = getCssVal(mplayer,'--color2');for(j = idx; j < data.ypData.length; j ++) {ctx.lineTo(slice*j, h - data.ypData * h / vmax);}ctx.stroke();ctx.fillText((aud.paused ? '播放 ' : '暂停 ') + toMin(aud.currentTime) + ' / ' + toMin(aud.duration), w/2, h*0.95);};let toMin = (val) => {if (!val) return '00:00';val = Math.floor(val);let min = parseInt(val / 60), sec = parseFloat(val % 60);if (min < 10) min = '0' + min;if (sec < 10) sec = '0' + sec;return min + ':' + sec;};draw();};mkPlayer.HCPlayer = playCode;})(this);
ypData = ;
HCPlayer({
ypData: ypData,
player_css: '--color1: purple; --color2: snow; --ww: 280px; --hh: 80px; left: calc(50% - 140px); bottom: 20px; ',
});
})();
</script>
插件代码:
(function(mkPlayer) {let defaults = {ypData: new Array(600).fill(0).map((v, k) => Math.floor(Math.random() * 200) + 10),player_css: 'bottom: 15px; left: 50%; transform: translate(-50%); ',playerCode: `<style>#mplayer { --color1: red; --color2: pink; --ww: 200; --hh: 80; position: absolute; cursor: pointer; }</style><canvas id="mplayer"></canvas>`,};let playCode = (user_config) => {let data = Object.assign({}, defaults, user_config);papa.innerHTML += data.playerCode;mplayer.style.cssText += data.player_css;let ctx = mplayer.getContext('2d');let getCssVal = (e,v) => getComputedStyle(e).getPropertyValue(v);let w = mplayer.width = getCssVal(mplayer,'--ww').replace(/[^0-9]/ig,''), h = mplayer.height = getCssVal(mplayer,'--hh').replace(/[^0-9]/ig,''), idx = 0;let slice = w / data.ypData.length, vmax = Math.max.apply(null, data.ypData);mplayer.onmousemove = (e) => { mplayer.title = e.offsetY < h * 0.8 ? toMin(aud.duration * e.offsetX / w) : '暂停/播放'; };mplayer.onclick = (e) => {if(e.offsetY < h * 0.8) {let ac = aud.duration * e.offsetX / w;idx = Math.round(data.ypData.length * ac / aud.duration);aud.currentTime = ac;} else {aud.paused ? aud.play() : aud.pause();}};aud.addEventListener('timeupdate', () => {idx = Math.round(data.ypData.length * aud.currentTime / aud.duration);if(idx > data.ypData.length - 1) idx = data.ypData.length - 1;draw();});let draw = () => {ctx.clearRect(0,0,w,h);ctx.strokeStyle = getCssVal(mplayer,'--color1');ctx.fillStyle = getCssVal(mplayer,'--color2');ctx.font = '14px sans-serif';ctx.shadowOffsetX = ctx.shadowOffsetY = 1;ctx.shadowBlur = 2;ctx.shadowColor = '#555';ctx.textAlign = 'center';ctx.beginPath();for(j = 0; j <= idx; j ++) {ctx.lineTo(slice*j, h - data.ypData * h / vmax);}ctx.stroke();ctx.beginPath();ctx.strokeStyle = getCssVal(mplayer,'--color2');for(j = idx; j < data.ypData.length; j ++) {ctx.lineTo(slice*j, h - data.ypData * h / vmax);}ctx.stroke();ctx.fillText((aud.paused ? '播放 ' : '暂停 ') + toMin(aud.currentTime) + ' / ' + toMin(aud.duration), w/2, h*0.95);};let toMin = (val) => {if (!val) return '00:00';val = Math.floor(val);let min = parseInt(val / 60), sec = parseFloat(val % 60);if (min < 10) min = '0' + min;if (sec < 10) sec = '0' + sec;return min + ':' + sec;};draw();};mkPlayer.HCPlayer = playCode;})(this);
本帖最后由 马黑黑 于 2022-12-16 18:06 编辑
插件调用方法
<script>
(function() {
//插件代码略
//音频数据数组略
HCPlayer({
ypData: ypData,
player_css: '--color1: purple; --color2: snow; --ww: 280px; --hh: 80px; left: calc(50% - 140px); bottom: 20px; ',
});
})();
</script>参数① ypData
可以省略,省略是音频数据数组和 ypData: ypData, 都不要!
省略 ypData 参数,意味着使用插件准备的随机音频音波数据,属于模拟示波,不能反映出歌曲的声音状态。
参数② player_css
一是两个颜色CSS变量:--color1 和 --color2,前者是示波的着色,后者是示波的底色。支持所有颜色表达法,不支持渐变背景颜色;
二是两个宽高CSS变量:--ww 和 --hh,前者表示示波图的长度、后者表示高度,长度建议200起、高度60起,数值可以不要 px 等单位,要也可以;
三是定位,用CSS属性,left/right 和 top/bottom 两两配对即可。
【附】最简单的调用方法:
<style>
#papa { margin: auto; width: 760px; height: 460px; background: gray; box-shadow: 3px 3px 20px #000; position: relative; }
</style>
<div id="papa"></div>
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=1324441790.mp3" autoplay loop></audio>
<script>
(function() {
//这里是插件代码不能省略
HCPlayer({});
})();
</script>
一楼完整代码<style>
#papa { margin: auto; width: 760px; height: 460px; background: gray; box-shadow: 3px 3px 20px #000; position: relative; }
</style>
<div id="papa"></div>
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=1324441790.mp3" autoplay loop></audio>
<script>
(function() {
(function(mkPlayer) {let defaults = {ypData: new Array(600).fill(0).map((v, k) => Math.floor(Math.random() * 200) + 10),player_css: 'bottom: 15px; left: 50%; transform: translate(-50%); ',playerCode: `<style>#mplayer { --color1: red; --color2: pink; --ww: 200; --hh: 80; position: absolute; cursor: pointer; }</style><canvas id="mplayer"></canvas>`,};let playCode = (user_config) => {let data = Object.assign({}, defaults, user_config);papa.innerHTML += data.playerCode;mplayer.style.cssText += data.player_css;let ctx = mplayer.getContext('2d');let getCssVal = (e,v) => getComputedStyle(e).getPropertyValue(v);let w = mplayer.width = getCssVal(mplayer,'--ww').replace(/[^0-9]/ig,''), h = mplayer.height = getCssVal(mplayer,'--hh').replace(/[^0-9]/ig,''), idx = 0;let slice = w / data.ypData.length, vmax = Math.max.apply(null, data.ypData);mplayer.onmousemove = (e) => { mplayer.title = e.offsetY < h * 0.8 ? toMin(aud.duration * e.offsetX / w) : '暂停/播放'; };mplayer.onclick = (e) => {if(e.offsetY < h * 0.8) {let ac = aud.duration * e.offsetX / w;idx = Math.round(data.ypData.length * ac / aud.duration);aud.currentTime = ac;} else {aud.paused ? aud.play() : aud.pause();}};aud.addEventListener('timeupdate', () => {idx = Math.round(data.ypData.length * aud.currentTime / aud.duration);if(idx > data.ypData.length - 1) idx = data.ypData.length - 1;draw();});let draw = () => {ctx.clearRect(0,0,w,h);ctx.strokeStyle = getCssVal(mplayer,'--color1');ctx.fillStyle = getCssVal(mplayer,'--color2');ctx.font = '14px sans-serif';ctx.shadowOffsetX = ctx.shadowOffsetY = 1;ctx.shadowBlur = 2;ctx.shadowColor = '#555';ctx.textAlign = 'center';ctx.beginPath();for(j = 0; j <= idx; j ++) {ctx.lineTo(slice*j, h - data.ypData * h / vmax);}ctx.stroke();ctx.beginPath();ctx.strokeStyle = getCssVal(mplayer,'--color2');for(j = idx; j < data.ypData.length; j ++) {ctx.lineTo(slice*j, h - data.ypData * h / vmax);}ctx.stroke();ctx.fillText((aud.paused ? '播放 ' : '暂停 ') + toMin(aud.currentTime) + ' / ' + toMin(aud.duration), w/2, h*0.95);};let toMin = (val) => {if (!val) return '00:00';val = Math.floor(val);let min = parseInt(val / 60), sec = parseFloat(val % 60);if (min < 10) min = '0' + min;if (sec < 10) sec = '0' + sec;return min + ':' + sec;};draw();};mkPlayer.HCPlayer = playCode;})(this);
ypData = ;
HCPlayer({
ypData: ypData,
player_css: '--color1: purple; --color2: snow; --ww: 280px; --hh: 80px; left: calc(50% - 140px); bottom: 20px; ',
});
})();
</script>
黑黑又把这个示波器封装了,真棒{:4_199:} 我做了一个,怎么示波和时间00:00离得那么近,都重叠了,这个应该调什么? 黑黑老师又出新教程了,等着看精彩的作业{:4_187:} 千羽 发表于 2022-12-16 20:31
黑黑老师又出新教程了,等着看精彩的作业
作业是你的{:4_170:} 红影 发表于 2022-12-16 19:55
黑黑又把这个示波器封装了,真棒
目前没有lrc歌词同步 红影 发表于 2022-12-16 20:10
我做了一个,怎么示波和时间00:00离得那么近,都重叠了,这个应该调什么?
换个声音频道再试吧 马黑黑 发表于 2022-12-16 20:39
作业是你的
好啊,明天估计很晚才会有空,,有时间就做,还不知道会不会呢{:4_203:} 千羽 发表于 2022-12-16 20:42
好啊,明天估计很晚才会有空,,有时间就做,还不知道会不会呢
不急慢慢来 马黑黑 发表于 2022-12-16 20:43
不急慢慢来
嗯·,{:4_181:} 千羽 发表于 2022-12-16 20:44
嗯·,
喝水{:4_191:} 马黑黑 发表于 2022-12-16 20:52
喝水
黑黑老师多喝咖啡{:4_181:} 这不是心电图的示波器吗?{:5_117:} 寒冬残荷 发表于 2022-12-16 20:59
这不是心电图的示波器吗?
示波图,心电图恰好也用的原理 千羽 发表于 2022-12-16 20:55
黑黑老师多喝咖啡
我喜欢咖啡,不加糖 马黑黑 发表于 2022-12-16 21:22
我喜欢咖啡,不加糖
晚上就多多地喝苦咖啡{:4_173:} 千羽 发表于 2022-12-16 21:46
晚上就多多地喝苦咖啡
忆苦思甜挺好