技术栈:Vue3.2 + TS
/1.肯定不能单纯的采用px放大,这样会出现视频放大的时候位置发生变动
/2.采用scale放大,这样每次放大都是视频的中心点
/1.当鼠标按下和视频已经放大之后,才允许用户拖动
/2.同时需要对视频拖动的范围作出限制
/3.按钮抬起的时候,需要把拖动取消掉,同时拖动限制离开范围也需要把按钮给取消掉
//页面结构
//给外层div绑定mouseleave,给视频绑定鼠标抬起,按下,移动相关事件,同时视频放大之后,绑定动态的class
<div class="videoBox" @mouseleave="endDrag">
<video
ref="videoRef"
id="customVideo"
class="video-js vjs-big-play-centered"
@mouseup="endDrag"
@mousedown="dragging"
@mousemove="handleDrag"
:class="{'videoPoint': scale > 1}"
:style="{ width: '100%', height: '100%' }">
</video>
</div>
//点击事件
//点击事件绑定一个就可以,同时传递不同的参数,来进行控制
<a-tooltip content="放大">
<a-button :style="{ color: 'red' }" @click="scaleUp(1)">
放大
</a-button>
</a-tooltip>
<a-tooltip content="缩小">
<a-button :style="{ color: 'red' }" @click="scaleUp(-1)">
缩小
</a-button>
</a-tooltip>
<a-tooltip content="还原">
<a-button :style="{ color: 'red' }" @click="scaleUp(0)">
还原
</a-button>
</a-tooltip>
//业务逻辑实现
// 1.视频放大缩小逻辑实现
// 视频放大,缩小,还原
const scale = ref(1) //控制视频放大缩小倍数
const videoRef = ref(null)//定义ref,拿到video标签相关的属性
const scaleUp = (flag) => {
// 根据flag的值,对视频进行放大缩小和还原的处理
switch (flag) {
case 1:
if (scale.value.toFixed(2) >= 2.5) {//js的精度误差,所以加了一个toFixed保留两位小数
return
}
scale.value += 0.1
videoRef.value.style.transform = `scale(${scale.value})`;
break;
case -1:
if (scale.value.toFixed(2) <= 0.1) {
return
}
scale.value -= 0.1
videoRef.value.style.transform = `scale(${scale.value})`;
break;
default:
resetPosition()
}
}
//还原:还原他的缩放倍数,还原拖动位置
const resetPosition = () => {
videoRef.value.style.transform = `scale(1)`;
scale.value = 1
videoPosition.x = 0;
videoPosition.y = 0;
videoRef.value.style.left = '0px';
videoRef.value.style.top = '0px';
}
2.视频拖动
这一块是比较困难的,需要把详细的思路理清楚
//定义鼠标的起始点击位置
const dragStartX = ref(0)
const dragStartY = ref(0)
//控制鼠标是否按下
const isClick = ref(false)
//控制视频位置的变化
const videoPosition = reactive({
x:0,
y:0
})
// 判断是否可以拖动 满足放大和按下,才可拖动,使用计算属性控制
const isDragging = computed(() => {
return scale.value > 1 && isClick.value ? true :false
});
//鼠标按下
const dragging = (e) => {
isClick.value = true
dragStartX.value = e.clientX - videoPosition.x;
dragStartY.value = e.clientY - videoPosition.y;
window.addEventListener('mouseup', endDrag);
}
let containerRect = null
const handleDrag = (e) => {
if (isClick.value) {
const {w,h} = getVideoSize()
videoPosition.x = e.clientX - dragStartX.value;
videoPosition.y = e.clientY - dragStartY.value;
// 限制取极值
videoPosition.x = Math.min(Math.max(-w, videoPosition.x), w);
videoPosition.y = Math.min(Math.max(-h, videoPosition.y), h);
}
// 满足点击和放大,才进行拖动
if (isDragging.value) {
videoRef.value.style.left = `${videoPosition.x}px`;
videoRef.value.style.top = `${videoPosition.y}px`;
}
}
const getVideoSize = () => {
containerRect = videoRef.value.getBoundingClientRect()
const { width, height } = containerRect
const w = width / 3
const h = height / 2
console.log(width);
return {w,h}
}
//取消拖动
const endDrag = () => {
isClick.value = false
window.removeEventListener('mouseup', endDrag);
};