<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<style>
.video-info {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#selectVideo {
/* border: 2px solid #000000; */
box-sizing: border-box;
/* background: rgba(80, 80, 80); */
display: block;
width: 50%;
height: 0;
padding-top: 28%;
position: relative;
overflow: hidden;
}
#moveSelected {
position: absolute;
border: 1px dashed #d9d9d9;
left: 0px;
top: 0px;
width: 0px;
height: 0px;
background-color: blue;
opacity: 0.3;
visibility: hidden;
z-index: 100;
}
.reduction {
width: 10%;
background: #4e89ff73;
color: #fff;
position: absolute;
right: 0;
top: 0;
text-align: center;
cursor: pointer;
}
</style>
<body>
<!-- 视频 -->
<div id="selectVideo">
<video
id="video"
autoplay
preload
controls
class="video-info"
src="https://joylearning.bmw.com.cn/video/0906133651e0aa7569c8ced509d9b42e8bed52a4b4.mp4"
></video>
<!-- 选中框选 -->
<div id="moveSelected"></div>
<div
class="reduction"
οnclick="rest()">
还原
</div>
</div>
<script>
let obj = {
id: "A",
// 视频or放大后的视频
amplify: {
videoZoomFlag: false, //是否展示放大后的视频
// 视频播放窗口起始点位置
top: 0,
left: 0,
// 记录鼠标按下时的坐标
downX: 0,
downY: 0,
// 记录鼠标抬起时候的坐标
mouseX2: 0,
mouseY2: 0,
//拖拽选择框DOM元素
rect: null, // 拖拽选择框节点rectArea
// 是否需要(允许)处理鼠标的移动事件,默认识不处理
select: false,
// 监控局部放大请求数据
rectInfo: {
videoWidth: 0, //播放界面的宽
videoHeight: 0,
rectWidth: 0, //选择框的宽
rectHeight: 0,
rectCenterOffsetX: 0, //选择框中心坐标
rectCenterOffsetY: 0,
},
showControl: true, // 是否显示控制条:拖拽选区时不显示
bigVideoBig: false, //当前是否为放大视频
},
};
let selectVideo = document.getElementById("selectVideo"); //最外层
let video = document.getElementById("video"); //视频标签
let moveSelected = document.getElementById("moveSelected"); // 选中阴影
console.dir(selectVideo);
/**
* @description: 重置选择框
* @return {*}
*/
const resetRect = async () => {
// 移除监听事件
let {amplify} = obj
document._params.amplify = amplify;
document._params.video = video;
document.removeEventListener("mouseup", up);
// 重置相关数据
amplify.rect.style.visibility = "hidden";
amplify.rect.style.width = "0px";
amplify.rect.style.height = "0px";
amplify.top = 0;
amplify.left = 0;
amplify.downX = 0;
amplify.downY = 0;
amplify.mouseX2 = 0;
amplify.mouseY2 = 0;
amplify.rect = null;
amplify.select = false;
amplify.rectInfo = {
videoWidth: 0,
videoHeight: 0,
rectWidth: 0,
rectHeight: 0,
rectCenterOffsetX: 0,
rectCenterOffsetY: 0,
};
amplify.showControl = true;
};
/**
* @description: 还原视频初始大小
* @param {*} amplify 对应的amplify对象
* @param {*} videoZoom 对应的id名称 videoMonitor_A
* @return {*}
*/
const rest = () => {
let { amplify } = obj;
amplify.videoZoomFlag = false;
amplify.bigVideoBig = false;
// 还原视频原始大小
video.style.width = "100%";
video.style.height = "100%";
video.style.top = 0;
video.style.left = 0;
// video.play();
};
// 放大
const handleVideo = async () => {
let {amplify} = obj
// 视频放大显示
if (
amplify.rectInfo.videoWidth / amplify.rectInfo.rectWidth <= 10 &&
amplify.videoZoomFlag
) {
// let videoZoomEle = document.getElementById(videoZoom);
// 放大倍数
let times = amplify.rectInfo.videoWidth / amplify.rectInfo.rectWidth;
/* 1、当前视频为放大后视频 */
if (amplify.bigVideoBig) {
// 视频放大后大小
video.style.width =
(
((video.offsetWidth * times) / amplify.rectInfo.videoWidth) *
100
).toFixed(2) + "%";
video.style.height =
(
((video.offsetHeight * times) / amplify.rectInfo.videoHeight) *
100
).toFixed(2) + "%";
// 移动放大后视频使框选区域显示在原播放窗口
video.style.top =
(
((((video.style.top.split("%")[0] / 100) *
amplify.rectInfo.videoHeight -
(amplify.rectInfo.rectCenterOffsetY -
amplify.rectInfo.rectHeight / 2)) *
times) /
amplify.rectInfo.videoHeight) *
100
).toFixed(2) + "%";
video.style.left =
(
((((video.style.left.split("%")[0] / 100) *
amplify.rectInfo.videoWidth -
(amplify.rectInfo.rectCenterOffsetX -
amplify.rectInfo.rectWidth / 2)) *
times) /
amplify.rectInfo.videoWidth) *
100
).toFixed(2) + "%";
} else {
/* 2、当前视频为正常大小视频 */
amplify.bigVideoBig = true;
// 放大后视频大小
video.style.width = 100 * times + "%";
video.style.height = 100 * times + "%";
// 移动放大后视频使框选区域显示在原播放窗口
video.style.top =
(
((-(
amplify.rectInfo.rectCenterOffsetY -
amplify.rectInfo.rectHeight / 2
) *
times) /
amplify.rectInfo.videoHeight) *
100
).toFixed(2) + "%";
video.style.left =
-(
(((amplify.rectInfo.rectCenterOffsetX -
amplify.rectInfo.rectWidth / 2) *
times) /
amplify.rectInfo.videoWidth) *
100
).toFixed(2) + "%";
}
} else {
// 显示默认视频大小
rest();
}
};
// 鼠标按下
selectVideo.addEventListener("mousedown", (event) => {
console.log(event, "鼠标按下");
video.pause();
let { amplify } = obj;
amplify.showControl = false; // 暂时不显示控制条
// 获取鼠标按下时的坐标位置
amplify.downX = event.clientX; //鼠标相对于浏览器有效区域x轴的位置
amplify.downY = event.clientY;
// 鼠标按下时才允许处理鼠标的移动事件
amplify.select = true;
// internalInstance.refs[rectArea][0]:获取“rectArea”节点
amplify.rect = moveSelected;
// 播放器窗口离浏览器窗口顶部距离
amplify.top = selectVideo.getBoundingClientRect().top;
// 播放器窗口离浏览器窗口左侧距离
amplify.left = selectVideo.getBoundingClientRect().left;
// 获取播放器窗口大小
amplify.rectInfo.videoHeight = selectVideo.offsetHeight;
amplify.rectInfo.videoWidth = selectVideo.offsetWidth;
// 添加鼠标抬起事件
document._params = { amplify, video }; // 传递监听事件所需参数
document.addEventListener("mouseup", up);
// event.preventDefault(); // 阻止默认行为, 不能阻止, 阻止后就不能清空数据了
event.stopPropagation(); // 阻止事件冒泡
});
// 鼠标移动
selectVideo.addEventListener("mousemove", (e) => {
// console.log(event, "鼠标移动");
let { amplify } = obj;
if (amplify.select) {
// 获取鼠标移动时的坐标位置
amplify.mouseX2 = e.clientX; //鼠标相对于浏览器有效区域x轴的位置
amplify.mouseY2 = e.clientY;
// A(左上) part
if (
amplify.mouseX2 < amplify.downX &&
amplify.mouseY2 < amplify.downY
) {
amplify.rect.style.left = amplify.mouseX2 - amplify.left + "px";
amplify.rect.style.top = amplify.mouseY2 - amplify.top + "px";
amplify.videoZoomFlag = false;
}
// B(右上) part
if (
amplify.mouseX2 > amplify.downX &&
amplify.mouseY2 < amplify.downY
) {
amplify.rect.style.left = amplify.downX - amplify.left + "px";
amplify.rect.style.top = amplify.mouseY2 - amplify.top + "px";
amplify.videoZoomFlag = false;
}
// C(左下) part
if (
amplify.mouseX2 < amplify.downX &&
amplify.mouseY2 > amplify.downY
) {
amplify.rect.style.left = amplify.mouseX2 - amplify.left + "px";
amplify.rect.style.top = amplify.downY - amplify.top + "px";
amplify.videoZoomFlag = false;
}
// D(右下) part
if (
amplify.mouseX2 > amplify.downX &&
amplify.mouseY2 > amplify.downY
) {
amplify.rect.style.left = amplify.downX - amplify.left + "px";
amplify.rect.style.top = amplify.downY - amplify.top + "px";
amplify.videoZoomFlag = true;
}
// 选择框大小
amplify.rect.style.width =
Math.abs(amplify.mouseX2 - amplify.downX) + "px";
amplify.rect.style.height =
Math.abs(amplify.mouseY2 - amplify.downY) + "px";
// 选择框显示
amplify.rect.style.visibility = "visible";
}
e.preventDefault(); // 阻止默认行为
e.stopPropagation(); // 阻止事件冒泡
});
// 鼠标松开
/**
* @description: 鼠标抬起
* @param {*} amplify 对应的amplify对象
* @param {*} video 对应的id名称 videoMonitor_A
* @return {*}
*/
const up = async (e) => {
// 获取监听事件传递的参数
let { amplify, video } = document._params;
amplify.showControl = true; // 选区完成后,显示控制条
//鼠标抬起后不允许处理鼠标移动事件
amplify.select = false;
if (amplify.rect.style.visibility !== "hidden") {
//获取选择框大小
amplify.rectInfo.rectWidth = Math.abs(
amplify.mouseX2 - amplify.downX
);
amplify.rectInfo.rectHeight = Math.abs(
amplify.mouseY2 - amplify.downY
);
//获取选择框中心坐标
amplify.rectInfo.rectCenterOffsetX =
parseInt(amplify.rect.style.left) + amplify.rectInfo.rectWidth / 2;
amplify.rectInfo.rectCenterOffsetY =
parseInt(amplify.rect.style.top) + amplify.rectInfo.rectHeight / 2;
//框选区域大小按视频播放窗口宽高比转换使框选部分放大后显示不失真:保持按播放宽高等比变化
let rectRate =
amplify.rectInfo.rectWidth / amplify.rectInfo.rectHeight;
let videoRate =
amplify.rectInfo.videoWidth / amplify.rectInfo.videoHeight;
// 情况一:框选宽高比小于播放窗口宽高比:使用播放窗口比率统一框选宽度
if (rectRate < videoRate) {
amplify.rectInfo.rectWidth =
amplify.rectInfo.rectHeight * videoRate;
// 框选部分在播放窗口左侧边缘的情况
if (
amplify.rectInfo.rectCenterOffsetX <
amplify.rectInfo.rectWidth / 2
) {
amplify.rectInfo.rectCenterOffsetX =
amplify.rectInfo.rectWidth / 2;
}
// 框选部分在播放窗口右侧边缘的情况
if (
amplify.rectInfo.rectCenterOffsetX +
amplify.rectInfo.rectWidth / 2 >
amplify.rectInfo.videoWidth
) {
amplify.rectInfo.rectCenterOffsetX =
amplify.rectInfo.videoWidth - amplify.rectInfo.rectWidth / 2;
}
// 情况二:框选宽高比大于等于播放窗口宽高比:使用播放窗口比率统一框选高度
} else {
amplify.rectInfo.rectHeight =
amplify.rectInfo.rectWidth / videoRate;
// 处理框选部分在播放窗口顶部边
if (
amplify.rectInfo.rectCenterOffsetY <
amplify.rectInfo.rectHeight / 2
) {
amplify.rectInfo.rectCenterOffsetY =
amplify.rectInfo.rectHeight / 2;
}
// 处理框选部分在播放窗口底部边
if (
amplify.rectInfo.rectCenterOffsetY +
amplify.rectInfo.rectHeight / 2 >
amplify.rectInfo.videoHeight
) {
amplify.rectInfo.rectCenterOffsetY =
amplify.rectInfo.videoHeight - amplify.rectInfo.rectHeight / 2;
}
}
// 处理视频
handleVideo();
}
//重置选择框
resetRect();
e.preventDefault(); // 阻止默认行为
e.stopPropagation(); // 阻止事件冒泡
};
// 鼠标离开拖拽选择区域
selectVideo.addEventListener("mouseleave", (event) => {
flag = false;
moveSelected.style.width = 0;
moveSelected.style.height = 0;
moveSelected.style.top = 0;
moveSelected.style.left = 0;
event.preventDefault(); // 阻止默认行为
event.stopPropagation(); // 阻止事件冒泡
});
</script>
</body>
</html>