当前位置: 首页 > news >正文

vue需求:实现签章/签字在页面上自由定位的功能(本质:元素在页面上的拖拽)

目录

第一章  效果展示

第二章  了解工具

2.1 draggable

2.1.1 了解draggable

2.1.2 draggable方法

2.1.3 利用例子理解方法

第三章 效果实现

3.1 实现思路

3.2 代码实现

3.2.1 涉及到的点

3.2.2 源代

第一章  效果展示

  • 效果描述:通过点击左边栏的签名和签章,使其在右边初步展示,然后再拖动确定他们的位置

第二章  了解工具

2.1 draggable

2.1.1 了解draggable

  • draggable 属性是 HTML5 新增的。
  • Internet Explorer 9+, Firefox, Opera, Chrome, 和 Safari 浏览器支持 draggable 属性,IE8以下不支持
  • draggable 属性规定元素是否可拖动
  • 用法:
<element draggable="true|false|auto">
  • 注意: 图片(<img>)和链接(<a>)不加这个属性,就可以拖拉,对于它们,为了防止拖拽,用到这个属性的时候,往往是将其设为false
  • 说明:
true规定元素是可拖动的。
false规定元素是不可拖动的。
auto使用浏览器的默认特性。

2.1.2 draggable方法

  • drag拖拽过程中,在被拖拽的节点上持续触发(相隔几百毫秒)。
  • dragstart用户拖拽开始时,在被拖拽的节点上触发,该事件的target属性是被拖拉的节点。通常在这个事件的监听函数中,指定拖拽的数据。(常用)
  • dragend拖拽结束时(释放鼠标键或按下 ESC 键)在被拖拽的节点上触发,该事件的target属性是被拖拉的节点。它与dragstart事件,在同一个节点上触发。不管拖拉是否跨窗口,或者中途被取消,dragend事件总是会触发的。(常用)
  • dragenter拖拽进入当前节点时,在当前节点上触发一次,该事件的target属性是当前节点。通常应该在这个事件的监听函数中,指定是否允许在当前节点放下(drop)拖拉的数据。如果当前节点没有该事件的监听函数,或者监听函数不执行任何操作,就意味着不允许在当前节点放下数据。在视觉上显示拖拉进入当前节点,也是在这个事件的监听函数中设置。
  • dragover拖拉到当前节点上方时,在当前节点上持续触发(相隔几百毫秒),该事件的target属性是当前节点。该事件与dragenter事件的区别是,dragenter事件在进入该节点时触发,然后只要没有离开这个节点,dragover事件会持续触发
  • dragleave拖拉操作离开当前节点范围时,在当前节点上触发,该事件的target属性是当前节点。如果要在视觉上显示拖拉离开操作当前节点,就在这个事件的监听函数中设置。
  • drop被拖拉的节点或选中的文本,释放到目标节点时,在目标节点上触发。注意,如果当前节点不允许drop,即使在该节点上方松开鼠标键,也不会触发该事件。如果用户按下 ESC 键,取消这个操作,也不会触发该事件。该事件的监听函数负责取出拖拉数据,并进行相关处理。

2.1.3 利用例子理解方法

<div class="back_box" ref="back_box"><divv-if="signShow"class="drag_box"draggable="true"@drag="drag($event)"@dragstart="dragstart($event)"@dragend="dragend($event)"@dragenter="dragenter($event)"@dragover="dragover($event)"@dragleave="dragleave($event)"@drop="drop($event)":style="`left:${elLeft}px;top:${elTop}px`">
</div>drag(e){console.log('drag', e)
},
// 拖拽开始事件
dragstart (e) {console.log('dragstart', e)
},
// 拖拽完成事件
dragend (e) {console.log('dragend', e)
},
dragenter (e) {console.log('dragenter', e)
},
dragover (e) {console.log('dragover', e)
},
dragleave (e) {console.log('dragleave', e)
},
  • 看效果

  • 看右边输出,很明显,小编开始拖拽时,dragstart函数调用,然后drag-> dragenter->dragover调用,这一过程是表示拖拽过程中进入了节点同时还在该节点上方的范围内,后面输出从drag->dragoverdrag->drag…的原因也是在拖拽的过程中,节点由原来的节点上方范围内到范围外之后只有drag触发,dragover不触发,最后松开鼠标,拖拽结束了,触发dragend
  •  至于为什么drop没有触发,这里请看文档的实例,如下。(小编理解是,该事件应该在存放的目标模板中使用,而不是自身)

HTML draggable 属性 | 菜鸟教程

  • event的参数(小编就不一一说明了,这里用到clientX和clientY计算偏移量的)

 

第三章 效果实现

3.1 实现思路

  • 三个元素:签名、签章已经模板
  • 页面布局,初步样式控制,小编的样式:(为了方便,小编模板用的图片-->大家用源代码时记得替换)

  •  点击左边的签名,右边模板出现对应的签名,签章同理,利用定位让签章与签名都在模板的左上角
  • 拖拽开始时记录一次最开始的位置
  • 拖拽结束鼠标松开时再记录一次位置
  • 利用两个位置的差计算偏移量
  • 最后再次利用定位top和left将签名和签章固定到模板上

3.2 代码实现

3.2.1 涉及到的点

  • 使用dragstart和dragend记录拖拽元素初始位置和结束位置
  • 利用宽高比例进行页面初始化(正常屏幕宽高1920*1080,根据需求初始化)
  • 了解一下
  1. clientX:当鼠标事件发生时(不管是onclick,还是omousemovenmouseover等),鼠标对于浏览器(这里说的是浏览器的有效区域)x抽的置
  2. clientY:当鼠标事件发生时,鼠标相对于浏览器(这里说的是浏览器的有效区域)y轴的位置;
  3. screenX:当鼠标事件发生时,鼠标相对于显示器屏幕x轴的位置;
  4. screenY:当鼠标事件发生时,鼠标相对于显示器屏幕y轴的位置;
  5. offsetX:当鼠标事件发生时,鼠标相对于事件源x轴的位置(这里的事件源是上一个有定位的父级标签)
  6. offsetY:当鼠标事件发生时,鼠标相对于事件源y轴的位置(这里的事件源是上一个有定位的父级标签)

3.2.2 源代码

<template><div class="page"><div class="left"><div class="title">签名</div><div class="img" @click="signShow = true"><img src="./img/sign.png" alt="" style="height: 50px; border: 1px solid #eee;"></div><div class="title">签章</div><div class="img" @click="sign2Show = true"><img src="./img/sign3.png" alt=""></div></div><div class="right"><div class="drag"><div class="back_box" ref="back_box"><divv-if="signShow"class="drag_box"draggable="true"@dragstart="dragstart($event)"@dragend="dragend($event)":style="`left:${elLeft}px;top:${elTop}px`"></div><divv-if="sign2Show"class="drag_box2"draggable="true"@dragstart="sign2dragstart($event)"@dragend="sign2dragend($event)":style="`left:${elLeft2}px;top:${elTop2}px`"></div></div></div></div></div>
</template><script>
export default {name: 'HelloWorld',data () {return {initWidth: 0, // 父元素的宽-自适应值initHeight: 0, // 父元素的高-自适应值startclientX: 0, // 元素拖拽前距离浏览器的X轴位置startclientY: 0, // 元素拖拽前距离浏览器的Y轴位置elLeft: 0, // 元素的左偏移量elTop: 0, // 元素的右偏移量,startclientX2: 0, // 元素拖拽前距离浏览器的X轴位置startclientY2: 0, // 元素拖拽前距离浏览器的Y轴位置elLeft2: 0, // 元素的左偏移量elTop2: 0, // 元素的右偏移量,signShow: false,sign2Show: false,}},components: {},methods: {// 页面初始化initBodySize () {this.initWidth = this.$refs.back_box.clientWidth // 拿到父元素宽this.initHeight = this.initWidth * (1080 / 1920) // 根据宽计算高实现自适应},// 拖拽开始事件dragstart (e) {this.startclientX = e.clientX // 记录拖拽元素初始位置this.startclientY = e.clientY},// 拖拽完成事件dragend (e) {let x = e.clientX - this.startclientX // 计算偏移量let y = e.clientY - this.startclientYthis.elLeft += x // 实现拖拽元素随偏移量移动this.elTop += y},// 拖拽开始事件sign2dragstart (e) {this.startclientX2 = e.clientX // 记录拖拽元素初始位置this.startclientY2 = e.clientY},// 拖拽完成事件sign2dragend (e) {let x = e.clientX - this.startclientX2 // 计算偏移量let y = e.clientY - this.startclientY2this.elLeft2 += x // 实现拖拽元素随偏移量移动this.elTop2 += y}},mounted () {this.initBodySize()}
}
</script><style lang="less" scoped>
.page{width: 100vw;height: 100vh;background-color: #fff;display: flex;justify-content: flex-start;.left{width: 20%;height: 100%;cursor: pointer;border-right: 1px solid #eee;.title{font-size: 14px;margin: 16px;}.img{margin: 16px 50px 16px 16px;img{height: 100px;}}}.right{width: 80%;position: relative;height: 100%;.back_box {background-image: url('./img/bg.png');background-size: 100% 100%;background-repeat: no-repeat;width: 70%;height: 60%;position: absolute;top: 0;right: 0;bottom: 0;left: 0;margin: auto;}.drag_box {width: 150px;height: 50px;background-image: url('./img/sign.png');background-size: 100% 100%;background-repeat: no-repeat;position: absolute;z-index: 10;}.drag_box2 {width: 150px;height: 150px;background-image: url('./img/sign2.png');background-size: 100% 100%;background-repeat: no-repeat;position: absolute;z-index: 10;}}
}
</style>

第四章 扩展 

  • 如果该需求大家也需要应用时,如果后端做pdf,前后端首先确定一致的模板
  • 前端需要做的是将签名、签章的位置向后端提供(注意前端传的位置必须的等比例的,如果前端模板被用户缩小窗口使用的,提供的位置就不准确了),需要将签名签章的拥有者向后端提供
  • 如果后端不自己拿签名签章的图片,还需要将其路径向后端提供如果图片的宽高用户可以手动控制,前端还需要对对图片的宽高进行处理,获取到宽高然后向后端提供——这里小编有两个方法:一个是通过鼠标滚轮对图片缩放从而控制图片大小(onwheel);另个一个是输入控制,小编后续的文章会谈到
  • 如果直接让前端生成pdf,看该文章或许会有帮助:

需求:前端生成一个模板并盖章的pdf文件(单个文件自动下载+多文件生成压缩包下载以及window.print()),一个pdf多个分页进行处理(保证图片、表、文字能完整展示,截断问题解决)_❆VE❆的博客-CSDN博客

相关文章:

vue需求:实现签章/签字在页面上自由定位的功能(本质:元素在页面上的拖拽)

目录 第一章 效果展示 第二章 了解工具 2.1 draggable 2.1.1 了解draggable 2.1.2 draggable方法 2.1.3 利用例子理解方法 第三章 效果实现 3.1 实现思路 3.2 代码实现 3.2.1 涉及到的点 3.2.2 源代 第一章 效果展示 效果描述&#xff1a;通过点击左边栏的签名和…...

【深度学习基础】Pytorch框架CV开发(1)基础铺垫

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…...

uniapp原生插件之安卓热敏打印机打印插件

插件介绍 安卓热敏打印机打印插件&#xff0c;自动授权&#xff0c;打印机连接监听&#xff0c;打印文本&#xff0c;条形码&#xff0c;二维码&#xff0c;切纸&#xff0c;打印机状态&#xff0c;打印结果查询等 插件地址 安卓热敏打印机打印插件 - DCloud 插件市场 超级…...

巴菲特:卖比亚迪有助于资金配置

巴菲特表示&#xff0c;未来可能会有更多银行倒闭&#xff0c;但储户不必担心&#xff0c;他警告说&#xff0c;陷入困境的银行股不是价值投资&#xff0c;因为即使政府采取行动保护储户&#xff0c;股东的权益也会受到损失。他称&#xff0c;将加大对日本综合商社的投资&#…...

香港服务器有哪些特点

香港服务器具有以下特点&#xff1a; 速度快&#xff1a;香港服务器地理位置优越&#xff0c;与内地服务器相比&#xff0c;网络延迟更低&#xff0c;访问速度更快。 稳定性高&#xff1a;香港服务器位于全球重要的金融中心&#xff0c;网络环境稳定&#xff0c;服务器稳定性高…...

Leetcode76最小覆盖子串

思路&#xff1a;滑动窗口思想 1. 滑动窗口是什么&#xff1a;用一个滑动窗口为覆盖目标子串的字符串 2.怎么移动窗口&#xff1a;当不满足覆盖时右指针移动扩大范围&#xff0c;当覆盖了就移动左指针缩减范围直到再次不覆盖 3. 怎么判断是否覆盖&#xff1a;这里使用两个哈…...

GD32 单片机 硬件I2C死锁解决方法

死锁的复现方式 在I2C恢复函数下个断点&#xff08;检测到I2C多次超时之后&#xff0c;应该能跳转到I2C恢复函数&#xff09;使用镊子&#xff0c;将SCL与SDA短接&#xff0c;很快就能看到程序停到恢复函数的断点上&#xff0c;此时再执行恢复函数&#xff0c;看能否正常走出&…...

SPSS两相关样本检验

前言&#xff1a; 本专栏参考教材为《SPSS22.0从入门到精通》&#xff0c;由于软件版本原因&#xff0c;部分内容有所改变&#xff0c;为适应软件版本的变化&#xff0c;特此创作此专栏便于大家学习。本专栏使用软件为&#xff1a;SPSS25.0 本专栏所有的数据文件请点击此链接下…...

【vscode远程开发】使用内网穿透实现在公网环境下远程访问

文章目录 前言1、安装OpenSSH2、vscode配置ssh3. 局域网测试连接远程服务器4. 公网远程连接4.1 ubuntu安装cpolar内网穿透4.2 创建隧道映射4.3 测试公网远程连接 5. 配置固定TCP端口地址5.1 保留一个固定TCP端口地址5.2 配置固定TCP端口地址5.3 测试固定公网地址远程 前言 远程…...

KaiwuDB 内核解析 - SQL 查询的生命周期

一、概述 KaiwuDB 内核解析系列共分上下两部分&#xff0c;本文是该系列的第一部分&#xff0c;主要涵盖了网络协议到 SQL 执行器&#xff0c;解释 KaiwuDB 如何执行 SQL 查询&#xff0c;包括系统各个组件的执行路径&#xff08;网络协议、SQL 会话管理、解析器、执行计划及优…...

2023.11.03 homework

小学4年级数学 1 2 3 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 19…...

ssm在线互助答疑系统-计算机毕设 附源码 20862

ssm在线互助答疑系统 摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时代。在现实运用中&#…...

MySQL中如何书写update避免锁表

1. 什么是MySQL锁表&#xff1f; MySQL锁表是指在对某个数据表进行读写操作时&#xff0c;为了保证数据的一致性和完整性&#xff0c;系统会对该数据表进行锁定&#xff0c;防止其他用户对该表进行操作。 2. 为什么会出现锁表&#xff1f; 当多个用户同时对同一个数据表进行…...

Mysql库操作

一&#xff1a;库的操作 1&#xff1a;创建数据库 mysql> create database test1; Query OK, 1 row affected (0.00 sec)mysql> create database test2 charsetutf8;create database test2 character utf8;Query OK, 1 row affected (0.00 sec)mysql> create databa…...

C#中LINQtoSQL只能在.NetFramework下使用,不能在.net 下使用

目录 一、在net7.0下无法实现LINQtoSQL 1.VS上建立数据库连接 2.VS上创建LINQtoSQL 二、在.NetFramework4.8下成功实现LINQtoSQL 1.VS上建立数据库连接 2.VS上创建LINQtoSQL 三、结论 四、理由 本文是个人观点&#xff0c;因为我百般努力在.net7.0下无法实现LINQtoSQL的…...

Nacos 的底层实现原理 注册中心的两种调用方式

目录 1. Nacos 的底层实现原理 1.1 配置中心自动刷新实现原理 1.2 注册中心底层实现原理 2. Nacos 注册中心的两种调用方式 2.1 RestTemplate Spring Cloud LoadBalancer 的调用方式 2.2 使用 OpenFeign Spring Cloud LoadBalancer 1. Nacos 的底层实现原理 1.1 配置中心…...

视频编码格式和文件格式(多媒体容器格式)的关系

视频编码格式和文件格式是两个不同的概念。 视频编码格式指的是将视频信号转换为数字信号时所采用的压缩算法标准。它决定了如何将原始视频数据压缩为较小的文件大小&#xff0c;以及如何解码回原始视频数据。目前常见的视频编码格式有 H.264、H.265、VP9 等。 文件格式则是指…...

RHCSA --- 第二天

一、查看IP地址 [rootlocalhost ~] ip ad 对应四张网卡 第一张&#xff1a;环回网卡&#xff08;用于测试&#xff09; 第二张&#xff08;主要&#xff09;&#xff1a;以太网网卡&#xff08;ens160&#xff09; 2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP>…...

作为一个初学者,入门大模型其实没那么难

在生成式 AI 盛行的当下&#xff0c;你是否被这种技术所折服&#xff0c;例如输入一段简简单单的文字&#xff0c;转眼之间&#xff0c;一幅精美的图片&#xff0c;又或者是文笔流畅的文字就展现在你的面前。 相信很多人有这种想法&#xff0c;认为生成式 AI 深不可测&#xf…...

【QT】基本的绘图操作和高级绘图

基本绘图 新建项目 重新绘图事件 画基本图形 #include "widget.h" #include "ui_widget.h" #include <QPainter>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }/…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 &#x1f4dd; 在上一篇文章中&#xff0c;我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源&#xff0c;方便后续将资源打包到一个可执行文件中。 2.embed介绍 &#x1f3af; Go 1.16 引入了革命性的 embed 包&#xff0c;彻底改变了静态资源管理的…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...

华为OD机试-最短木板长度-二分法(A卷,100分)

此题是一个最大化最小值的典型例题&#xff0c; 因为搜索范围是有界的&#xff0c;上界最大木板长度补充的全部木料长度&#xff0c;下界最小木板长度&#xff1b; 即left0,right10^6; 我们可以设置一个候选值x(mid)&#xff0c;将木板的长度全部都补充到x&#xff0c;如果成功…...