UNPKG

@tarojs/components

Version:

Taro 组件库

232 lines (228 loc) • 7.89 kB
import { proxyCustomElement, HTMLElement, h, Host } from '@stencil/core/internal/client'; const formatTime = (time) => { if (!time) return ''; const sec = Math.round(time % 60); const min = Math.round((time - sec) / 60); return `${min < 10 ? `0${min}` : min}:${sec < 10 ? `0${sec}` : sec}`; }; const calcDist = (x, y) => { return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); }; const normalizeNumber = (number) => { return Math.max(-1, Math.min(number, 1)); }; let scene = 'default'; const screenFn = (function () { let val; const fnMap = [ [ 'requestFullscreen', 'exitFullscreen', 'fullscreenElement', 'fullscreenEnabled', 'fullscreenchange', 'fullscreenerror' ], // New WebKit [ 'webkitRequestFullscreen', 'webkitExitFullscreen', 'webkitFullscreenElement', 'webkitFullscreenEnabled', 'webkitfullscreenchange', 'webkitfullscreenerror' ], // Old WebKit [ 'webkitRequestFullScreen', 'webkitCancelFullScreen', 'webkitCurrentFullScreenElement', 'webkitCancelFullScreen', 'webkitfullscreenchange', 'webkitfullscreenerror' ], [ 'mozRequestFullScreen', 'mozCancelFullScreen', 'mozFullScreenElement', 'mozFullScreenEnabled', 'mozfullscreenchange', 'mozfullscreenerror' ], [ 'msRequestFullscreen', 'msExitFullscreen', 'msFullscreenElement', 'msFullscreenEnabled', 'MSFullscreenChange', 'MSFullscreenError' ] ]; var defaultIOSMap = [ 'webkitEnterFullscreen', 'webkitExitFullscreen', 'webkitCurrentFullScreenElement', 'webkitSupportsFullscreen', 'fullscreenchange', 'fullscreenerror' ]; let i = 0; const l = fnMap.length; const ret = {}; // This for loop essentially checks the current document object for the property/methods above. for (; i < l; i++) { val = fnMap[i]; if (val && val[1] in document) { for (i = 0; i < val.length; i++) { ret[fnMap[0][i]] = val[i]; } return ret; } } if (!ret[fnMap[0][0]]) { scene = 'iOS'; // when there is no any APIs be set. // In IOS, there is no 'webkitEnterFullscreen' property `in document` but video can use it for fullscreen. // ref: https://developer.apple.com/documentation/webkitjs/htmlvideoelement/1633500-webkitenterfullscreen for (i = 0; i < defaultIOSMap.length; i++) { ret[fnMap[0][i]] = defaultIOSMap[i]; } } // If it doesn't find any of them, this whole function returns {} // and the fn variable is set to this returned value. return ret; })(); const isHls = url => /\.(m3u8)($|\?)/i.test(url); const VideoControl = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement { constructor() { super(); this.__registerHost(); this.visible = false; this.isDraggingProgressBall = false; this.percentage = 0; this.progressDimensions = { left: 0, width: 0 }; this.calcPercentage = (pageX) => { let pos = pageX - this.progressDimensions.left; pos = Math.max(pos, 0); pos = Math.min(pos, this.progressDimensions.width); return pos / this.progressDimensions.width; }; this.onDragProgressBallStart = () => { this.isDraggingProgressBall = true; this.hideControlsTimer && clearTimeout(this.hideControlsTimer); }; this.onClickProgress = (e) => { e.stopPropagation(); const percentage = this.calcPercentage(e.pageX); this.seekFunc(percentage * this.duration); this.toggleVisibility(true); }; this.controls = undefined; this.currentTime = undefined; this.duration = undefined; this.isPlaying = undefined; this.pauseFunc = undefined; this.playFunc = undefined; this.seekFunc = undefined; this.showPlayBtn = undefined; this.showProgress = undefined; } onDocumentTouchMove(e) { if (!this.isDraggingProgressBall) return; const touchX = e.touches[0].pageX; this.percentage = this.calcPercentage(touchX); this.setProgressBall(this.percentage); this.setCurrentTime(this.percentage * this.duration); } onDocumentTouchEnd() { if (!this.isDraggingProgressBall) return; this.isDraggingProgressBall = false; this.seekFunc(this.percentage * this.duration); this.toggleVisibility(true); } async setProgressBall(percentage) { if (this.progressBallRef) { this.progressBallRef.style.left = `${percentage * 100}%`; } } async toggleVisibility(nextVisible) { const visible = nextVisible === undefined ? !this.visible : nextVisible; if (visible) { this.hideControlsTimer && clearTimeout(this.hideControlsTimer); if (this.isPlaying) { this.hideControlsTimer = setTimeout(() => { this.toggleVisibility(false); }, 2000); } this.el.style.visibility = 'visible'; } else { this.el.style.visibility = 'hidden'; } this.visible = !!visible; } async getIsDraggingProgressBall() { return this.isDraggingProgressBall; } async setCurrentTime(time) { this.currentTimeRef.innerHTML = formatTime(time); } render() { const { controls, currentTime, duration, isPlaying, pauseFunc, playFunc, showPlayBtn, showProgress } = this; const formattedDuration = formatTime(duration); let playBtn; if (!showPlayBtn) { playBtn = null; } else if (isPlaying) { playBtn = h("div", { class: 'taro-video-control-button taro-video-control-button-pause', onClick: pauseFunc }); } else { playBtn = h("div", { class: 'taro-video-control-button taro-video-control-button-play', onClick: playFunc }); } return (h(Host, { class: 'taro-video-bar taro-video-bar-full' }, controls && (h("div", { class: 'taro-video-controls' }, playBtn, showProgress && (h("div", { class: 'taro-video-current-time', ref: dom => (this.currentTimeRef = dom) }, formatTime(currentTime))), showProgress && (h("div", { class: 'taro-video-progress-container', onClick: this.onClickProgress }, h("div", { class: 'taro-video-progress', ref: ref => { if (!ref) return; const rect = ref.getBoundingClientRect(); this.progressDimensions.left = rect.left; this.progressDimensions.width = rect.width; } }, h("div", { class: 'taro-video-progress-buffered', style: { width: '100%' } }), h("div", { class: 'taro-video-ball', ref: dom => (this.progressBallRef = dom), onTouchStart: this.onDragProgressBallStart, style: { left: `${formattedDuration ? (this.currentTime / duration) * 100 : 0}%` } }, h("div", { class: 'taro-video-inner' }))))), showProgress && h("div", { class: 'taro-video-duration' }, formattedDuration))), h("slot", null))); } get el() { return this; } }, [4, "taro-video-control", { "controls": [4], "currentTime": [2, "current-time"], "duration": [2], "isPlaying": [4, "is-playing"], "pauseFunc": [16], "playFunc": [16], "seekFunc": [16], "showPlayBtn": [4, "show-play-btn"], "showProgress": [4, "show-progress"], "setProgressBall": [64], "toggleVisibility": [64], "getIsDraggingProgressBall": [64], "setCurrentTime": [64] }, [[5, "touchmove", "onDocumentTouchMove"], [5, "touchend", "onDocumentTouchEnd"], [5, "touchcancel", "onDocumentTouchEnd"]]]); function defineCustomElement() { if (typeof customElements === "undefined") { return; } const components = ["taro-video-control"]; components.forEach(tagName => { switch (tagName) { case "taro-video-control": if (!customElements.get(tagName)) { customElements.define(tagName, VideoControl); } break; } }); } export { VideoControl as V, scene as a, calcDist as c, defineCustomElement as d, formatTime as f, isHls as i, normalizeNumber as n, screenFn as s };