├── .eslintignore
├── src
├── default.jpg
├── demo
│ ├── favicon.ico
│ ├── main.js
│ ├── index.html
│ └── App.vue
├── assets
│ ├── vue-aplayer.png
│ ├── vue-aplayer-round.png
│ ├── repeat-all.svg
│ ├── loading.svg
│ ├── play.svg
│ ├── shuffle.svg
│ ├── pause.svg
│ ├── repeat-one.svg
│ ├── volume-off.svg
│ ├── repeat-all-legacy.svg
│ ├── no-repeat.svg
│ ├── menu.svg
│ ├── skip.svg
│ ├── lrc.svg
│ ├── volume-down.svg
│ ├── repeat-one-legacy.svg
│ └── volume-up.svg
├── scss
│ └── variables.scss
├── components
│ ├── aplayer-iconbutton.vue
│ ├── aplayer-icon.vue
│ ├── aplayer-controller-volume.vue
│ ├── aplayer-thumbnail.vue
│ ├── aplayer-list.vue
│ ├── aplayer-controller.vue
│ ├── aplayer-lrc.vue
│ └── aplayer-controller-progress.vue
├── utils.js
└── vue-aplayer.vue
├── postcss.config.js
├── .babelrc
├── renovate.json
├── .editorconfig
├── .eslintrc.js
├── .travis.yml
├── LICENSE
├── webpack.config.js
├── .gitignore
├── package.json
├── webpack.demo.config.js
├── README.md
└── docs
├── README.zh-CN.md
└── README.md
/.eslintignore:
--------------------------------------------------------------------------------
1 | /demo/
2 | /dist/
3 | /*.js
4 |
--------------------------------------------------------------------------------
/src/default.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SevenOutman/vue-aplayer/HEAD/src/default.jpg
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | require('autoprefixer')
4 | ]
5 | }
--------------------------------------------------------------------------------
/src/demo/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SevenOutman/vue-aplayer/HEAD/src/demo/favicon.ico
--------------------------------------------------------------------------------
/src/assets/vue-aplayer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SevenOutman/vue-aplayer/HEAD/src/assets/vue-aplayer.png
--------------------------------------------------------------------------------
/src/assets/vue-aplayer-round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SevenOutman/vue-aplayer/HEAD/src/assets/vue-aplayer-round.png
--------------------------------------------------------------------------------
/src/scss/variables.scss:
--------------------------------------------------------------------------------
1 | $aplayer-height: 66px;
2 | $lrc-height: 30px;
3 | $aplayer-height-lrc: $aplayer-height + $lrc-height - 6;
4 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@babel/preset-env",
5 | {
6 | "modules": false
7 | }
8 | ]
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:js-lib",
4 | ":autodetectPinVersions",
5 | ":automergeMinor",
6 | ":automergeBranchPush",
7 | "schedule:daily"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | end_of_line = lf
7 | indent_style = space
8 | indent_size = 2
9 | trim_trailing_whitespace = true
10 | insert_final_newline = false
11 |
--------------------------------------------------------------------------------
/src/assets/repeat-all.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/loading.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/play.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/shuffle.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/pause.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/repeat-one.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/volume-off.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/demo/main.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Doma on 2016/11/22.
3 | */
4 | import Vue from 'vue'
5 | import VueAPlayer from '../vue-aplayer.vue'
6 | Vue.config.devtools = true
7 | // VueAPlayer.disableVersionBadge = true
8 |
9 | import App from './App.vue'
10 | new Vue({
11 | el: '#app',
12 | render: h => h(App)
13 | })
14 |
--------------------------------------------------------------------------------
/src/assets/repeat-all-legacy.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/no-repeat.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/menu.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/skip.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/lrc.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/volume-down.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | // https://eslint.org/docs/user-guide/configuring
2 |
3 | module.exports = {
4 | root: true,
5 | parserOptions: {
6 | parser: 'babel-eslint'
7 | },
8 | env: {
9 | browser: true,
10 | },
11 | // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
12 | // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
13 | extends: ['plugin:vue/essential'],
14 | // required to lint *.vue files
15 | plugins: [
16 | 'vue'
17 | ],
18 | // add your custom rules here
19 | rules: {
20 | // allow debugger during development
21 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
22 | 'space-before-function-paren': ['error', 'always']
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "lts/*"
4 |
5 | cache:
6 | yarn: true
7 | directories:
8 | - "node_modules"
9 |
10 | # use latest yarn
11 | before_install:
12 | - curl -o- -L https://yarnpkg.com/install.sh | bash
13 | - export PATH=$HOME/.yarn/bin:$PATH
14 |
15 | # fix upath incompatibility
16 | install: yarn --ignore-engines
17 |
18 | # GitHub Pages deploy
19 | before_deploy:
20 | - npm run predeploy
21 |
22 | deploy:
23 | - provider: pages
24 | skip-cleanup: true
25 | github-token: $GITHUB_TOKEN # Set in travis-ci.org dashboard, marked secure
26 | keep-history: true
27 | on:
28 | branch: master
29 | local-dir: demo
30 | - provider: npm
31 | skip-cleanup: true
32 | email: "leishenghao@126.com"
33 | api_key: $NPM_AUTH_TOKEN
34 | on:
35 | tags: true
--------------------------------------------------------------------------------
/src/components/aplayer-iconbutton.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/assets/repeat-one-legacy.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016-present Shenghao "Doma" Lei
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/components/aplayer-icon.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/assets/volume-up.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var webpack = require('webpack')
3 |
4 | module.exports = {
5 | entry: './src/vue-aplayer.vue',
6 | output: {
7 | path: path.resolve(__dirname, 'dist'),
8 | filename: 'vue-aplayer.min.js',
9 | library: 'VueAPlayer',
10 | libraryTarget: 'umd',
11 | libraryExport: 'default',
12 | umdNamedDefine: true
13 | },
14 |
15 | externals: {
16 | 'hls.js': {
17 | amd: 'hls.js',
18 | commonjs: 'hls.js',
19 | commonjs2: 'hls.js',
20 | root: 'Hls'
21 | },
22 | 'vue': {
23 | amd: 'vue',
24 | commonjs: 'vue',
25 | commonjs2: 'vue',
26 | root: 'Vue'
27 | },
28 | },
29 |
30 | module: {
31 | rules: [
32 | {
33 | test: /\.(js|vue)$/,
34 | loader: 'eslint-loader',
35 | enforce: 'pre',
36 | include: [path.resolve(__dirname, 'src')],
37 | options: {
38 | formatter: require('eslint-friendly-formatter'),
39 | emitWarning: true
40 | }
41 | },
42 | {
43 | test: /\.vue$/,
44 | loader: 'vue-loader',
45 | options: {
46 | loaders: {
47 | scss: 'vue-style-loader!css-loader?minimize=true!postcss-loader!sass-loader'
48 | },
49 | }
50 | },
51 | {
52 | test: /\.js$/,
53 | loader: 'babel-loader',
54 | exclude: /node_modules/,
55 | },
56 | {
57 | test: /\.(png|jpg)$/,
58 | loader: 'url-loader?limit=40000'
59 | },
60 | {
61 | test: /\.svg$/,
62 | loader: 'svg-inline-loader'
63 | },
64 | {
65 | test: /\.html$/,
66 | loader: 'vue-html-loader'
67 | }
68 | ]
69 | },
70 | devtool: '#source-map',
71 | plugins: [
72 | new webpack.DefinePlugin({
73 | 'process.env': {
74 | NODE_ENV: `"${process.env.NODE_ENV}"`
75 | },
76 | VERSION: JSON.stringify(require('./package.json').version)
77 | }),
78 | ]
79 | }
80 |
81 | if (process.env.NODE_ENV === 'production') {
82 | // http://vuejs.github.io/vue-loader/workflow/production.html
83 | module.exports.plugins.push(
84 | new webpack.optimize.UglifyJsPlugin({
85 | compress: {
86 | warnings: false
87 | },
88 | })
89 | )
90 | }
--------------------------------------------------------------------------------
/src/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Vue-APlayer Demo
6 |
7 |
42 |
43 |
44 |
45 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### JetBrains template
3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
4 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
5 |
6 | # User-specific stuff:
7 | .idea/
8 | .idea/workspace.xml
9 | .idea/tasks.xml
10 | .idea/dictionaries
11 | .idea/vcs.xml
12 | .idea/jsLibraryMappings.xml
13 |
14 | # Sensitive or high-churn files:
15 | .idea/dataSources.ids
16 | .idea/dataSources.xml
17 | .idea/dataSources.local.xml
18 | .idea/sqlDataSources.xml
19 | .idea/dynamic.xml
20 | .idea/uiDesigner.xml
21 |
22 | # Gradle:
23 | .idea/gradle.xml
24 | .idea/libraries
25 |
26 | # Mongo Explorer plugin:
27 | .idea/mongoSettings.xml
28 |
29 | ## File-based project format:
30 | *.iws
31 |
32 | ## Plugin-specific files:
33 |
34 | # IntelliJ
35 | /out/
36 |
37 | # mpeltonen/sbt-idea plugin
38 | .idea_modules/
39 |
40 | # JIRA plugin
41 | atlassian-ide-plugin.xml
42 |
43 | # Crashlytics plugin (for Android Studio and IntelliJ)
44 | com_crashlytics_export_strings.xml
45 | crashlytics.properties
46 | crashlytics-build.properties
47 | fabric.properties
48 | ### Node template
49 | # Logs
50 | logs
51 | *.log
52 | npm-debug.log*
53 | yarn-debug.log*
54 | yarn-error.log*
55 |
56 | # Runtime data
57 | pids
58 | *.pid
59 | *.seed
60 | *.pid.lock
61 |
62 | # Directory for instrumented libs generated by jscoverage/JSCover
63 | lib-cov
64 |
65 | # Coverage directory used by tools like istanbul
66 | coverage
67 |
68 | # nyc test coverage
69 | .nyc_output
70 |
71 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
72 | .grunt
73 |
74 | # Bower dependency directory (https://bower.io/)
75 | bower_components
76 |
77 | # node-waf configuration
78 | .lock-wscript
79 |
80 | # Compiled binary addons (http://nodejs.org/api/addons.html)
81 | build/Release
82 |
83 | # Dependency directories
84 | node_modules/
85 | jspm_packages/
86 |
87 | # Typescript v1 declaration files
88 | typings/
89 |
90 | # Optional npm cache directory
91 | .npm
92 |
93 | # Optional eslint cache
94 | .eslintcache
95 |
96 | # Optional REPL history
97 | .node_repl_history
98 |
99 | # Output of 'npm pack'
100 | *.tgz
101 |
102 | # Yarn Integrity file
103 | .yarn-integrity
104 |
105 | # dotenv environment variables file
106 | .env
107 |
108 | /dist/
109 | /demo/
110 | package-lock.json
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-aplayer",
3 | "version": "1.6.0",
4 | "description": "Easy-to-use music player for Vue 2.x",
5 | "main": "dist/vue-aplayer.min.js",
6 | "files": [
7 | "src",
8 | "!src/demo/*",
9 | "dist/*.js"
10 | ],
11 | "scripts": {
12 | "start": "yarn run dev",
13 | "dev": "webpack serve --config webpack.demo.config.js",
14 | "build": "export NODE_ENV=production && webpack --progress --hide-modules",
15 | "build:demo": "export NODE_ENV=production && webpack --progress --hide-modules --config webpack.demo.config.js",
16 | "prepublishOnly": "yarn run build",
17 | "predeploy": "yarn add hls.js && yarn run build:demo && echo 'vue-aplayer.js.org' > demo/CNAME",
18 | "lint": "eslint --ext .js,.vue src",
19 | "test": "yarn run lint"
20 | },
21 | "repository": {
22 | "type": "git",
23 | "url": "git+https://github.com/SevenOutman/vue-aplayer.git"
24 | },
25 | "keywords": [
26 | "vue",
27 | "aplayer",
28 | "vue-aplayer",
29 | "music-player",
30 | "html5",
31 | "component",
32 | "vue-compoents"
33 | ],
34 | "author": {
35 | "name": "Doma",
36 | "email": "leishenghao@126.com",
37 | "url": "https://github.com/SevenOutman"
38 | },
39 | "license": "MIT",
40 | "bugs": {
41 | "url": "https://github.com/SevenOutman/vue-aplayer/issues"
42 | },
43 | "homepage": "https://github.com/SevenOutman/vue-aplayer#readme",
44 | "peerDependencies": {
45 | "vue": "^2.5.16"
46 | },
47 | "devDependencies": {
48 | "@babel/core": "^7.15.0",
49 | "@babel/preset-env": "^7.15.0",
50 | "@babel/preset-stage-2": "^7.8.3",
51 | "autoprefixer": "9.6.1",
52 | "babel-eslint": "10.1.0",
53 | "babel-loader": "8.1.0",
54 | "css-loader": "2.1.1",
55 | "cz-conventional-changelog": "2.1.0",
56 | "eslint": "5.16.0",
57 | "eslint-friendly-formatter": "4.0.1",
58 | "eslint-loader": "2.2.1",
59 | "eslint-plugin-vue": "5.2.3",
60 | "file-loader": "3.0.1",
61 | "hls.js": "0.12.4",
62 | "html-webpack-plugin": "3.2.0",
63 | "node-sass": "4.12.0",
64 | "postcss-loader": "3.0.0",
65 | "sass-loader": "7.2.0",
66 | "style-loader": "0.23.1",
67 | "svg-inline-loader": "0.8.0",
68 | "url-loader": "1.1.2",
69 | "vue": "2.6.10",
70 | "vue-html-loader": "1.2.4",
71 | "vue-loader": "^14.2.2",
72 | "vue-template-compiler": "2.6.10",
73 | "webpack": "4.39.2",
74 | "webpack-cli": "^4.8.0",
75 | "webpack-dev-server": "^4.1.0"
76 | },
77 | "browserslist": [
78 | "> 1%",
79 | "last 2 versions",
80 | "not ie <= 8"
81 | ],
82 | "config": {
83 | "commitizen": {
84 | "path": "cz-conventional-changelog"
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/webpack.demo.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var webpack = require('webpack')
3 | var HtmlWebpackPlugin = require('html-webpack-plugin')
4 |
5 | module.exports = {
6 | mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
7 | entry: './src/demo/main.js',
8 | output: {
9 | path: path.resolve(__dirname, 'demo'),
10 | filename: 'demo.js',
11 | },
12 |
13 | module: {
14 | rules: [
15 | {
16 | test: /\.(js|vue)$/,
17 | loader: 'eslint-loader',
18 | enforce: 'pre',
19 | include: [path.resolve(__dirname, 'src')],
20 | options: {
21 | formatter: require('eslint-friendly-formatter'),
22 | emitWarning: true,
23 | },
24 | },
25 | {
26 | test: /\.vue$/,
27 | loader: 'vue-loader',
28 | options: {
29 | loaders: {
30 | js: 'babel-loader?babelrc',
31 | scss: 'style-loader!css-loader!postcss-loader!sass-loader',
32 | },
33 | },
34 | },
35 | {
36 | test: /\.js$/,
37 | loader: 'babel-loader',
38 | exclude: /node_modules/,
39 | },
40 | {
41 | test: /\.(png|jpg)$/,
42 | loader: 'url-loader?limit=40000',
43 | },
44 | {
45 | test: /\.svg$/,
46 | loader: 'svg-inline-loader',
47 | },
48 | {
49 | test: /\.html$/,
50 | loader: 'vue-html-loader',
51 | },
52 | ],
53 | },
54 | devtool: '#eval-source-map',
55 | devServer: {
56 | static: {
57 | directory: path.join(__dirname, 'demo'),
58 | },
59 | compress: true,
60 | port: 3000,
61 | host: '0.0.0.0',
62 | proxy: {
63 | '/aplayer': {
64 | target: 'https://cn-east-17-aplayer-35525609.oss.dogecdn.com/',
65 | secure: false,
66 | changeOrigin: true,
67 | headers: {
68 | host: 'vue-aplayer.js.org',
69 | Referer: 'https://vue-aplayer.js.org/',
70 | },
71 | pathRewrite (path) {
72 | return path.replace(/^\/aplayer/, '')
73 | },
74 | },
75 | },
76 | },
77 | plugins: [
78 | new HtmlWebpackPlugin({
79 | filename: 'index.html',
80 | template: 'src/demo/index.html',
81 | favicon: 'src/demo/favicon.ico',
82 | }),
83 | new webpack.DefinePlugin({
84 | 'process.env': {
85 | NODE_ENV: `"${process.env.NODE_ENV}"`,
86 | },
87 | VERSION: JSON.stringify(require("./package.json").version),
88 | }),
89 | ],
90 | }
91 |
92 | if (process.env.NODE_ENV === 'production') {
93 | module.exports.output.publicPath = '/'
94 | module.exports.devtool = '#source-map'
95 | // http://vuejs.github.io/vue-loader/workflow/production.html
96 | module.exports.plugins.push(
97 | new webpack.optimize.UglifyJsPlugin({
98 | compress: {
99 | warnings: false,
100 | },
101 | }),
102 | )
103 | }
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Parse lrc, suppose multiple time tag
3 | * @see https://github.com/MoePlayer/APlayer/blob/master/src/js/lrc.js#L83
4 | * @author DIYgod(https://github.com/DIYgod)
5 | *
6 | * @param {String} lrc_s - Format:
7 | * [mm:ss]lyric
8 | * [mm:ss.xx]lyric
9 | * [mm:ss.xxx]lyric
10 | * [mm:ss.xx][mm:ss.xx][mm:ss.xx]lyric
11 | * [mm:ss.xx]lyric
12 | *
13 | * @return {String} [[time, text], [time, text], [time, text], ...]
14 | */
15 | export function parseLrc (lrc_s) {
16 | if (lrc_s) {
17 | lrc_s = lrc_s.replace(/([^\]^\n])\[/g, (match, p1) => p1 + '\n[')
18 | const lyric = lrc_s.split('\n')
19 | const lrc = []
20 | const lyricLen = lyric.length
21 | for (let i = 0; i < lyricLen; i++) {
22 | // match lrc time
23 | const lrcTimes = lyric[i].match(/\[(\d{2}):(\d{2})(\.(\d{2,3}))?]/g)
24 | // match lrc text
25 | const lrcText = lyric[i].replace(/.*\[(\d{2}):(\d{2})(\.(\d{2,3}))?]/g, '').replace(/<(\d{2}):(\d{2})(\.(\d{2,3}))?>/g, '').replace(/^\s+|\s+$/g, '')
26 |
27 | if (lrcTimes) {
28 | // handle multiple time tag
29 | const timeLen = lrcTimes.length
30 | for (let j = 0; j < timeLen; j++) {
31 | const oneTime = /\[(\d{2}):(\d{2})(\.(\d{2,3}))?]/.exec(lrcTimes[j])
32 | const min2sec = oneTime[1] * 60
33 | const sec2sec = parseInt(oneTime[2])
34 | const msec2sec = oneTime[4] ? parseInt(oneTime[4]) / ((oneTime[4] + '').length === 2 ? 100 : 1000) : 0
35 | const lrcTime = min2sec + sec2sec + msec2sec
36 | lrc.push([lrcTime, lrcText])
37 | }
38 | }
39 | }
40 | // sort by time
41 | lrc.sort((a, b) => a[0] - b[0])
42 | return lrc
43 | }
44 | else {
45 | return []
46 | }
47 | }
48 |
49 | /**
50 | * Compare two semantic versions(major.minor.patch)
51 | */
52 | export function versionCompare (semantic1, semantic2) {
53 | if (semantic1 === semantic2) {
54 | return 0
55 | }
56 | const [major1, minor1, patch1] = semantic1.split('.').map(Number)
57 | const [major2, minor2, patch2] = semantic2.split('.').map(Number)
58 |
59 | if (major1 > major2) {
60 | return 1
61 | } else if (major1 === major2) {
62 | if (minor1 > minor2) {
63 | return 1
64 | } else if (minor1 === minor2) {
65 | if (patch1 > patch2) {
66 | return 1
67 | }
68 | }
69 | }
70 | return -1
71 | }
72 |
73 | export function warn (message) {
74 | return console.warn(`[Vue-APlayer] ${message}`)
75 | }
76 |
77 | export function deprecatedProp (name, sinceVersion, alternative) {
78 | return warn(`'${name}' is deprecated since v${sinceVersion}, and will be removed in future releases, use '${alternative}' instead`)
79 | }
80 |
81 | export function getElementViewLeft (element) {
82 | let actualLeft = element.offsetLeft
83 | let current = element.offsetParent
84 | let elementScrollLeft
85 | while (current !== null) {
86 | actualLeft += current.offsetLeft
87 | current = current.offsetParent
88 | }
89 | elementScrollLeft = document.body.scrollLeft + document.documentElement.scrollLeft
90 | return actualLeft - elementScrollLeft
91 | }
92 |
93 | export function getElementViewTop (element) {
94 | let actualTop = element.offsetTop
95 | let current = element.offsetParent
96 | let elementScrollTop
97 | while (current !== null) {
98 | actualTop += current.offsetTop
99 | current = current.offsetParent
100 | }
101 | elementScrollTop = document.body.scrollTop + document.documentElement.scrollTop
102 | return actualTop - elementScrollTop
103 | }
104 |
--------------------------------------------------------------------------------
/src/components/aplayer-controller-volume.vue:
--------------------------------------------------------------------------------
1 |
2 |
24 |
25 |
26 |
73 |
74 |
--------------------------------------------------------------------------------
/src/components/aplayer-thumbnail.vue:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
80 |
81 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Vue-APlayer
5 |
6 | ## Please refer to [**Future of vue-aplayer**](https://github.com/SevenOutman/vue-aplayer/discussions/236) before you continue.
7 |
8 | Vue implementation of [APlayer](https://github.com/MoePlayer/APlayer) prototype.
9 | [**Demo**](https://sevenoutman.github.io/vue-aplayer)
10 |
11 |
12 | [](https://travis-ci.org/SevenOutman/vue-aplayer)
13 | [](https://www.npmjs.com/package/vue-aplayer)
14 | [](https://www.npmjs.com/package/vue-aplayer)
15 | [](https://david-dm.org/SevenOutman/vue-aplayer#info=devDependencies)
16 |
17 | [](https://hubble.js.org/#/?owner=SevenOutman&repo=vue-aplayer&start)
18 | [](https://github.com/SevenOutman/vue-aplayer/commits/develop)
19 | [](https://github.com/SevenOutman/vue-aplayer/commits/develop)
20 | [](https://github.com/SevenOutman/vue-aplayer/network/dependents?dependent_type=REPOSITORY)
21 | [](https://discord.gg/e3SeMJE)
22 |
23 | 
24 |
25 |
26 | ### Features
27 | - Beautiful clean UI
28 | - Lyrics scroll
29 | - Playlist with repeat & shuffle controls
30 | - Custom theme color / Self-adapting theme color
31 | - Drag and place anywhere
32 | - Mutex play
33 | - HLS support
34 | - **Easy props and API**
35 | - **Dependency free** and light-weight (gzipped 16KB)
36 |
37 | Using Vue-APlayer in your project? [Let me know!](https://github.com/SevenOutman/vue-aplayer/issues/26)
38 |
39 |
40 | ## Usage
41 |
42 | ```HTML
43 |
51 | ```
52 | [**Full documentation**](https://github.com/SevenOutman/vue-aplayer/blob/develop/docs/README.md)
53 |
54 | [**中文文档**](https://github.com/SevenOutman/vue-aplayer/blob/develop/docs/README.zh-CN.md)
55 |
56 |
57 | ## Changelog
58 |
59 | Detailed changes fro each release are documented in the [release notes](https://github.com/SevenOutman/vue-aplayer/releases).
60 |
61 |
62 | ## Contribution
63 |
64 | Feel free to [open an issue](https://github.com/SevenOutman/vue-aplayer/issues) if you find a bug or have a nice idea.
65 |
66 | [PRs are welcome](https://github.com/SevenOutman/vue-aplayer/blob/master/docs/README.md#contribute).
67 |
68 |
69 | ## The name
70 |
71 | - When referring to `Vue-APlayer`, the name should be written in exactly the same case.
72 | - When referring to its versions, either `Vue-APlayer@1.x` (GitHub) or `vue-aplayer@1.x` (npm) is fine.
73 |
74 |
75 | ## Related projects
76 |
77 | - [APlayer](https://github.com/MoePlayer/APlayer): Prior art
78 | - [@moefe/vue-aplayer](https://github.com/MoePlayer/vue-aplayer): Another Vue implementation of APlayer by [@u3u](https://github.com/u3u)
79 |
80 |
81 | ## Thanks
82 |
83 | [@DIYgod](https://github.com/DIYgod), for creating APlayer and sharing cloud storage for hosting Vue-APlayer's demo page media resources.
84 |
85 |
86 | ## License
87 |
88 | Vue-APlayer is [MIT Licensed](https://github.com/SevenOutman/vue-aplayer/blob/master/LICENSE).
89 |
90 | Copyright (c) 2016-present Shenghao "Doma" Lei
91 |
92 |
--------------------------------------------------------------------------------
/src/components/aplayer-list.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
13 | -
19 |
20 | {{ index + 1}}
21 | {{ aMusic.title || 'Untitled' }}
22 | {{ aMusic.artist || 'Unknown' }}
23 |
24 |
25 |
26 |
27 |
28 |
29 |
60 |
61 |
--------------------------------------------------------------------------------
/src/components/aplayer-controller.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
$emit('dragbegin', val)"
8 | @dragend="val => $emit('dragend', val)"
9 | @dragging="val => $emit('dragging', val)"
10 | />
11 |
12 |
13 | - {{secondToTime(stat.playedTime)}} / {{secondToTime(stat.duration)}}
15 |
16 |
$emit('setvolume', v)"
23 | />
24 |
30 |
36 |
42 |
43 |
44 |
45 |
46 |
86 |
87 |
--------------------------------------------------------------------------------
/docs/README.zh-CN.md:
--------------------------------------------------------------------------------
1 | ## 安装
2 |
3 | ### Node
4 |
5 | ```
6 | $ yarn add vue-aplayer
7 | ```
8 |
9 | 或者如果你选择 `npm`
10 |
11 | ```
12 | $ npm i vue-aplayer
13 | ```
14 |
15 | ### CDN
16 |
17 | ```html
18 |
19 |
22 | ```
23 |
24 |
25 | ## 运行时要求
26 |
27 | - [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
28 | - [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
29 |
30 |
31 |
32 | ## 使用
33 |
34 | ```HTML
35 |
43 | ```
44 |
45 | ```JS
46 | // ES6
47 | import Aplayer from 'vue-aplayer'
48 |
49 | new Vue({
50 | components: {
51 | Aplayer
52 | }
53 | })
54 | ```
55 |
56 |
57 |
58 | ### Props
59 |
60 | | 名称 | 类型 | 默认值 | 说明 |
61 | | ---- | ---- | ------- | ----------- |
62 | | music| Object | *必需* | 当前播放的音乐。 具体请看[音乐信息](https://github.com/SevenOutman/vue-aplayer/blob/develop/docs/README.zh-CN.md#音乐信息) |
63 | | list | Array | `[]` | 播放列表。如果 list 不是空数组,播放列表就会显示出来,即使 list 中只有一首歌并且它和 music 一样 |
64 | | mini | Boolean | `false` | 迷你模式 |
65 | | float | Boolean | `false` | 浮动模式。你可以在页面上随意拖放你的播放器 |
66 | | showLrc | Boolean | `false` | 是否显示歌词 |
67 | | mutex | Boolean | `true` | 是否在该播放器播放时暂停其他播放器 |
68 | | theme | String | `'#41b883'` | 主题色。如果当前歌曲也设置了 `theme` 则以歌曲的为准 |
69 | | shuffle | Boolean | `false` | 随机播放 |
70 | | repeat | String | `'no-repeat'` | 轮播模式。值可以是 `'repeat-one'`(单曲循环)`'repeat-all'`(列表循环)或者 `'no-repeat'`(不循环)。为了好记,还可以使用对应的 `'music'` `'list'` `'none'` |
71 | | listMaxHeight | String | *none* | 播放列表面板最大高度 |
72 | | listFolded | Boolean | `false` | 默认收起播放列表 |
73 | | narrow | | | DEPRECATED, 请使用 `mini` |
74 | | listmaxheight | | | DEPRECATED, 请使用 `listMaxHeight` |
75 | | showlrc | | | DEPRECATED, 请使用 `showLrc` |
76 |
77 | > 如果你是用的是 Vue@2.3.0+, 你可以在 `music` `shuffle` 和 `repeat` 上使用 [`.sync` 修饰符](https://cn.vuejs.org/v2/guide/components.html#sync-%E4%BF%AE%E9%A5%B0%E7%AC%A6)。
78 |
79 |
80 |
81 | ### 将 Audio 属性作为 props
82 |
83 | 从 `v1.4.0` 开始,我们选取了一些 `