效果图

  • 国际惯例一楼放图,满足需求往下看。

dom绑定鼠标事件

<template><div class="video-box" v-boxSelect><video ref="VIDEO" class="w-1/1 h-1/1" controls autoplay :src="url"> </video></div>
</template>
<style lang="less" scoped>.video-box {position: relative;overflow: hidden;width: 100%;height: 100%;}
</style>
  • 初始化挂载鼠标按下事件
const boxSelectDirective: Directive = {mounted,unmounted,
};
const mounted = (el: Element, binding: DirectiveBinding<any>) => {on(el, 'mousedown', down);
};
function down(this: HTMLElement, e: MouseEvent) {domX = this.getBoundingClientRect().x;domY = this.getBoundingClientRect().y;startX = e.clientX - domX;startY = e.clientY - domY;divDom = document.createElement('div');divDom.className = 'l_screenshot';divDom.style.top = startY + 'px';divDom.style.left = startX + 'px';this.appendChild(divDom);
}

创建dom元素,并且插入到当前dom的子节点中。插入节点设置属性

 .l_screenshot {width: 1px;height: 1px;border: 1px solid red;position: absolute;z-index: 99;}

按下鼠标事件里挂载鼠标移动以及鼠标抬起事件。注意这里鼠标按下事件在当前dom下监听,但是鼠标抬起要在整个document中监听。

 on(document, 'mouseup', mouseup.bind(this));on(this, 'mousemove', throttle(mousemove.bind(this), 30));
  • 鼠标移动
function mousemove(this: HTMLElement, e: MouseEvent) {e.preventDefault();if (divDom) {const moveX = e.clientX - domX! - startX!;const moveY = e.clientY - domY! - startY!;if (moveX > 0) {divDom.style.width = moveX + 'px';divDom.style.left = startX + 'px';divDom.style.right = '';} else {divDom.style.width = -moveX + 'px';divDom.style.right = this.getBoundingClientRect().width - startX! + 'px';divDom.style.left = '';}if (moveY > 0) {divDom.style.height = moveY + 'px';divDom.style.top = startY + 'px';divDom.style.bottom = '';} else {divDom.style.height = -moveY + 'px';divDom.style.top = '';divDom.style.bottom = this.getBoundingClientRect().height - startY! + 'px';}}
}

鼠标移动时计算当前鼠标位置与初始位置的距离,x为正时width为正且设置dom的style属性为left。当x为负数时,width取正直并且dom的style属性left设置为空切设置right属性。

  • 鼠标抬起
function mouseup(this: HTMLElement) {if (divDom) {off(this, 'mousemove', mousemove);off(document, 'mouseup', mouseup);fn &&fn({key,startX,startY,});destroy();}
}
function destroy() {document.querySelectorAll('.l_screenshot').forEach((i) => i.remove());divDom = null;startX = null;startY = null;domX = null;domY = null;
}

整个事件结束,清除副作用。

  • 完整代码
/*** Global boxSelection directive* Used for fine-grained control of component permissions* @Example v-boxSelection*/
import { on, off } from '/@/utils/domUtils';
import { throttle } from '/@/utils';
import type { App, Directive, DirectiveBinding } from 'vue';
let divDom: HTMLElement | null,startX: number | null,startY: number | null,domX: number | null,domY: number | null,fn: Function | null,key: number | string | null;
function down(this: HTMLElement, e: MouseEvent) {domX = this.getBoundingClientRect().x;domY = this.getBoundingClientRect().y;startX = e.clientX - domX;startY = e.clientY - domY;divDom = document.createElement('div');divDom.className = 'l_screenshot';divDom.style.top = startY + 'px';divDom.style.left = startX + 'px';this.appendChild(divDom);on(document, 'mouseup', mouseup.bind(this));on(this, 'mousemove', throttle(mousemove.bind(this), 30));
}
function mousemove(this: HTMLElement, e: MouseEvent) {e.preventDefault();if (divDom) {const moveX = e.clientX - domX! - startX!;const moveY = e.clientY - domY! - startY!;if (moveX > 0) {divDom.style.width = moveX + 'px';divDom.style.left = startX + 'px';divDom.style.right = '';} else {divDom.style.width = -moveX + 'px';divDom.style.right = this.getBoundingClientRect().width - startX! + 'px';divDom.style.left = '';}if (moveY > 0) {divDom.style.height = moveY + 'px';divDom.style.top = startY + 'px';divDom.style.bottom = '';} else {divDom.style.height = -moveY + 'px';divDom.style.top = '';divDom.style.bottom = this.getBoundingClientRect().height - startY! + 'px';}}
}
function mouseup(this: HTMLElement) {if (divDom) {off(this, 'mousemove', mousemove);off(document, 'mouseup', mouseup);fn &&fn({key,startX,startY,});destroy();}
}
const mounted = (el: Element, binding: DirectiveBinding<any>) => {fn = binding.value[1];key = binding.value[0];on(el, 'mousedown', down);
};
const unmounted = (el: Element) => {off(el, 'mousedown', down);fn = null;key = null;
};
function destroy() {document.querySelectorAll('.l_screenshot').forEach((i) => i.remove());divDom = null;startX = null;startY = null;domX = null;domY = null;
}
const boxSelectDirective: Directive = {mounted,unmounted,
};export function setupBoxSelectDirective(app: App) {app.directive('boxSelect', boxSelectDirective);
}export default boxSelectDirective;
  • 调用
 <div class="video-box" v-boxSelect="['vedioId', completed]"><video ref="VIDEO" class="w-1/1 h-1/1" controls autoplay :src="url"> </video></div><script>function completed(obj) {console.log(obj);}</script>

Directive鼠标拉选框,视频(监控)鼠标拖动聚焦相关推荐

  1. Element UI中el-calendar日历的使用及样式修改(年月可下拉选框选择)

    项目场景: 以日历形式展现当前页面.其中,年月可进行下拉选择,默认选中当天日期,用户可以自由点选日期,被选中后日期以紫色显示,鼠标在日历上移动时,日期显示出橙色.有数据的日期显示出灰色. 实现思路:删 ...

  2. Ajax异步配合数据字典完成下拉选框

    Ajax异步配合数据字典完成下拉选框 在一个web项目中,往往有许多下拉选框,其中下拉选框必须含有特定的内容,而如果在jsp或者html页面中写死的话就很难修改,也不能动态获取到更新的数据,所以要使用 ...

  3. easyExcel导出某列是固定下拉选框的excel模板

    easyexcel导出固定下拉选框的模板,项目中遇到的,记录一下. 1.示例 如图,第四列的值是下拉选框,是服务器端根据真实数据动态生成的. 2.实现方案 2.1 依赖 <dependency& ...

  4. html 表格,列表,表单,select和下拉选框,textarea多行文本域,label关联控件,表单,浮动框架,结构化标签

    1. 表格 表格的语法 (1) table标签: 表示表格的开始和结束.表格的所有内容都需要写在这一对标签里 (2) tr标签: 表示表格中的一行 table row (3) td标签:要写在tr中, ...

  5. (vue)提示Tooltip/el-popover在下拉选框option中用法及样式修改

    (vue)提示Tooltip/el-popover在下拉选框option中用法及样式修改 iview效果 Eleement-ui效果 代码 <Optionv-for="(item, i ...

  6. 好用的下拉选框(单选,多选,全选,清空和反选,及个种样式)----个人钟爱

    下拉选框 如需样例和具体效果,请点击下面的连接. 好用的下拉选框(单选,多选,全选,清空和反选,及个种样式) 附件一:layui应用formselect layui.config({base: './ ...

  7. Element UI中el-calendar日历的年月快捷选择(可下拉选框选择)

    需求: 以日历形式展现当前页面.其中,年月可进行下拉选择,默认选中当月,用户可以自由点选日期 实现思路:右上角年月元素隐藏掉,写一个下拉选框,通过css定位到正确位置,通过vue计算属性进行数据绑定 ...

  8. winform中TreeView控件复选框联动时鼠标点击过快导致的显示不正确的问题

    今天我在试着做一个C#树形视图(TreeView)控件,要求在每个节点前面添加一个可用于打勾的复选框,并要求复选框有上下级联动的效果.现在在网上能查到挺多满足这类功能的代码,原本我也以为这是一件挺简单 ...

  9. C# - 解决TreeView控件复选框联动时鼠标点击过快导致的显示不正确的问题

    2019独角兽企业重金招聘Python工程师标准>>> 今天我在试着做一个C#树形视图(TreeView)控件,要求在每个节点前面添加一个可用于打勾的复选框,并要求复选框有上下级联动 ...

最新文章

  1. 多解决些问题,少谈些框架和流程
  2. Docker Review - Docker 概念 入门篇
  3. 数学建模——K-means聚类模型Python代码
  4. WiFiDemon – iOS WiFi RCE 0-Day漏洞利用
  5. 使用fullPage做的大图片全屏滚动
  6. 「软件项目管理」成本估算模型——Walston-Felix模型和COCOMO Ⅱ模型
  7. java集成微信扫码登录
  8. 39岁java程序员,失业中,看不到希望,很迷茫,路在何方?
  9. 动画插件--WOWJS
  10. 微信小程序获取年月日周及早上、中午、晚上
  11. (原创)[联觉][类比推理的应用]震惊!声音也有温度和冷暖?什么是冷声和暖声?无处不在的联觉,色彩、声音的频率与温度之间的通感,色彩和声音的冷暖(类比冷色和暖色)
  12. Python 爬取朋友圈最新方法!!(文末赠书)
  13. 计算机无法进入bios模式,win7进入bios设置界面_win7无法进入bios设置解决办法
  14. Ardunio开发实例-ENC28J60以太网模块实现Web服务器
  15. Nyquist-Shannon采样定理的理解
  16. 为什么说冯诺依曼结构是现代计算机的基础,为什么现代计算机被称为冯·诺依曼结构计算机??...
  17. 阿里云配置小程序证书 https总结
  18. node.js的前世今生(特色篇)
  19. 小飞鱼通达二开 移动端接口显示“无办理权限”问题的处理(图文)
  20. 挖矿病毒 qW3xT.2 最终解决方案

热门文章

  1. phpcms V9 整合 Discuz! X2 标准教程
  2. 帝国CMS与Ucenter同步通信,会员整合
  3. 台积电和三星都变脸了,美国图谋失败,外媒:拜登心都碎了
  4. 电脑不用,电脑不用时需要关机吗
  5. 针对虚幻3引擎渲染底层的效率优化
  6. 技工职称考试计算机部分,2017职称计算机考试Dreamweaver练习试题及答案
  7. [tyvj2054] 四叶草魔杖 (最小生成树 状压dp)
  8. 【C语言】对拍【保姆级教程】
  9. mysql 创建外键约束
  10. 精益生产管理如何让全体员工养成消除浪费和持续改进意识?