diff --git a/docs/thumbnail/js/common.js b/docs/thumbnail/js/common.js index f7c3862b4..278a74728 100644 --- a/docs/thumbnail/js/common.js +++ b/docs/thumbnail/js/common.js @@ -1,4 +1,5 @@ (function() { + var $img = document.querySelector('.img'); var $upload = document.querySelector('.upload'); var $file = document.querySelector('.file'); var $artplayer = document.querySelector('.artplayer'); @@ -16,34 +17,28 @@ $artplayer.style.display = 'block'; restartArtplayer(); }, - callbackThumbnailUrl: function (url) { - console.log(url); - } + callbackThumbnailUrl: function(url) { + $img.style.backgroundImage = `url(${url})`; + }, + callbackDone: function(videoUrl, thumbnailUrl) { + restartArtplayer(); + }, }); function restartArtplayer() { - var number = Number($number.value); - var width = Number($width.value); - var height = Number($height.value); - var column = Number($column.value); - Artplayer.instances.forEach(function(art) { art.destroy(true); }); var option = { container: $artplayer, - url: thumbnail.videoUrl + url: thumbnail.videoUrl, }; if (thumbnail.thumbnailUrl) { option.thumbnails = { url: thumbnail.thumbnailUrl, - number: number, - width: width, - height: height, - column: column, - } + }; } var art = new Artplayer(option); @@ -52,13 +47,13 @@ var $video = art.template.$video; $aspectRatio.textContent = $video.videoWidth + ' x ' + $video.videoHeight; $duration.textContent = $video.duration + 's'; - thumbnail.setup({ + thumbnail.mergeOption({ videoElement: $video, - number: number, - width: width, - height: height, - column: column, }); + + if (!thumbnail.thumbnailUrl) { + thumbnail.getThumbnailUrl(); + } }); } })(); diff --git a/docs/uncompiled/artplayer-tool-thumbnail.js b/docs/uncompiled/artplayer-tool-thumbnail.js index 94ced53bf..804449e3f 100644 --- a/docs/uncompiled/artplayer-tool-thumbnail.js +++ b/docs/uncompiled/artplayer-tool-thumbnail.js @@ -74,6 +74,18 @@ } } + function runPromisesInSeries(ps) { + return ps.reduce(function (p, next) { + return p.then(next); + }, Promise.resolve()); + } + + function sleep(ms) { + return new Promise(function (resolve) { + return setTimeout(resolve, ms); + }); + } + var ArtplayerToolThumbnail = /*#__PURE__*/ function () { @@ -96,13 +108,20 @@ errorHandle(typeof option.callbackThumbnailUrl === 'function', 'This callbackThumbnailUrl is not a function'); } - this.option = option; - this.init(); + this.option = objectSpread({}, ArtplayerToolThumbnail.DEFAULTS, option); + this.getVideoUrl(); } createClass(ArtplayerToolThumbnail, [{ - key: "init", - value: function init() { + key: "mergeOption", + value: function mergeOption() { + var option = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + this.option = objectSpread({}, this.option, option); + return this.option; + } + }, { + key: "getVideoUrl", + value: function getVideoUrl() { var _this = this; var fileType = ['video/mp4', 'video/ogg', 'video/webm']; @@ -121,10 +140,84 @@ }); } }, { - key: "setup", - value: function setup() { + key: "getThumbnailUrl", + value: function getThumbnailUrl() { + var _this2 = this; + var option = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - this.option = objectSpread({}, this.option, option); + this.mergeOption(option); + var _this$option = this.option, + number = _this$option.number, + width = _this$option.width, + height = _this$option.height, + column = _this$option.column, + videoElement = _this$option.videoElement, + callbackDone = _this$option.callbackDone; + var duration = videoElement.duration; + var timeGap = duration / number; + var timePoints = [timeGap]; + + while (timePoints.length < number) { + var last = timePoints[timePoints.length - 1]; + timePoints.push(last + timeGap); + } + + var screenshotDate = timePoints.map(function (item, index) { + return { + time: item - timeGap / 2, + x: index % column * width, + y: Math.floor(index / column) * height + }; + }); + var canvas = document.createElement('canvas'); + canvas.width = width * column; + canvas.height = Math.ceil(number / column) * height; + var promiseList = screenshotDate.map(function (item) { + return _this2.getScreenshot(canvas, item); + }); + runPromisesInSeries(promiseList).then(function () { + var thumbnailUrl = canvas.toDataURL('image/png'); + _this2.thumbnailUrl = thumbnailUrl; + + if (callbackDone) { + callbackDone(_this2.videoUrl, thumbnailUrl); + } + }); + } + }, { + key: "getScreenshot", + value: function getScreenshot(canvas, item) { + var _this3 = this; + + return function () { + var context2D = canvas.getContext('2d'); + var _this3$option = _this3.option, + width = _this3$option.width, + height = _this3$option.height, + videoElement = _this3$option.videoElement, + delay = _this3$option.delay, + callbackThumbnailUrl = _this3$option.callbackThumbnailUrl; + videoElement.currentTime = item.time; + return sleep(delay).then(function () { + context2D.drawImage(videoElement, item.x, item.y, width, height); + var thumbnailUrl = canvas.toDataURL('image/png'); + + if (callbackThumbnailUrl) { + callbackThumbnailUrl(thumbnailUrl); + } + }); + }; + } + }], [{ + key: "DEFAULTS", + get: function get() { + return { + delay: 300, + number: 60, + width: 160, + height: 90, + column: 10 + }; } }]); diff --git a/packages/artplayer-tool-thumbnail/src/index.js b/packages/artplayer-tool-thumbnail/src/index.js index 04f64bc2d..159b139c8 100644 --- a/packages/artplayer-tool-thumbnail/src/index.js +++ b/packages/artplayer-tool-thumbnail/src/index.js @@ -6,6 +6,14 @@ function errorHandle(condition, msg) { } } +function runPromisesInSeries(ps) { + return ps.reduce((p, next) => p.then(next), Promise.resolve()); +} + +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + class ArtplayerToolThumbnail { constructor(option) { if (option.fileInput) { @@ -30,11 +38,32 @@ class ArtplayerToolThumbnail { ); } - this.option = option; - this.init(); + this.option = { + ...ArtplayerToolThumbnail.DEFAULTS, + ...option, + }; + this.getVideoUrl(); } - init() { + static get DEFAULTS() { + return { + delay: 300, + number: 60, + width: 160, + height: 90, + column: 10, + }; + } + + mergeOption(option = {}) { + this.option = { + ...this.option, + ...option, + }; + return this.option; + } + + getVideoUrl() { const fileType = ['video/mp4', 'video/ogg', 'video/webm']; this.option.fileInput.addEventListener('change', () => { const file = this.option.fileInput.files[0]; @@ -49,10 +78,46 @@ class ArtplayerToolThumbnail { }); } - setup(option = {}) { - this.option = { - ...this.option, - ...option, + getThumbnailUrl(option = {}) { + this.mergeOption(option); + const { number, width, height, column, videoElement, callbackDone } = this.option; + const { duration } = videoElement; + const timeGap = duration / number; + const timePoints = [timeGap]; + while (timePoints.length < number) { + const last = timePoints[timePoints.length - 1]; + timePoints.push(last + timeGap); + } + const screenshotDate = timePoints.map((item, index) => ({ + time: item - timeGap / 2, + x: (index % column) * width, + y: Math.floor(index / column) * height, + })); + const canvas = document.createElement('canvas'); + canvas.width = width * column; + canvas.height = Math.ceil(number / column) * height; + const promiseList = screenshotDate.map(item => this.getScreenshot(canvas, item)); + runPromisesInSeries(promiseList).then(() => { + const thumbnailUrl = canvas.toDataURL('image/png'); + this.thumbnailUrl = thumbnailUrl; + if (callbackDone) { + callbackDone(this.videoUrl, thumbnailUrl); + } + }); + } + + getScreenshot(canvas, item) { + return () => { + const context2D = canvas.getContext('2d'); + const { width, height, videoElement, delay, callbackThumbnailUrl } = this.option; + videoElement.currentTime = item.time; + return sleep(delay).then(() => { + context2D.drawImage(videoElement, item.x, item.y, width, height); + const thumbnailUrl = canvas.toDataURL('image/png'); + if (callbackThumbnailUrl) { + callbackThumbnailUrl(thumbnailUrl); + } + }); }; } }