diff --git a/README.md b/README.md
index fb9a6c0ab..b6fd71047 100644
--- a/README.md
+++ b/README.md
@@ -29,15 +29,15 @@
## Ecosystem
-| Project | Description | Demo |
-| --------------------------------------------------------------------------------------------------------------------- | ------------------------------ | ------------------------------------------- |
-| [artplayer-plugin-danmu](https://github.com/zhw2590582/ArtPlayer/tree/master/packages/artplayer-plugin-danmu) | Danmu plugin for ArtPlayer | `WIP` |
-| [artplayer-plugin-flv](https://github.com/zhw2590582/ArtPlayer/tree/master/packages/artplayer-plugin-flv) | Flv plugin for ArtPlayer | `WIP` |
-| [artplayer-plugin-gif](https://github.com/zhw2590582/ArtPlayer/tree/master/packages/artplayer-plugin-gif) | Gif plugin for ArtPlayer | [demo](https://artplayer.org/gif/) |
-| [artplayer-plugin-backlight](https://github.com/zhw2590582/ArtPlayer/tree/master/packages/artplayer-plugin-backlight) | Backlight plugin for ArtPlayer | [demo](https://artplayer.org/backlight/) |
-| [artplayer-tool-thumbnail](https://github.com/zhw2590582/ArtPlayer/tree/master/packages/artplayer-tool-thumbnail) | Thumbnail tool for ArtPlayer | [demo](https://artplayer.org/thumbnail/) |
-| [artplayer-react](https://github.com/zhw2590582/ArtPlayer/tree/master/packages/artplayer-react) | React Component for Artplayer | [demo](https://codesandbox.io/s/n74859y9rl) |
-| [artplayer-vue](https://github.com/zhw2590582/ArtPlayer/tree/master/packages/artplayer-vue) | Vue Component for Artplayer | [demo](https://codesandbox.io/s/6z76lm109n) |
+| Project | Description | Demo |
+| --------------------------------------------------------------------------------------------------------------------- | ------------------------------ | ---------------------------------------------------------------------------------------------------- |
+| [artplayer-plugin-danmu](https://github.com/zhw2590582/ArtPlayer/tree/master/packages/artplayer-plugin-danmu) | Danmu plugin for ArtPlayer | `WIP` |
+| [artplayer-plugin-flv](https://github.com/zhw2590582/ArtPlayer/tree/master/packages/artplayer-plugin-flv) | Flv plugin for ArtPlayer | `WIP` |
+| [artplayer-plugin-gif](https://github.com/zhw2590582/ArtPlayer/tree/master/packages/artplayer-plugin-gif) | Gif plugin for ArtPlayer | [demo](https://artplayer.org/?libs=.%2Funcompiled%2Fartplayer-plugin-gif.js&example=gif) |
+| [artplayer-plugin-backlight](https://github.com/zhw2590582/ArtPlayer/tree/master/packages/artplayer-plugin-backlight) | Backlight plugin for ArtPlayer | [demo](https://artplayer.org/?libs=.%2Funcompiled%2Fartplayer-plugin-backlight.js&example=backlight) |
+| [artplayer-tool-thumbnail](https://github.com/zhw2590582/ArtPlayer/tree/master/packages/artplayer-tool-thumbnail) | Thumbnail tool for ArtPlayer | [demo](https://artplayer.org/?libs=.%2Funcompiled%2Fartplayer-plugin-thumbnail.js&example=thumbnail) |
+| [artplayer-react](https://github.com/zhw2590582/ArtPlayer/tree/master/packages/artplayer-react) | React Component for Artplayer | [demo](https://codesandbox.io/s/n74859y9rl) |
+| [artplayer-vue](https://github.com/zhw2590582/ArtPlayer/tree/master/packages/artplayer-vue) | Vue Component for Artplayer | [demo](https://codesandbox.io/s/6z76lm109n) |
## Demo
diff --git a/docs/assets/css/dracula.css b/docs/assets/css/dracula.css
new file mode 100644
index 000000000..c1ed556e2
--- /dev/null
+++ b/docs/assets/css/dracula.css
@@ -0,0 +1,41 @@
+/*
+
+ Name: dracula
+ Author: Michael Kaminsky (http://github.com/mkaminsky11)
+
+ Original dracula color scheme by Zeno Rocha (https://github.com/zenorocha/dracula-theme)
+
+*/
+
+
+.cm-s-dracula.CodeMirror, .cm-s-dracula .CodeMirror-gutters {
+ background-color: #282a36 !important;
+ color: #f8f8f2 !important;
+ border: none;
+ }
+ .cm-s-dracula .CodeMirror-gutters { color: #282a36; }
+ .cm-s-dracula .CodeMirror-cursor { border-left: solid thin #f8f8f0; }
+ .cm-s-dracula .CodeMirror-linenumber { color: #6D8A88; }
+ .cm-s-dracula .CodeMirror-selected { background: rgba(255, 255, 255, 0.10); }
+ .cm-s-dracula .CodeMirror-line::selection, .cm-s-dracula .CodeMirror-line > span::selection, .cm-s-dracula .CodeMirror-line > span > span::selection { background: rgba(255, 255, 255, 0.10); }
+ .cm-s-dracula .CodeMirror-line::-moz-selection, .cm-s-dracula .CodeMirror-line > span::-moz-selection, .cm-s-dracula .CodeMirror-line > span > span::-moz-selection { background: rgba(255, 255, 255, 0.10); }
+ .cm-s-dracula span.cm-comment { color: #6272a4; }
+ .cm-s-dracula span.cm-string, .cm-s-dracula span.cm-string-2 { color: #f1fa8c; }
+ .cm-s-dracula span.cm-number { color: #bd93f9; }
+ .cm-s-dracula span.cm-variable { color: #50fa7b; }
+ .cm-s-dracula span.cm-variable-2 { color: white; }
+ .cm-s-dracula span.cm-def { color: #50fa7b; }
+ .cm-s-dracula span.cm-operator { color: #ff79c6; }
+ .cm-s-dracula span.cm-keyword { color: #ff79c6; }
+ .cm-s-dracula span.cm-atom { color: #bd93f9; }
+ .cm-s-dracula span.cm-meta { color: #f8f8f2; }
+ .cm-s-dracula span.cm-tag { color: #ff79c6; }
+ .cm-s-dracula span.cm-attribute { color: #50fa7b; }
+ .cm-s-dracula span.cm-qualifier { color: #50fa7b; }
+ .cm-s-dracula span.cm-property { color: #66d9ef; }
+ .cm-s-dracula span.cm-builtin { color: #50fa7b; }
+ .cm-s-dracula span.cm-variable-3, .cm-s-dracula span.cm-type { color: #ffb86c; }
+
+ .cm-s-dracula .CodeMirror-activeline-background { background: rgba(255,255,255,0.1); }
+ .cm-s-dracula .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }
+
\ No newline at end of file
diff --git a/docs/assets/css/style.css b/docs/assets/css/style.css
new file mode 100644
index 000000000..2a3204664
--- /dev/null
+++ b/docs/assets/css/style.css
@@ -0,0 +1,137 @@
+body,
+html {
+ height: 100%;
+}
+
+body {
+ font-family: Hiragino Sans GB, Microsoft YaHei, \5fae\8f6f\96c5\9ed1, tahoma, arial, simsun, \5b8b\4f53;
+ -webkit-text-size-adjust: 100% !important;
+ -moz-text-size-adjust: 100% !important;
+ -ms-text-size-adjust: 100% !important;
+ text-size-adjust: 100% !important;
+ font-size: 14px;
+ margin: 0;
+ padding: 0;
+ background: rgb(16, 17, 19);
+}
+
+*,
+:after,
+:before {
+ box-sizing: border-box;
+}
+
+a {
+ color: #ccc;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #fff;
+}
+
+img {
+ max-width: 100%;
+ vertical-align: top;
+}
+
+.header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ font-size: 13px;
+ height: 48px;
+ width: 100%;
+ padding: 0 0 0 20px;
+ border-bottom: 1px solid rgb(17, 21, 24);
+ background-color: rgb(28, 32, 34);
+}
+
+.header .menus {
+ flex: 1;
+}
+
+.header .menus a {
+ margin-left: 30px;
+}
+
+.header .run {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 100px;
+ height: 100%;
+ cursor: pointer;
+ color: #f1fa8c;
+ border-left: 1px solid rgb(17, 21, 24);
+ background-color: rgb(39, 41, 54);
+}
+
+.main {
+ display: flex;
+ flex: 1;
+ height: 100%;
+}
+
+.main .part-left {
+ display: flex;
+ flex-direction: column;
+ width: 40%;
+ border-right: 1px solid rgb(17, 21, 24);
+}
+
+.main .part-left .libs {
+ height: 50px;
+}
+
+.main .part-left .libsInput {
+ height: 100%;
+ width: 100%;
+ padding: 5px 10px;
+ outline: none;
+ resize: none;
+ border: none;
+ font-size: 13px;
+ color: #ccc;
+ border-bottom: 1px solid rgb(17, 21, 24);
+ background-color: rgb(28, 32, 34);
+}
+
+.main .part-left .code {
+ flex: 1;
+ overflow: auto;
+}
+
+.main .part-left .code .codeMirrorWrap {
+ height: 100%;
+ overflow-x: hidden;
+}
+
+.CodeMirror {
+ height: 100%;
+ width: calc(100% + 30px);
+ padding: 10px 30px 10px 0;
+}
+
+.main .part-right {
+ flex: 1;
+}
+
+.part-right .video-wrap {
+ display: flex;
+ height: 70%;
+ align-items: center;
+ justify-content: center;
+ border-bottom: 1px solid rgb(17, 21, 24);
+}
+
+.part-right .video-wrap .artplayer-app {
+ width: 90%;
+ height: 60%;
+ border: 1px solid rgba(255, 255, 255, 0.05);
+}
+
+.part-right .console {
+ position: relative;
+ height: 30%;
+}
diff --git a/docs/assets/example/backlight.js b/docs/assets/example/backlight.js
new file mode 100644
index 000000000..fd70eb556
--- /dev/null
+++ b/docs/assets/example/backlight.js
@@ -0,0 +1,9 @@
+var art = new Artplayer({
+ container: '.artplayer-app',
+ url: 'https://zhw2590582.github.io/assets-cdn/video/ambilight.mp4',
+ autoSize: true,
+ moreVideoAttr: {
+ crossOrigin: 'anonymous',
+ },
+ plugins: [artplayerPluginBacklight],
+});
\ No newline at end of file
diff --git a/docs/assets/example/gif.js b/docs/assets/example/gif.js
new file mode 100644
index 000000000..4daab77c7
--- /dev/null
+++ b/docs/assets/example/gif.js
@@ -0,0 +1 @@
+console.log('gif');
\ No newline at end of file
diff --git a/docs/assets/example/index.js b/docs/assets/example/index.js
new file mode 100644
index 000000000..41777d9e9
--- /dev/null
+++ b/docs/assets/example/index.js
@@ -0,0 +1,110 @@
+var url = 'https://zhw2590582.github.io/assets-cdn';
+var art = new Artplayer({
+ container: '.artplayer-app',
+ url: url + '/video/one-more-time-one-more-chance-480p.mp4',
+ title: '【新海诚动画】『秒速5センチメートル』',
+ poster: url + '/image/one-more-time-one-more-chance-poster.jpg',
+ volume: 0.5,
+ muted: false,
+ autoplay: false,
+ pip: true,
+ autoSize: true,
+ screenshot: true,
+ setting: true,
+ loop: true,
+ playbackRate: true,
+ aspectRatio: true,
+ fullscreen: true,
+ fullscreenWeb: true,
+ mutex: true,
+ theme: '#ffad00',
+ lang: 'zh-cn',
+ moreVideoAttr: {
+ crossOrigin: 'anonymous',
+ },
+ contextmenu: [
+ {
+ html: '自定义菜单 - 天亮请关灯 Σ(っ °Д °;)っ',
+ click: function() {
+ console.info('自定义菜单 - 天亮请关灯 Σ(っ °Д °;)っ');
+ this.hide();
+ },
+ },
+ ],
+ layers: [
+ {
+ html: `
`,
+ click: function() {
+ art.destroy(true);
+ art = new Artplayer({
+ autoplay: true,
+ container: '.artplayer-app',
+ url: url + '/video/you-name.mp4',
+ });
+ },
+ style: {
+ position: 'absolute',
+ top: '20px',
+ right: '20px',
+ opacity: '.9',
+ },
+ },
+ ],
+ quality: [
+ {
+ default: true,
+ name: '标清 480P',
+ url: url + '/video/one-more-time-one-more-chance-480p.mp4',
+ },
+ {
+ name: '高清 720P',
+ url: url + '/video/one-more-time-one-more-chance-720p.mp4',
+ },
+ ],
+ thumbnails: {
+ url: url + '/image/one-more-time-one-more-chance-thumbnails.png',
+ width: 190,
+ height: 107,
+ },
+ subtitle: {
+ url: url + '/subtitle/one-more-time-one-more-chance.srt',
+ style: {
+ color: '#03A9F4',
+ },
+ },
+ highlight: [
+ {
+ time: 60,
+ text: 'One more chance',
+ },
+ {
+ time: 120,
+ text: '谁でもいいはずなのに',
+ },
+ {
+ time: 180,
+ text: '夏の想い出がまわる',
+ },
+ {
+ time: 240,
+ text: 'こんなとこにあるはずもないのに',
+ },
+ {
+ time: 300,
+ text: '--终わり--',
+ },
+ ],
+ controls: [
+ {
+ name: 'preview',
+ position: 'right',
+ html: '打开',
+ mounted: $preview => {
+ art.plugins.localPreview.attach($preview);
+ },
+ },
+ ],
+ icons: {
+ loading: '
',
+ },
+});
\ No newline at end of file
diff --git a/docs/assets/example/thumbnail.js b/docs/assets/example/thumbnail.js
new file mode 100644
index 000000000..ff01395e0
--- /dev/null
+++ b/docs/assets/example/thumbnail.js
@@ -0,0 +1 @@
+console.log('thumbnail');
\ No newline at end of file
diff --git a/docs/assets/img/ploading.gif b/docs/assets/img/ploading.gif
new file mode 100644
index 000000000..1a8c97d04
Binary files /dev/null and b/docs/assets/img/ploading.gif differ
diff --git a/docs/assets/js/common.js b/docs/assets/js/common.js
new file mode 100644
index 000000000..b5f30d5b4
--- /dev/null
+++ b/docs/assets/js/common.js
@@ -0,0 +1,176 @@
+(function() {
+ var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
+ if (isMobile) {
+ window.location.href = './mobile.html';
+ return;
+ }
+
+ var $codeMirror = document.querySelector('.codeMirrorWrap');
+ var $lib = document.querySelector('.libsInput');
+ var $run = document.querySelector('.run');
+ var loaddLib = [];
+
+ consola.creat({
+ target: '.console',
+ size: '100%',
+ zIndex: 99,
+ });
+
+ var mirror = CodeMirror($codeMirror, {
+ lineNumbers: true,
+ mode: 'javascript',
+ matchBrackets: true,
+ styleActiveLine: true,
+ theme: 'dracula',
+ value: '',
+ });
+
+ function initArt(art) {
+ Artplayer.config.video.events.forEach(function(item) {
+ art.on('video:' + item, function(event) {
+ console.log('video: ' + event.type);
+ });
+ });
+ }
+
+ function getURLParameters(url) {
+ return (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce(function(a, v) {
+ return (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a;
+ }, {});
+ }
+
+ function getExt(url) {
+ if (url.includes('?')) {
+ return getExt(url.split('?')[0]);
+ }
+
+ if (url.includes('#')) {
+ return getExt(url.split('#')[0]);
+ }
+
+ return url
+ .trim()
+ .toLowerCase()
+ .split('.')
+ .pop();
+ }
+
+ function loadScript(url) {
+ return new Promise(function(resolve, reject) {
+ var script = document.createElement('script');
+ script.type = 'text/javascript';
+ script.src = url;
+ script.onload = function() {
+ resolve(url);
+ };
+ script.onerror = function() {
+ reject(new Error('Loading script failed:' + url));
+ };
+ document.querySelector('head').appendChild(script);
+ });
+ }
+
+ function loadStyle(url) {
+ return new Promise(function(resolve, reject) {
+ var link = document.createElement('link');
+ link.rel = 'stylesheet';
+ link.href = url;
+ link.onload = function() {
+ resolve(url);
+ };
+ link.onerror = function() {
+ reject(new Error('Loading style failed:' + url));
+ };
+ document.querySelector('head').appendChild(link);
+ });
+ }
+
+ function loadLib(libs) {
+ var libPromise = [];
+ var libsDecode = decodeURIComponent(libs || '');
+ libsDecode
+ .split(/\r?\n/)
+ .filter(function(url) {
+ return !loaddLib.includes(url);
+ })
+ .forEach(function(url) {
+ var ext = getExt(url);
+ if (ext === 'js') {
+ libPromise.push(loadScript(url));
+ } else if (ext === 'css') {
+ libPromise.push(loadStyle(url));
+ }
+ });
+ $lib.value = libsDecode;
+ return Promise.all(libPromise);
+ }
+
+ function runExample(name) {
+ fetch(`./assets/example/${name}.js`)
+ .then(function(response) {
+ return response.text();
+ })
+ .then(function(text) {
+ mirror.setValue(text);
+ runCode();
+ })
+ .catch(function(err) {
+ console.error(err.message);
+ });
+ }
+
+ function loadCode(code, example) {
+ if (example) {
+ runExample(example);
+ } else if (code) {
+ mirror.setValue(decodeURIComponent(code).trim());
+ runCode();
+ } else {
+ runExample('index');
+ }
+ }
+
+ function runCode() {
+ Artplayer.instances.forEach(function(art) {
+ art.destroy(true);
+ });
+ var code = mirror.getValue();
+ eval(code);
+ initArt(Artplayer.instances[0]);
+ console.info('Player initialization completed');
+ }
+
+ function initApp() {
+ var _getURLParameters = getURLParameters(window.location.href),
+ code = _getURLParameters.code,
+ libs = _getURLParameters.libs;
+ example = _getURLParameters.example;
+
+ loadLib(libs)
+ .then(function(result) {
+ loaddLib = loaddLib.concat(result);
+ loadCode(code, example);
+ })
+ .catch(function(err) {
+ console.error(err.message);
+ });
+ }
+
+ window.addEventListener('error', function(err) {
+ console.error(err.message);
+ });
+
+ window.addEventListener('unhandledrejection', function(err) {
+ console.error(err.message);
+ });
+
+ $run.addEventListener('click', function(e) {
+ var libs = encodeURIComponent($lib.value);
+ var code = encodeURIComponent(mirror.getValue());
+ var url = window.location.origin + window.location.pathname + '?libs=' + libs + '&code=' + code;
+ history.pushState(null, null, url);
+ initApp();
+ });
+
+ initApp();
+})();
diff --git a/docs/index.html b/docs/index.html
index d0bbb4f38..620aefec8 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -1,14 +1,51 @@
-