章节内容
历史介绍
开发环境
代码封装
函数式
获取小说命令行版(上)
获取小说命令行版(中)
获取小说命令行版(下)
嵌入到应用中
插件机制
文字转语音
设置与信号中断
插件商店
下载与删除(上)
下载与删除(下)
通知栏程序
播放功能
美化界面
数据可视化(上)
数据可视化(中)
数据可视化(下)
嵌入到应用中
打包应用

实现音频的播放只需要使用 Audio 标签即可,但是由于一些安全策略会禁止载入文件,所以我们要关闭安全策略。

# 关闭安全策略

关闭掉 webSecurity ,这样就可以读取本地的音频文件了,记得重启 Electron。

mainWindow = createMainWindow({
  width: 400,
  height: 560,
  frame: false,
  transparent: true,
  show: false,
  webPreferences: {
    webSecurity: false
  }
})

# 播放页面

我们先实现功能,之后再美化界面,我们现在通过 remote 访问主进程的一些模块,来选取文件夹,对 Mp3 文件进行排序,通过监听 svelte 的 state 状态修改事件,来监视播放地址的修改,这里一定要加上文件协议 file:// 要不然会报错,这里没有做平台兼容,平台的路径少许不同。

<Back/>
<div>
    <button on:click="next()">next</button>
    <button on:click="prev()">prev</button>
    <button on:click="file()">file</button>
</div>

<script>
    import {
        ipcRenderer,
        remote
    } from "electron";
    const {
        dialog,
        app
    } = remote
    const {
        readdir
    } = remote.require('fs-extra')
    import {
        resolve
    } from 'path'
    export default {
        data() {
            return {
                currentSrc: '',
                index: 0,
                files: []
            };
        },
        components: {
            Back: '../components/Back.svelte'
        },
        oncreate() {
            this.player = new Audio()
            document.querySelector('#app').appendChild(this.player)
            this.player.onended = this.next // 播放完成下一首
            this.on('state', ({
                changed
            }) => {
                if (changed.currentSrc) {
                    this.player.src = this.get().currentSrc
                    this.play()
                }
            })
        },
        methods: {
            next() { // 下一曲
                const {
                    index,
                    files
                } = this.get()
                let i = index + 1
                if (i > files.length - 1) { // 边界守护
                    i = files.length - 1
                }
                this.set({
                    index: i,
                    currentSrc: "file://" + files[i]
                })
            },
            prev() { // 上一曲
                const {
                    index,
                    files
                } = this.get()
                let i = index - 1
                if (i < 0) { // 边界守护
                    i = 0
                }
                this.set({
                    index: i,
                    currentSrc: "file://" + files[i]
                })
            },
            play() { // 播放
                this.player.play()
            },
            pause() { // 暂停
                this.play.pause()
            },
            file() { // 选取文件
                dialog.showOpenDialog({
                    title: '选择音乐目录',
                    defaultPath: app.getPath('home'),
                    properties: ['openDirectory']
                }, async(folders) => {
                    if (folders.length > 0) {
                        const folder = folders[0]
                        let files = await readdir(folder)

                        const compare = (a, b) => { // 比较字符串前面的数字
                            let t1 = a.split('-')[0];
                            let t2 = b.split('-');
                            return parseInt(t1) - parseInt(t2)
                        }

                        files = files.sort(compare).map(file => resolve(folder, file)) // 文件排序
                        this.set({
                            files,
                            currentSrc: "file://" + files[0]
                        })
                    }
                })
            }
        }
    };
</script>