美文网首页HTML
做一个网易云音乐可视化工具

做一个网易云音乐可视化工具

作者: MangfuStudio | 来源:发表于2020-10-04 18:32 被阅读0次

    前言

    最近在Github上看到了一个音乐可视化前端库:vudio.js https://github.com/alex2wong/vudio.js

    效果有点炫酷:



    本人是非常喜欢将音频可视化的效果,联想到之前的网易云地址解析API,决定将两者结合,做个简单的网易云音乐可视化小工具。

    今天将制作过程记录一下。

    以下是演示效果:
    https://static.cdnjs.cloud/2020104_box/6f27a474b6a546c71ea3b6951a16e813_2020-10-04-16-55-23.mp4_2020-10-04-16-55-23.mp4

    除此之外,我也将它推送到了Gitee Page上,你可以通过以下地址体验(受限于网易云地址解析API,无法播放VIP音乐,有点遗憾):
    https://txb582.gitee.io/%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90%E5%8F%AF%E8%A7%86%E5%8C%96/index.html

    思路

    大体思路是:
    1、可视化工具获取用户输入的网易云分享链接。
    2、调用解析API将分享地址解析为音乐真实地址实现播放。
    3、调用vudio.js将音乐可视化。
    解析API和可视化库都准备好了,主要的开发工作就只有可视化工具页面的开发
    在该工具中,用到了以下东西:

    • axios网络请求库
    • 网易云地址解析API
    • 音频可视化库vudio.js

    开发

    1、建立常用的目录结构

    2、页面结构

    页面主要分为两大块
    1、可视化动画区域
    2、悬浮于右侧的可收拉菜单



    页面布局代码

    <body id="body">
        <div id="box-show">
        </div>
        <div id="box-menu">
        </div>
    </body>
    

    然后在可视化区域添加
    <audio>和<canvas>元素,用于音乐的播放和可视化动画的绘制。

    <body id="body">
        <div id="box-show">
            <audio id="audio" src=""></audio>
            <canvas id="canvas">
                你的浏览器不支持Canvas
            </canvas>
        </div>
        <div id="box-menu">
        </div>
    </body>
    

    在菜单中添加
    两个<div>用于放置收放按钮和菜单主体

    <body id="body">
        <div id="box-show">
            <audio id="audio" src=""></audio>
            <canvas id="canvas">
                你的浏览器不支持Canvas
            </canvas>
        </div>
        <div id="box-menu">
            <div id="box-menu-pull">
            </div>
            <div id="box-menu-list">
            </div>
        </div>
    </body>
    

    在按钮区域放置一个<button>作为菜单收放按钮
    在菜单主体区域放置
    <img>用于显示关照二维码
    <span>用于显示提示
    两个用div包裹起来的<input>实现搜索栏
    还有两个嵌套的<div>用于显示播放的历史记录,用两个<div>嵌套是因为后续为了不让滚动条影响页面美观,使用嵌套的方式通过位移来隐藏滚动条。

    <body id="body">
        <div id="box-show">
            <audio id="audio" src=""></audio>
            <canvas id="canvas">
                你的浏览器不支持Canvas
            </canvas>
        </div>
        <div id="box-menu">
            <div id="box-menu-pull">
                <button>></button>
            </div>
            <div id="box-menu-list">
                <img src="./images/微信公众号二维码.jpg">
                <span> 扫码关注我们 | MF工作室 </span>
                <div>
                    <input id="search-input" type="text" placeholder="网易云音乐链接">
                    <input id="search-button" type="button" value="GO">
                </div>
                <div>
                    <div id="box-menu-list-historical"></div>
                </div>
            </div>
        </div>
    </body>
    

    然后引入必要的文件

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>网易云音乐可视化工具 | MF工作室</title>
        <link rel="shortcut icon" href="./images/logo.ico" type="image/x-icon">
        <meta http-equiv="Access-Control-Allow-Origin" content="viapi.cn/wyy">
        <link rel="stylesheet" href="./css/index.css">
        <script src="./js/vudio.js"></script>
        <script src="./js/axios.min.js"></script>
        <script src="./js/index.js"></script>
    </head>
    

    3、页面样式

    /* 清空所有边距并禁止用户复制选择页面内容 */
    * {
        margin: 0px;
        border: 0px;
        padding: 0px;
        user-select: none;
        box-sizing: border-box;
    }
    /* 将html,body 设置与窗口一致, 方便高度使用百分比 */
    html, body {
        width: 100%;
        height: 100%;
    }
    /* 设置页面背景渐变, 如果你想, 也可以用图片替代 */
    body {
        background-image: linear-gradient(#f28fb2, #6cbffd);
        background-repeat: no-repeat;
        background-size: cover;
    }
    /* 可视化区域设置为充满body元素 */
    #box-show {
        width: 100%;
        height: 100%;
        display: flex;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
    }
    #box-show>canvas {
        max-width: 100%;
    }
    #box-show>audio {
        display: none;
    }
    /* 将菜单设置为绝对定位, 固定在页面右侧 */
    #box-menu {
        width: 350px;
        height: 100%;
        position: fixed;
        top: 0px;
        right: 0px;
        opacity: 0.6;
        transition: right 0.5s;
        display: flex;
    }
    /* 收拉按钮区域使用flex布局, 建按钮居中显示 */
    #box-menu-pull {
        width: 50px;
        height: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
    }
    /* 设置收拉按钮样式 */
    #box-menu-pull>button {
        width: 50px;
        height: 50px;
        font-size: 30px;
        border-radius: 50% 0% 0% 50%;
        outline: none;
        background-color: rgba(142, 194, 243, 0.8);
        color: #FFFFFF;
    }
    /* 使用flex布局, 将菜单主体中的内容垂直居中显示 */
    #box-menu-list {
        width: 300px;
        height: 100%;
        padding-top: 20px;
        padding-bottom: 20px;
        margin-bottom: 20px;
        background-color: rgba(142, 194, 243, 0.8);
        display: flex;
        flex-direction: column;
        align-items: center;
        overflow-y: auto;
    }
    /* 公众号二维码样式 */
    #box-menu-list>img {
        width: 85%;
        border: 5px solid rgba(151, 199, 231, 0.8);
        border-radius: 10px;
    }
    /* 提示语样式 */
    #box-menu-list>span:nth-of-type(1) {
        color: #ffffff;
    }
    /* 搜索栏样式 */
    #box-menu-list>div:nth-of-type(1) {
        width: 90%;
        height: 40px;
        display: flex;
        justify-content: center;
        align-items: center;
        margin-top: 10px;
        border-radius: 5px;
    }
    /* 搜索栏输入框样式 */
    #search-input {
        height: 100%;
        width: calc(100% - 40px);
        background-color: rgba(151, 199, 231, 0.8);
        outline: none;
        padding-left: 5px;
        padding-right: 5px;
        color: #FFFFFF;
    }
    #search-input::-webkit-input-placeholder { color: #FFFFFF; }
    #search-input::-moz-placeholder { color: #FFFFFF; }
    #search-input:-moz-placeholder { color: #FFFFFF; }
    #search-input:-ms-input-placeholder { color: #FFFFFF; }
    /* 搜索栏提交按钮样式 */
    #search-button {
        width: 40px;
        height: 100%;
        background-color: rgba(151, 199, 231, 0.8);
        outline: none;
        border-left: 1px solid #c8d5dd;
        color: #FFFF;
    }
    /* 历史播放记录显示区域样式 */
    #box-menu-list>div:nth-of-type(2) {
        width: 100%;
        height: 55%;
        overflow: hidden;
    }
    #box-menu-list-historical{
        width: 100%;
        height: 100%;
        overflow: auto;
        /* 相对于正常位置右移15像素, 这样就可以使用上层元素遮盖掉滚动条了 */
        position: relative;
        right: -15px;
    }
    #box-menu-list-historical>button {
        display: block;
        padding: 10px;
        width: 95%;
        border-radius: 5px;
        margin-top: 10px;
        color: #FFFFFF;
        background-color: rgba(151, 199, 231, 0.8);
        position: relative;
        right: 15px;
        outline: none;
    }
    

    4、页面逻辑

    window.onload = function () {
        var menu = document.getElementById("box-menu");
        var menu_pull_button = document.querySelector("#box-menu-pull > button");
        var box_menu_list_historical = document.getElementById("box-menu-list-historical");
        var audio_object = document.getElementById("audio");
        // 允许跨域读取音频, 如果不设置, 在调用API时浏览器会因为同源策略阻止音乐拉取
        audio_object.crossOrigin = "anonymous";
        var canvas_object = document.getElementById("canvas");
        var search_button = document.getElementById("search-button");
        var search_input = document.getElementById("search-input");
        // 侧边菜单点击 拉出/隐藏
        var is_pull = true;
        menu_pull_button.onclick = function () {
            if (is_pull) {
                menu.style.right = "-300px";
                menu_pull_button.innerText = "<";
                is_pull = false;
            } else {
                menu.style.right = "0px";
                menu_pull_button.innerText = ">";
                is_pull = true;
            }
        }
        // 提交按钮点击处理
        search_button.onclick = function () {
            // 从网易云分享链接中提取音乐ID
            source_music_url = search_input.value;
            source_musid_id = ((source_music_url.split("?")[1]).split("&")[0]).split("=")[1];
            // 调用API解析音乐真实地址, API具体使用方法参考: https://api.565.ink/docs#/Lan%E5%B7%A5%E5%85%B7%E7%AE%B1/wangyiyunmc_163mc_get
            axios.get(`https://api.565.ink/163mc?id=${source_musid_id}`).then(function (response) {
                console.log(response.data);
                music_url = response.data["resulturl"];
                audio_object.setAttribute("src", music_url);
                audio_object.play();
                // 向菜单列表插入历史播放记录按钮
                let button = document.createElement("button");
                button.setAttribute("data-music-url", response.data["resulturl"]);
                button.innerText = source_musid_id;
                button.onclick = function () {
                    audio_object.setAttribute("src", this.getAttribute("data-music-url"));
                    audio_object.play();
                }
                box_menu_list_historical.appendChild(button)
            })
        }
        // 音频可视化, 具体使用方法参考: https://github.com/alex2wong/vudio
        var vudio = new Vudio(audio_object, canvas_object, {
            effect: 'circlebar',
            accuracy: 128, 
            width: 400,
            height: 400, 
            waveform: {
                maxHeight: 80,
                minHeight: 1,
                spacing: 1,
                shadowBlur: 0, 
                fadeSide: true, 
                horizontalAlign: 'center', 
                verticalAlign: 'middle' 
            }
        });
        vudio.dance();
    }
    
    

    相关文章

      网友评论

        本文标题:做一个网易云音乐可视化工具

        本文链接:https://www.haomeiwen.com/subject/fabnuktx.html