FenXiNspUniapp/packDetail1/component/timeLine/timeLine.vue

638 lines
26 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view style="height: 100%">
<!-- 这是自定义组件的内部WXML结构 -->
<view class="time-line-container">
<view class="current-time" id="current-time-scal">
<view class="current-time-bg">{{ current }}</view>
</view>
<view class="">
<scroll-view :scroll-y="true" class="time-line-item-container" :scroll-top="scrollTop" :enhanced="true" :show-scrollbar="false">
<view
:scroll-y="true"
style="height: 300px"
class="time-line-item"
id="time-line-item"
:enhanced="true"
@dragend="binddragendFun"
@touchend="binddragendFun"
@touchmove="bindtouchMoveFun"
:disable-scroll="true"
>
<view
class="time-item"
:style="'margin-top: ' + item.marginTop + 'px; padding-bottom: ' + item.paddingBottom + 'px; border-right-color: ' + item.borderColor + ';'"
v-for="(item, index) in timeArr"
:key="index"
>
<view class="scale"></view>
<view class="scale"></view>
<view class="scale"></view>
<view class="scale"></view>
<view class="scale"></view>
<view class="scale" style="width: 10px"></view>
<!-- <view class="item-unavail" style="height: {{item.availPercent}}px; top: {{item.availTop}}px"></view> -->
<view class="item-unavail" :style="'height: ' + item.height + 'px; top: ' + item.top + 'px'" v-for="(item, index1) in item.recArr" :key="index1"></view>
<view :id="item.label" style="position: relative; top: 51px; left: 40%">{{ item.current }}</view>
</view>
</view>
</scroll-view>
</view>
</view>
<slot></slot>
</view>
</template>
<script>
export default {
data() {
return {
// 这里是一些组件内部数据
// someData: {},
start: '00:00:00',
// 传入最近片段起始时刻
end: '24:00:00',
// 传入最近片段结束时刻 默认结束时间为240000, 1440 24
current: 0,
// 当前播放时刻
// rate: 1, // 12小时 21小时 3半小时 410分钟 51分钟
timelag: 30,
// 120: 2小时 601小时 30半小时1010分钟11分钟
timeArr: [],
// 时间轴列表
availTimeLine: [
{
st: '22:33:48',
et: '23:59:59'
},
{
st: '20:11:23',
et: '22:33:48'
},
{
st: '23:00:23',
et: '23:00:48'
}
],
// 由实际存在视频片段的时间组成,[{st: '', et: ''}, {st: '', et: ''}, ...]
scrollTop: 0,
// 页面滚动偏移量 页面偏移量由传入时刻决定
currentTimer: '',
// 时刻定时器
timelineTimer: '',
//时间轴定时器,
index: 0,
// 初始时刻在availtimeLine中的index
playCodeClone: 0,
// 当前播放状态值
date: '',
noTimeLineTxt: '',
//当前距离页面高度
currentTop: 0,
playCodeClone: 0
};
},
props: {
// 这里定义了innerText属性属性值可以在组件使用时指定
innerText: {
type: String,
default: 'default value'
},
playCode: {
type: Number,
observer: function (news, olds, path) {
console.log('news', news);
// news == 2004 开始播放
if (news == 2004 || news == 2003 || news == 2105 || news == 2009 || news == 2107 || news == 2032) {
// 根据偏移量自动滚动时间轴
this._autoScrollTimeLine();
} else {
const { currentTimer, timelineTimer } = this.data;
clearInterval(currentTimer);
clearInterval(timelineTimer)
}
this.playCode=news
}
},
dateLine: {
type: Array,
observer: function (news, olds, path) {
console.log('news', news);
if (news.length && news.length > 0) {
this.availTimeLine=news,
this.start=news[0].st,
this.end=news[0].et,
this.current=news[0].st,
// 渲染时间轴
this._matchTimeDot();
// 根据起始时间设置初始偏移量
this.primaryOffsetH();
// 将当前播放时间片段传给父组件
this.triggerEvent('getPalyParam', { stTime: news[0].st, etTime: news[0].et })
} else {
const { currentTimer, timelineTimer } = this.data;
clearInterval(currentTimer);
clearInterval(timelineTimer)
this.availTimeLine=[],
this.current=0,
// 渲染时间轴
this._matchTimeDot();
this.primaryOffsetH();
}
}
}
},
mounted() {
// 处理小程序 attached 生命周期
this.attached();
},
methods: {
attached: function () {},
// 这里是一个自定义方法
customMethod: function () {},
handletouchmove: function (event) {
console.log('event', event);
},
// 时刻转分钟
timeToMinute: function (time) {
const e = time.split(':');
let h = Number(e[0]);
const m = Number(e[1]);
// const s = Number(e[2]);
return h * 60 + m;
},
// 时刻转秒
timeToSecond: function (time) {
const e = time.split(':');
let h = Number(e[0]);
const m = Number(e[1]);
const s = Number(e[2]);
return h * 60 * 60 + m * 60 + (s ? s : 0);
},
// 分钟转时刻
minuteToTime: function (minute) {
let hour = Math.floor(minute / 60);
let m = minute % 60;
return (hour > 9 ? hour : '0' + hour) + ':' + (m > 9 ? m : '0' + m);
},
// 计时器,每秒+1
secondCountDown: function (time) {
const { current } = this;
// console.log('currentTime', current);
const temp = current.split(':');
let hour = Number(temp[0]);
let minute = Number(temp[1]);
let second = Number(temp[2]);
let t = hour * 60 * 60 + minute * 60 + second + 1;
let h = Math.floor(t / 3600);
let m = Math.floor((t - h * 3600) / 60);
let s = t - h * 3600 - m * 60;
this.current=(h > 9 ? h : '0' + h) + ':' + (m > 9 ? m : '0' + m) + ':' + (s > 9 ? s : '0' + s)
},
// 渲染时间轴
matchTimeDotFun: function () {
const { start, end, timelag, availTimeLine } = this;
console.log('start', start, 'end', end);
var timeArr = [];
let availPercent = 0;
// 播放时间片段时刻转分钟
let availArr = [];
let len = availTimeLine.length;
for (let i = 0; i < len; i++) {
const temp = availTimeLine[i];
let st = this.timeToSecond(temp.st);
let et = this.timeToSecond(temp.et);
// console.log('st: ', st, 'et:', et);
let stminute;
let etminute;
let stAvailPercent = 0;
let etAvailPercent = 0;
stminute = Math.floor(st / (timelag * 60)) * timelag;
stAvailPercent = (st - stminute * 60) / timelag;
etminute = Math.floor(et / (timelag * 60)) * timelag;
etAvailPercent = (et - etminute * 60) / timelag;
// stminute = this.timeToMinute(temp.st);
// etminute= this.timeToMinute(temp.et);
// const offset_stminute = stminute-(Math.floor(stminute/timelag) * timelag);
// console.log(offset_stminute);
// const offset_etminute = etminute-(Math.floor(etminute/timelag) * timelag);
// stAvailPercent = (offset_stminute*60 + (st - ( stminute*60 )))/(60*timelag);
// console.log(stAvailPercent);
// etAvailPercent = (offset_etminute*60 + (et - ( etminute*60 )))/(60*timelag);
availArr[i] = {
st: stminute,
et: etminute,
stAvailPercent: stAvailPercent,
etAvailPercent: etAvailPercent
};
}
console.log('availArr: ', availArr);
// 时间转分钟
let minute = this.timeToMinute(end);
// // 检测是否包含秒,则实际分钟加1
// const e = end.split(':');
// const s = Number(e[2]);
// if (s > 0) {
// minute = minute + 1
// }
minute = Math.floor(minute / timelag) * timelag;
for (let i = minute; i >= 0; ) {
// let borderColor = '#ddd';
let marginTop = 0;
let paddingBottom = 0;
// let availPercent = 0;
let availTop = 0;
let recArr = [];
if (i == minute) {
marginTop = 70;
}
if (i == 0) {
paddingBottom = 290;
}
for (let j = 0; j < len; j++) {
if (i >= availArr[j].st && i <= availArr[j].et) {
if (i == availArr[j].st && i == availArr[j].et) {
availPercent = availArr[j].etAvailPercent - availArr[j].stAvailPercent;
availTop = 60 - availArr[j].etAvailPercent;
var height = availArr[j].etAvailPercent - availArr[j].stAvailPercent;
var top = 60 - availArr[j].etAvailPercent;
recArr.push({
height: height,
top: top
});
} else {
if (i == availArr[j].st) {
recArr.push({
height: 60 - availArr[j].stAvailPercent,
top: 0
});
}
if (i == availArr[j].et) {
recArr.push({
height: availArr[j].etAvailPercent,
top: 60 - availArr[j].etAvailPercent
});
} else if (i > availArr[j].st && i < availArr[j].et) {
recArr.push({
height: 60,
top: 0
});
}
}
}
}
let time = this.minuteToTime(i);
timeArr.push({
id: i,
current: time,
label: 'a' + i,
marginTop: marginTop,
paddingBottom: paddingBottom,
recArr: recArr
});
i = i - timelag;
}
this.timeArr=timeArr
console.log('timeArr:', timeArr);
uni.createSelectorQuery()
.in(this)
.select('#current-time-scal')
.boundingClientRect((rect) => {
console.log('~~~~~~~~~~~~~~~~~~~~', rect);
this.currentTop=rect.top + 30
})
.exec();
},
// 计算初始偏移量
primaryOffsetH: function () {
const { start, timelag, timeArr } = this;
const currentItem = timeArr[0].current;
console.log(currentItem);
const currentTime = this.timeToSecond(currentItem);
console.log(currentTime);
const startSecond = this.timeToSecond(start);
console.log(startSecond);
const offsetS = currentTime - startSecond;
console.log(offsetS);
const offsetH = Math.ceil(offsetS / timelag) + 60; // offsetS / (timelag * 60) * 60
this.scrollTop=offsetH
console.log('起始偏移量', offsetH);
},
// 计算当前偏移量
currentOffsetH: function () {
const { current, timelag, timeArr } = this;
const startItem = timeArr[0].current;
console.log(startItem);
const startSecond = this.timeToSecond(startItem);
console.log(startSecond);
const currentSecond = this.timeToSecond(current);
console.log(currentSecond);
const offsetS = startSecond - currentSecond;
console.log(offsetS);
const offsetH = Math.ceil(offsetS / timelag) + 60; // offsetS / (timelag * 60) * 60
this.scrollTop=offsetH
console.log('当前偏移量', offsetH);
},
// 通过时间轴位置获取当前时间
rectTopTotime: function (reactTop) {
let { timelag } = this;
// let rectTop = rect.top; // 获取当前元素距离父元素顶部的高度
// let reactTop = 0 - rectTop; // 实际偏移高度
let index = Math.floor(reactTop / 60); // 以分钟为刻度时每个元素初始高度为60px, 向下取整并除以时刻倍数得出偏移item;
let offsetH = Math.floor(reactTop - index * 60); // 偏移高度
let current;
let offsetSecond;
console.log('index', index, 'offsetH:', offsetH);
if (offsetH == 0) {
if (index == 0) {
const currentMinute = this.timeToMinute(this.timeArr[0].current);
const time = currentMinute + timelag;
current = this.minuteToTime(time);
offsetSecond = 0;
} else {
current = this.timeArr[index - 1].current;
offsetSecond = 0;
}
} else {
// 当timelag==120,timelag==60,timelag==30,timelag==10,timelag==1
const time = this.timeArr[index].current;
let minute = this.timeToMinute(time);
// 相对于下一元素偏移
const offsetY = 60 - offsetH;
const offsetS = offsetY * timelag; // offsetY / 60 * timelag * 60
const offsetM = Math.floor(offsetS / 60) + minute;
const second = Math.floor(offsetS / 60) * 60;
offsetSecond = Math.ceil(offsetS - second); // 保留两位小数
current = this.minuteToTime(offsetM);
}
this.current=current + ':' + (offsetSecond > 9 ? offsetSecond : '0' + offsetSecond),
this.scrollTop=reactTop
console.log('rectLeft', reactTop);
console.log('currentTime', current);
},
// 时间轴自动滚动, 时间每秒变化时间轴根据timelag滚动
autoScrollTimeLineFun: function () {
const { timelag, end, availTimeLine } = this;
let { scrollTop } = this;
const that = this;
const waitTime = timelag * 1000;
let top = Math.abs(scrollTop);
console.log('top', top);
if (this.currentTimer) {
clearInterval(this.currentTimer);
}
if (this.timelineTimer) {
clearInterval(this.timelineTimer);
}
/**时间时刻变化 */
let currentTimer = setInterval(() => {
let { index, current } = that;
if (current == availTimeLine[index].et && index == 0) {
clearInterval(currentTimer);
clearInterval(timelineTimer);
console.log('当播放到最后一刻停止');
} else if (current == availTimeLine[index].et && index > 0) {
this.index=index - 1,
this.current=availTimeLine[index - 1].st
this.currentOffsetH();
console.log('跳转到下一个时间片段');
// 将指定的播放时间片段传递给父组件i;
// this.triggerEvent('getPalyParam', { playParam: availTimeLine[index-1] })
} else {
this.secondCountDown();
}
}, 1000);
/**时间轴滚动间隔为 timelg*1000 */
let timelineTimer = setInterval(() => {
let { scrollTop } = this;
scrollTop--;
// console.log('偏移量',scrollTop);
this.scrollTop=scrollTop
}, waitTime);
this.currentTimer=currentTimer,
this.timelineTimer=timelineTimer
},
//
// 监听手动滚动时间轴时,停止时间轴滚动,时刻仍然变化
bindtouchMoveFun: function () {
console.log('监听到时间轴滚动');
let { timelineTimer, currentTimer, currentTop } = this;
if (timelineTimer || currentTimer) {
clearInterval(timelineTimer);
clearInterval(currentTimer);
}
},
// 手动滚动停止,选定时刻自动播放
binddragendFun: function (event) {
/** 清除已存在的timer */
let { timelineTimer, currentTimer } = this;
let that = this;
if (timelineTimer || currentTimer) {
clearInterval(timelineTimer);
clearInterval(currentTimer);
}
var timer;
const scollPromise = new Promise(function (resolve, reject) {
console.log('start');
let preTop = -1;
timer = setInterval(() => {
console.log('intel');
// debugger
uni.createSelectorQuery()
.in(that)
.select('#time-line-item')
.boundingClientRect((rect) => {
console.log('*rect', rect);
if (rect.top !== preTop) {
console.log('scolling', rect.top, preTop);
preTop = rect.top;
} else {
console.log('scoll stop');
resolve(rect.top);
}
})
.exec();
}, 100);
});
scollPromise.then((data) => {
clearInterval(timer);
uni.createSelectorQuery()
.in(this)
.select('#time-line-item')
.boundingClientRect((rect) => {
let { timelag, availTimeLine, currentTop } = this;
// let rectTop = rect.top; // 获取当前元素距离父元素顶部的高度第一个元素包含margin-top: 70px
// let reactTop = 70 - rectTop; // 实际偏移高度 (除去margin-top);
let rectTop = rect.top;
let reactTop = currentTop - rectTop; // 实际偏移高度
console.log('****************************************', rectTop, currentTop, rectTop);
console.log('页面滚动实际高度', reactTop);
if (reactTop == 0) {
const time = this.timeArr[0].current;
const currentTime = this.timeToMinute(time);
const minute = currentTime + timelag;
const current = this.minuteToTime(minute);
this.current=current + ':' + '00'
} else {
// 根据实际偏移高度计算当前时间
this.rectTopTotime(reactTop);
}
/** 判断当前时刻是否在有播放片段的时间段内 */
let len = availTimeLine.length;
for (let i = 0; i < len - 1; i++) {
const j = i + 1;
const temp = availTimeLine[i];
const nextTemp = availTimeLine[j];
let st = this.timeToSecond(temp.st);
let et = this.timeToSecond(temp.et);
let nextEt = this.timeToSecond(nextTemp.et);
let nextSt = this.timeToSecond(nextTemp.st);
const { current } = this;
const currentSecond = this.timeToSecond(current);
if (j == len - 1 && currentSecond < nextSt) {
this.index=j,
this.current=availTimeLine[j].st
this.currentOffsetH();
this.$emit('getPalyParam', {
detail: {
stTime: availTimeLine[j].st,
etTime: availTimeLine[0].et
}
});
return;
}
// 在可播放范围内
if (currentSecond >= st && currentSecond <= et) {
/** 时间轴移动 */
this.index=i,
this.current=current
// 将指定的播放时间片段传递给父组件i
console.log('传递给父组件i:', current);
this.currentOffsetH();
this.$emit('getPalyParam', {
detail: {
etTime: availTimeLine[0].et,
stTime: current
}
});
return;
} else if (currentSecond < st && currentSecond > nextEt) {
this.index=i,
this.current=availTimeLine[i].st
this.currentOffsetH();
// 将指定的播放时间片段传递给父组件i
this.$emit('getPalyParam', {
detail: {
stTime: availTimeLine[i].st,
etTime: availTimeLine[0].et
}
});
return;
}
}
})
.exec();
});
}
},
created: function () {},
watch: {
playCode: {
handler: function (news, olds, path) {
// this.playCodeClone = this.clone(this.playCode);
console.log('news', news);
// news == 2004 开始播放
if (news == 2004 || news == 2003 || news == 2105 || news == 2009 || news == 2107 || news == 2032) {
// 根据偏移量自动滚动时间轴
this.autoScrollTimeLineFun();
} else {
const { currentTimer, timelineTimer } = this;
clearInterval(currentTimer);
clearInterval(timelineTimer);
}
this.playCode=news
},
immediate: true
},
dateLine: {
handler: function (news, olds, path) {
console.log('news', news);
if (news.length && news.length > 0) {
this.availTimeLine=news,
this.start=news[0].st,
this.end=news[0].et,
this.current=news[0].st
// 渲染时间轴
this.matchTimeDotFun();
// 根据起始时间设置初始偏移量
this.primaryOffsetH();
// 将当前播放时间片段传给父组件
this.$emit('getPalyParam', {
detail: {
stTime: news[0].st,
etTime: news[0].et
}
});
} else {
const { currentTimer, timelineTimer } = this;
clearInterval(currentTimer);
clearInterval(timelineTimer);
this.availTimeLine=[],
this.current=0
// 渲染时间轴
this.matchTimeDotFun();
this.primaryOffsetH();
}
},
immediate: true,
deep: true
}
}
};
</script>
<style>
@import './timeLine.css';
</style>