|
@@ -0,0 +1,315 @@
|
|
|
+Component({
|
|
|
+ options: {
|
|
|
+ addGlobalClass: true,
|
|
|
+ // 指定所有 _ 开头的数据字段为纯数据字段
|
|
|
+ pureDataPattern: /^_/
|
|
|
+ },
|
|
|
+ properties: {
|
|
|
+ duration: {
|
|
|
+ type: Number,
|
|
|
+ value: 500
|
|
|
+ },
|
|
|
+ easingFunction: {
|
|
|
+ type: String,
|
|
|
+ value: 'default'
|
|
|
+ },
|
|
|
+ loop: {
|
|
|
+ type: Boolean,
|
|
|
+ value: true
|
|
|
+ },
|
|
|
+ targetPlayIndex: {
|
|
|
+ type: Number,
|
|
|
+ value: -1,
|
|
|
+ observer: function (newVal) {
|
|
|
+ if (newVal >= 0) {
|
|
|
+ this.targetPlay(newVal)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // {id, url, objectFit}
|
|
|
+ videoList: {
|
|
|
+ type: Array,
|
|
|
+ value: [],
|
|
|
+ observer: function (newVal = []) {
|
|
|
+ this._videoListChanged(newVal)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data: {
|
|
|
+ nextQueue: [], // 待播放列表
|
|
|
+ prevQueue: [], // 已播放列表
|
|
|
+ curQueue: [], // 当前播放列表
|
|
|
+ circular: false, // 是否循环
|
|
|
+ _last: 0, // 上一次显示
|
|
|
+ _maxCount: -1,
|
|
|
+ _dataIdx: 0,
|
|
|
+ initIndex: 0,
|
|
|
+ playerIdx: 0,
|
|
|
+ playing: false,
|
|
|
+ _change: -1,
|
|
|
+ _invalidUp: 0,
|
|
|
+ _invalidDown: 0,
|
|
|
+ _videoContexts: []
|
|
|
+ },
|
|
|
+ lifetimes: {
|
|
|
+ attached() {
|
|
|
+ this.data._videoContexts = [
|
|
|
+ wx.createVideoContext('video_0', this),
|
|
|
+ wx.createVideoContext('video_1', this),
|
|
|
+ wx.createVideoContext('video_2', this)
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this._swipering = false
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // 添加新的视频源
|
|
|
+ _videoListChanged(newVal) {
|
|
|
+
|
|
|
+ const data = this.data
|
|
|
+
|
|
|
+ newVal.forEach(item => {
|
|
|
+ data.nextQueue.push(item)
|
|
|
+ })
|
|
|
+ const maxCount = newVal.length
|
|
|
+ if (data.curQueue.length === 0) {
|
|
|
+ this.setData({
|
|
|
+ curQueue: data.nextQueue.splice(0, 3),
|
|
|
+ _maxCount: maxCount
|
|
|
+ }, () => {
|
|
|
+ this.playCurrent(0)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ animationfinish(e) {
|
|
|
+ const {
|
|
|
+ _last,
|
|
|
+ _change,
|
|
|
+ curQueue,
|
|
|
+ prevQueue,
|
|
|
+ nextQueue
|
|
|
+ } = this.data
|
|
|
+
|
|
|
+ const current = e.detail.current
|
|
|
+ const diff = current - _last
|
|
|
+ this._swipering = false
|
|
|
+
|
|
|
+ this.data._last = current
|
|
|
+ this.playCurrent(current)
|
|
|
+
|
|
|
+ const direction = (diff === 1 || diff === -2) ? 'up' : 'down'
|
|
|
+
|
|
|
+ console.log('direction', direction)
|
|
|
+
|
|
|
+ if (direction === 'up') {
|
|
|
+ if (this.data._invalidDown === 0) {
|
|
|
+ this.data._dataIdx++
|
|
|
+ if (this.data._dataIdx >= this.data._maxCount) {
|
|
|
+ this.data._dataIdx = 0
|
|
|
+ }
|
|
|
+ this.loadCurQueue(this.data._dataIdx, current)
|
|
|
+ } else {
|
|
|
+ this.data._invalidDown -= 1
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (direction === 'down') {
|
|
|
+ if (this.data._invalidUp === 0) {
|
|
|
+ this.data._dataIdx--
|
|
|
+ if (this.data._dataIdx < 0) {
|
|
|
+ this.data._dataIdx = this.data._maxCount - 1
|
|
|
+ }
|
|
|
+ this.loadCurQueue(this.data._dataIdx, current)
|
|
|
+ } else {
|
|
|
+ this.data._invalidUp -= 1
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.triggerEvent('change', {
|
|
|
+ activeId: curQueue[current].id
|
|
|
+ })
|
|
|
+
|
|
|
+ let circular = true
|
|
|
+
|
|
|
+ // if (nextQueue.length === 0 && current !== 0) {
|
|
|
+ // circular = false
|
|
|
+ // }
|
|
|
+
|
|
|
+ // if (prevQueue.length === 0 && current !== 2) {
|
|
|
+ // circular = false
|
|
|
+ // }
|
|
|
+
|
|
|
+
|
|
|
+ this.setData({
|
|
|
+ curQueue,
|
|
|
+ circular,
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ loadCurQueue(dataIdx, playerIdx) {
|
|
|
+ const {
|
|
|
+ _maxCount,
|
|
|
+ curQueue,
|
|
|
+ videoList
|
|
|
+ } = this.data
|
|
|
+
|
|
|
+ const current = playerIdx;
|
|
|
+ let curDataIdx = dataIdx;
|
|
|
+
|
|
|
+ if (curDataIdx > _maxCount) {
|
|
|
+ curDataIdx = _maxCount;
|
|
|
+ }
|
|
|
+
|
|
|
+ let pre = 0,
|
|
|
+ next = 0,
|
|
|
+ preV, nextV, curVideo;
|
|
|
+
|
|
|
+ pre = current - 1;
|
|
|
+ if (pre < 0) {
|
|
|
+ pre = 2;
|
|
|
+ }
|
|
|
+ next = current + 1;
|
|
|
+ if (next > 2) {
|
|
|
+ next = 0;
|
|
|
+ }
|
|
|
+ if (curDataIdx - 1 >= 0) {
|
|
|
+ preV = videoList[curDataIdx - 1];
|
|
|
+ } else {
|
|
|
+ preV = videoList[_maxCount - 1];
|
|
|
+ }
|
|
|
+ console.log('curDataIdx + 1 ', curDataIdx + 1)
|
|
|
+ if (curDataIdx + 1 < _maxCount) {
|
|
|
+ nextV = videoList[curDataIdx + 1];
|
|
|
+ } else {
|
|
|
+ nextV = videoList[0];
|
|
|
+ }
|
|
|
+
|
|
|
+ curVideo = videoList[curDataIdx];
|
|
|
+ curQueue[pre] = preV
|
|
|
+ curQueue[next] = nextV
|
|
|
+ curQueue[current] = curVideo
|
|
|
+
|
|
|
+
|
|
|
+ console.log('preV', preV)
|
|
|
+ console.log('curVideo', curVideo)
|
|
|
+ console.log('nextV', nextV)
|
|
|
+ console.log('curQueue', curQueue)
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 指定视频播放
|
|
|
+ * @param {videoList(index)} dataIdx
|
|
|
+ */
|
|
|
+ targetPlay(dataIdx) {
|
|
|
+ let curQueue = this.data.videoList.slice();
|
|
|
+
|
|
|
+ if (dataIdx >= this.data._maxCount) {
|
|
|
+ this._dataIdx = dataIdx = this.data._maxCount - 1
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.data._maxCount - dataIdx < 3) {
|
|
|
+ if (this.data._maxCount - dataIdx === 2) {
|
|
|
+ const last = this.data.videoList.slice().shift();
|
|
|
+ curQueue = curQueue.splice(dataIdx, 2).concat(last)
|
|
|
+ }
|
|
|
+ if (this.data._maxCount - dataIdx === 1) {
|
|
|
+ const first = this.data.videoList.slice().pop();
|
|
|
+ curQueue = [first].concat(curQueue.splice(0, 2));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ curQueue = curQueue.splice(dataIdx, 3)
|
|
|
+ }
|
|
|
+ this.setData({
|
|
|
+ curQueue: curQueue,
|
|
|
+ _dataIdx: dataIdx,
|
|
|
+ playerIdx: 0
|
|
|
+ }, () => {
|
|
|
+ this.playCurrent(0)
|
|
|
+ })
|
|
|
+ },
|
|
|
+ // 避免卡顿
|
|
|
+ playCurrent(current) {
|
|
|
+
|
|
|
+ this.data._videoContexts.forEach((ctx, index) => {
|
|
|
+ index !== current ? ctx.pause() : ctx.play()
|
|
|
+ })
|
|
|
+
|
|
|
+ this.setData({
|
|
|
+ playing: true,
|
|
|
+ playerIdx: current
|
|
|
+ }, () => {
|
|
|
+ // this.data._videoContexts.forEach((ctx, index) => {
|
|
|
+ // index !== current ? ctx.seek(0) : null
|
|
|
+ // })
|
|
|
+ })
|
|
|
+ // // 重置所有视频pause时重置时间
|
|
|
+ // setTimeout(() => {
|
|
|
+ // this.data._videoContexts.forEach((ctx, index) => {
|
|
|
+ // index !== current ? ctx.seek(0) : null
|
|
|
+ // })
|
|
|
+ // }, 100)
|
|
|
+
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ onPlay(e) {
|
|
|
+ this.trigger(e, 'play')
|
|
|
+ },
|
|
|
+
|
|
|
+ onPause(e) {
|
|
|
+ this.trigger(e, 'pause')
|
|
|
+ },
|
|
|
+
|
|
|
+ onEnded(e) {
|
|
|
+ this.trigger(e, 'ended')
|
|
|
+ },
|
|
|
+
|
|
|
+ onError(e) {
|
|
|
+ this.trigger(e, 'error')
|
|
|
+ },
|
|
|
+
|
|
|
+ onTimeUpdate(e) {
|
|
|
+ this.trigger(e, 'timeupdate')
|
|
|
+ },
|
|
|
+
|
|
|
+ onWaiting(e) {
|
|
|
+ this.trigger(e, 'wait')
|
|
|
+ },
|
|
|
+
|
|
|
+ onProgress(e) {
|
|
|
+ this.trigger(e, 'progress')
|
|
|
+ },
|
|
|
+
|
|
|
+ onLoadedMetaData(e) {
|
|
|
+ this.trigger(e, 'loadedmetadata')
|
|
|
+ },
|
|
|
+ trigger(e, type, ext = {}) {
|
|
|
+ const detail = e.detail
|
|
|
+ const activeId = e.target.dataset.id
|
|
|
+ this.triggerEvent(type, Object.assign({
|
|
|
+ ...detail,
|
|
|
+ activeId
|
|
|
+ }, ext))
|
|
|
+ },
|
|
|
+ onVideoOverlayTap() {
|
|
|
+ if (this.data.playing) {
|
|
|
+ this.data._videoContexts.forEach((ctx, index) => {
|
|
|
+ ctx.pause()
|
|
|
+ })
|
|
|
+ this.setData({
|
|
|
+ playing: false
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ this.data._videoContexts.forEach((ctx, index) => {
|
|
|
+ index !== this.data.playerIdx ? ctx.pause() : ctx.play()
|
|
|
+ })
|
|
|
+ this.setData({
|
|
|
+ playing: true
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onSwiping() {
|
|
|
+ this._swipering = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+})
|