mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-25 08:01:20 -08:00
完成gif插件
This commit is contained in:
1 parent
d535423dd8
commit
c9dfc883ab
11 files changed
+352
-54
No files matched your search
@@ -1,3 +1,63 @@
|
||||
# artplayer-plugin-gif
|
||||
Gif plugin for ArtPlayer
|
||||
|
||||
Gif plugin for ArtPlayer, use [gifshot](https://github.com/yahoo/gifshot) as a dependency
|
||||
|
||||
## Demo
|
||||
|
||||
[Checkout the demo](https://artplayer.org/gif/) from Github Pages
|
||||
|
||||
## Install
|
||||
|
||||
Install with `npm`
|
||||
|
||||
```
|
||||
$ npm install artplayer-plugin-gif
|
||||
```
|
||||
|
||||
Or install with `yarn`
|
||||
|
||||
```
|
||||
$ yarn add artplayer-plugin-gif
|
||||
```
|
||||
|
||||
```js
|
||||
import artplayerPluginGif from 'artplayer-plugin-gif';
|
||||
```
|
||||
|
||||
Or umd builds are also available
|
||||
|
||||
```html
|
||||
<script src="artplayer-plugin-gif"></script>
|
||||
```
|
||||
|
||||
Will expose the global variable to `window.artplayerPluginGif`.
|
||||
|
||||
## Usage
|
||||
|
||||
This will add a button called "GIF" in the bottom control bar.
|
||||
|
||||
```js
|
||||
var art = new Artplayer({
|
||||
container: '.artplayer-app',
|
||||
url: 'path/to/video.mp4',
|
||||
plugins: [artplayerPluginGif],
|
||||
});
|
||||
```
|
||||
|
||||
Or can be called via api
|
||||
|
||||
```js
|
||||
art.plugins.artplayerPluginGif.create(
|
||||
{
|
||||
// some configuration
|
||||
// https://github.com/yahoo/gifshot#options
|
||||
},
|
||||
function(imageUrl) {
|
||||
console.log(imageUrl);
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Harvey Zack](https://www.zhw-island.com/)
|
||||
@@ -1,22 +1,140 @@
|
||||
import gifshot from 'gifshot';
|
||||
|
||||
function i18nMix(i18n) {
|
||||
i18n.update({
|
||||
'zh-cn': {
|
||||
'Long press, gif length is between 1 second and 5 seconds': '长按,gif 长度为 1 ~ 5 秒',
|
||||
'Gif time is too short': 'Gif 时间太短',
|
||||
'Start creating gif, please wait': '开始创建 gif,请稍等',
|
||||
'Create gif successfully': '创建 gif 成功',
|
||||
'There is another gif in the processing': '正有另一个 gif 在创建中',
|
||||
},
|
||||
'zh-tw': {
|
||||
'Long press, gif length is between 1 second and 5 seconds': '長按,gif 長度為 1 ~ 5 秒',
|
||||
'Gif time is too short': 'Gif 時間太短',
|
||||
'Start creating gif, please wait': '開始創建 gif,請稍等',
|
||||
'Create gif successfully': '創建 gif 成功',
|
||||
'There is another gif in the processing': '正有另一個 gif 在創建中',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function artplayerPluginGif(art) {
|
||||
const { errorHandle, clamp, downloadImage } = art.constructor.utils;
|
||||
const {
|
||||
i18n,
|
||||
notice,
|
||||
layers,
|
||||
controls,
|
||||
player,
|
||||
option: { theme, title },
|
||||
events: { proxy },
|
||||
template: { $video },
|
||||
} = art;
|
||||
|
||||
i18nMix(i18n);
|
||||
|
||||
layers.add({
|
||||
name: 'artplayer-plugin-gif-progress',
|
||||
html: '<div class="artplayer-plugin-gif-progress"></div>',
|
||||
style: {
|
||||
position: 'absolute',
|
||||
top: '0',
|
||||
left: '0',
|
||||
height: '3px',
|
||||
width: '0%',
|
||||
'background-color': theme,
|
||||
},
|
||||
});
|
||||
|
||||
const $progress = layers['artplayer-plugin-gif-progress'].$ref;
|
||||
let isProcessing = false;
|
||||
let pressStartTime = 0;
|
||||
let progressTimer = null;
|
||||
|
||||
function cleanTimer() {
|
||||
$progress.style.width = '0%';
|
||||
clearTimeout(progressTimer);
|
||||
progressTimer = null;
|
||||
}
|
||||
|
||||
function createGif() {
|
||||
cleanTimer();
|
||||
const pressTime = new Date() - pressStartTime;
|
||||
|
||||
if (isProcessing) {
|
||||
notice.show(i18n.get('There is another gif in the processing'));
|
||||
} else if (pressTime < 1000) {
|
||||
notice.show(i18n.get('Gif time is too short'));
|
||||
} else {
|
||||
const numFrames = Math.floor(clamp(pressTime, 1000, 5000) / 100);
|
||||
const { videoWidth, videoHeight } = $video;
|
||||
art.plugins.artplayerPluginGif.create(
|
||||
{
|
||||
numFrames,
|
||||
gifHeight: 200,
|
||||
gifWidth: (videoWidth / videoHeight) * 200,
|
||||
},
|
||||
image => {
|
||||
downloadImage(image, `${title || 'unnamed'}.gif`);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
controls.add({
|
||||
name: 'artplayer-plugin-gif',
|
||||
position: 'right',
|
||||
html: 'GIF',
|
||||
mounted: $gif => {
|
||||
proxy($gif, 'mousedown', () => {
|
||||
cleanTimer();
|
||||
pressStartTime = new Date();
|
||||
notice.show(i18n.get('Long press, gif length is between 1 second and 5 seconds'));
|
||||
|
||||
(function loop() {
|
||||
progressTimer = setTimeout(() => {
|
||||
const width = parseInt($progress.style.width, 10);
|
||||
if (width <= 100) {
|
||||
$progress.style.width = `${width + 1}%`;
|
||||
loop();
|
||||
} else {
|
||||
createGif();
|
||||
}
|
||||
}, 50);
|
||||
})();
|
||||
});
|
||||
|
||||
proxy($gif, 'mouseup', () => {
|
||||
createGif();
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
name: 'artplayerPluginGif',
|
||||
isProcessing,
|
||||
create(config = {}, callback) {
|
||||
isProcessing = true;
|
||||
art.emit('artplayerPluginGif:create:start');
|
||||
notice.show(`${i18n.get('Start creating gif, please wait')}: ${config.numFrames / 10 || 1} s`, false, 5000);
|
||||
gifshot.createGIF(
|
||||
{
|
||||
...config,
|
||||
video: [art.template.$video.src],
|
||||
offset: player.currentTime,
|
||||
video: [$video.src],
|
||||
},
|
||||
obj => {
|
||||
if (!obj.error) {
|
||||
if (callback) {
|
||||
callback(obj.image);
|
||||
}
|
||||
} else {
|
||||
console.log(obj.error);
|
||||
if (obj.error) {
|
||||
notice.show(obj.errorMsg);
|
||||
errorHandle(false, obj.errorMsg);
|
||||
} else if (typeof callback === 'function') {
|
||||
callback(obj.image);
|
||||
notice.show(i18n.get('Create gif successfully'));
|
||||
}
|
||||
|
||||
isProcessing = false;
|
||||
art.emit('artplayerPluginGif:create:end');
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { setStyle, secondToTime } from '../utils';
|
||||
import { secondToTime, downloadImage } from '../utils';
|
||||
|
||||
export default function screenshotMix(art, player) {
|
||||
const {
|
||||
@@ -13,13 +13,7 @@ export default function screenshotMix(art, player) {
|
||||
canvas.height = $video.videoHeight;
|
||||
canvas.getContext('2d').drawImage($video, 0, 0);
|
||||
const dataUri = canvas.toDataURL('image/png');
|
||||
const elink = document.createElement('a');
|
||||
setStyle(elink, 'display', 'none');
|
||||
elink.href = dataUri;
|
||||
elink.download = `${option.title || 'artplayer'}_${secondToTime($video.currentTime)}.png`;
|
||||
document.body.appendChild(elink);
|
||||
elink.click();
|
||||
document.body.removeChild(elink);
|
||||
downloadImage(dataUri, `${option.title || 'artplayer'}_${secondToTime($video.currentTime)}.png`);
|
||||
return dataUri;
|
||||
}
|
||||
|
||||
|
||||
@@ -136,7 +136,9 @@
|
||||
opacity: .9;
|
||||
font-size: 12px;
|
||||
height: 36px;
|
||||
min-width: 36px;
|
||||
line-height: 36px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
.art-icon {
|
||||
display: flex;
|
||||
|
||||
@@ -170,3 +170,13 @@ export function vttToBlob(vttText) {
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export function downloadImage(url, name) {
|
||||
const elink = document.createElement('a');
|
||||
setStyle(elink, 'display', 'none');
|
||||
elink.href = url;
|
||||
elink.download = name;
|
||||
document.body.appendChild(elink);
|
||||
elink.click();
|
||||
document.body.removeChild(elink);
|
||||
}
|
||||
Reference in new issue
Block a user