背景
最近项目要求在播放器上实现触摸滑动或者鼠标按下滑动松开时改变播放seek, 要显示播放时间点的变化.
事件
查了一下相关事件,
触摸主要是touchstart, touchemove, touchend.
鼠标按下滑动松开是mousedown, mousemove, mouseleave, mouseup.
实现效果
开始时出现半透明黑色浮层, 中间显示时间的数字变化, 包括固定不变的片长和随着滑动变化的播放时间点, 当滑动动作完成时, 浮层在1秒内渐渐消失.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<style>
#flashbox {
position: absolute;
left: 0px;
top: 0px;
width: 100vw;
height: 100vh;
background-color: black;
display: flex;
justify-content: center;
align-items: center;
}
@keyframes fadeOut0 {
0% { opacity: 1; }
50% { opacity: 1; }
100% { opacity: 0; }
}
@keyframes fadeOut1 {
0% { opacity: 1; }
50% { opacity: 1; }
100% { opacity: 0; }
}
.tipsBox {
position: absolute;
left: 0px; top: 0px;
width: 100%; height: 100%;
background-color: #0000007F;
display: flex;
justify-content: center;
align-items: center;
opacity: 0;
}
.animateFadeOut0 {
animation: fadeOut0 2s;
animation-fill-mode: forwards;
}
.animateFadeOut1 {
animation: fadeOut1 2s;
animation-fill-mode: forwards;
}
.playTimeLeft {
color: #0CCC4C;
font-size: 20px;
padding-right: 10px;
}
.playTimeSplit {
color: #ffffff;
font-size: 20px;
padding-right: 10px;
}
.playTimeRight {
color: #ffffff;
font-size: 20px;
}
</style>
<script>
window.onload = function () {
let obj = document.getElementById('flashbox');
var downX = 0, downY = 0;
var minOffset = 5;
obj.onmousedown = function(event){
if (event) {
downX = parseInt(event.offsetX);
downY = parseInt(event.offsetY);
console.log(`onmousedown, ox: ${downX}, oy: ${downY}`);
obj.onmousemove = onMouseMove;
obj.onmouseup = onMouseUp;
obj.onmouseleave = onMouseUp;
}
}
obj.addEventListener("touchstart", (event)=>{
if (event) {
try {
downX = parseInt(event.touches[0].clientX);
downY = parseInt(event.touches[0].clientY);
} catch (error) { }
console.log(`ontouchstart, ox: ${downX}, oy: ${downY}`);
}
}, false);
obj.addEventListener("touchmove", onTouchMove, false);
function onTouchMove(event) {
if (event) {
var moveX = 0, moveY = 0;
try {
moveX = parseInt(event.touches[0].clientX);
moveY = parseInt(event.touches[0].clientY);
} catch (error) { }
console.log(`ontouchmove, ox: ${moveX}, oy: ${moveY}`);
if (isValidNum(moveX) && isValidNum(moveY) &&
isValidNum(downX) && isValidNum(downY)) {
parseTouchEvent(moveX - downX, moveY - downY);
}
downX = moveX;
downY = moveY;
}
}
obj.addEventListener("touchend", onTouchEnd, false);
function onTouchEnd(event) {
if (event) {
var upX = 0, upY = 0;
try {
upX = parseInt(event.touches[0].clientX);
upY = parseInt(event.touches[0].clientY);
} catch (error) { }
console.log(`ontouchend, ox: ${upX}, oy: ${upY}`);
if (isValidNum(upX) && isValidNum(upY) &&
isValidNum(downX) && isValidNum(downY)) {
parseTouchEvent(upX - downX, upY - downY);
}
downX = 0;
downY = 0;
}
}
function isValidNum(num) {
return typeof num === "number" && !isNaN(num);
}
function onMouseMove(event) {
if (event) {
var moveX = parseInt(event.offsetX);
var moveY = parseInt(event.offsetY);
if (isValidNum(moveX) && isValidNum(moveY) &&
isValidNum(downX) && isValidNum(downY)) {
parseTouchEvent(moveX - downX, moveY - downY);
}
downX = moveX;
downY = moveY;
console.log(`onmousemove, ox: ${moveX}, oy: ${moveY}`);
}
}
function onMouseUp(event) {
if (event) {
var upX = parseInt(event.offsetX);
var upY = parseInt(event.offsetY);
if (isValidNum(upX) && isValidNum(upY) &&
isValidNum(downX) && isValidNum(downY)) {
parseTouchEvent(upX - downX, upY - downY);
}
console.log(`onmouseup, ox: ${upX}, oy: ${upY}`);
document.onmouseup = null;
obj.onmousemove = null;
downX = 0;
downY = 0;
}
}
function parseTouchEvent(offsetX, offsetY) {
if (Math.abs(offsetX) > Math.abs(offsetY)) {
if (offsetX >= 0) {
onTouchEvent("move-right", offsetX);
} else {
onTouchEvent("move-left", -offsetX);
}
} else {
if (offsetY >= 0) {
onTouchEvent("move-down", offsetY);
} else {
onTouchEvent("move-up", -offsetY);
}
}
}
var curPlayPos = 0;
var videoDuration = 600;
function onTouchEvent(touchName, touchOffset) {
if (touchOffset > minOffset) {
console.log(`${touchName} ${touchOffset}`);
if (touchName === "move-right") {
let prePos = curPlayPos;
curPlayPos += touchOffset;
if (curPlayPos > videoDuration) {
curPlayPos = videoDuration;
}
showTips(prePos, curPlayPos);
} else if (touchName === "move-left") {
let prePos = curPlayPos;
curPlayPos -= touchOffset;
if (curPlayPos < 0) {
curPlayPos = 0;
}
showTips(prePos, curPlayPos);
}
}
}
var task = null;
let animateIndex = 0;
var inter = null;
function updateTextByInterval(dom, curPos, dstPos) {
if (curPos === dstPos) return;
task = {
curPos, dstPos,
asend: dstPos > curPos
};
clearInterval(inter);
inter = setInterval(()=>{
if (task) {
if (task.asend) {
task.curPos+=5;
if (task.curPos > task.dstPos) task.curPos = task.dstPos;
} else {
task.curPos-=5;
if (task.curPos < task.dstPos) task.curPos = task.dstPos;
}
dom.innerText = toTimeSpan(task.curPos);
if (task.curPos === task.dstPos) {
clearInterval(inter);
inter = null;
task = null;
}
} else {
clearInterval(inter);
inter = null;
task = null;
}
});
}
function showAnimation(tipsBox) {
animateIndex = (animateIndex + 1) % 2;
tipsBox.setAttribute("class", `tipsBox animateFadeOut${animateIndex}`);
}
function showTips(curPos, dstPos) {
let tipsBox = document.querySelector('.tipsBox');
if (!tipsBox) return;
showAnimation(tipsBox);
let spanLeft = document.querySelector('.playTimeLeft');
spanLeft.innerText = toTimeSpan(curPos);
updateTextByInterval(spanLeft, curPos, dstPos);
let spanRight = document.querySelector('.playTimeRight');
spanRight.innerText = toTimeSpan(videoDuration);
}
function toTimeSpan(seconds) {
var value = Math.round(seconds);
var s = value % 60;
value = Math.floor(value / 60);
var m = value % 60;
value = Math.floor(value / 60);
var h = value;
var strHour = h.toString().padStart(2, '0');
var strMinute = m.toString().padStart(2, '0');
var strSecond = s.toString().padStart(2, '0');
return `${strHour}:${strMinute}:${strSecond}`;
}
}
</script>
</head>
<body >
<div id="flashbox" ondragstart="return false;" onselectstart="return false">
<div class="tipsBox" >
<span class="playTimeLeft"></span>
<span class="playTimeSplit">/</span>
<span class="playTimeRight"></span>
</div>
</div>
</body>
</html>