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

本文主要是介绍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需求:实现签章/签字在页面上自由定位的功能(本质:元素在页面上的拖拽)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/345139

相关文章

使用Redis快速实现共享Session登录的详细步骤

《使用Redis快速实现共享Session登录的详细步骤》在Web开发中,Session通常用于存储用户的会话信息,允许用户在多个页面之间保持登录状态,Redis是一个开源的高性能键值数据库,广泛用于... 目录前言实现原理:步骤:使用Redis实现共享Session登录1. 引入Redis依赖2. 配置R

SpringBoot实现RSA+AES自动接口解密的实战指南

《SpringBoot实现RSA+AES自动接口解密的实战指南》在当今数据泄露频发的网络环境中,接口安全已成为开发者不可忽视的核心议题,RSA+AES混合加密方案因其安全性高、性能优越而被广泛采用,本... 目录一、项目依赖与环境准备1.1 Maven依赖配置1.2 密钥生成与配置二、加密工具类实现2.1

在Java中实现线程之间的数据共享的几种方式总结

《在Java中实现线程之间的数据共享的几种方式总结》在Java中实现线程间数据共享是并发编程的核心需求,但需要谨慎处理同步问题以避免竞态条件,本文通过代码示例给大家介绍了几种主要实现方式及其最佳实践,... 目录1. 共享变量与同步机制2. 轻量级通信机制3. 线程安全容器4. 线程局部变量(ThreadL

把Python列表中的元素移动到开头的三种方法

《把Python列表中的元素移动到开头的三种方法》在Python编程中,我们经常需要对列表(list)进行操作,有时,我们希望将列表中的某个元素移动到最前面,使其成为第一项,本文给大家介绍了把Pyth... 目录一、查找删除插入法1. 找到元素的索引2. 移除元素3. 插入到列表开头二、使用列表切片(Lis

python使用Akshare与Streamlit实现股票估值分析教程(图文代码)

《python使用Akshare与Streamlit实现股票估值分析教程(图文代码)》入职测试中的一道题,要求:从Akshare下载某一个股票近十年的财务报表包括,资产负债表,利润表,现金流量表,保存... 目录一、前言二、核心知识点梳理1、Akshare数据获取2、Pandas数据处理3、Matplotl

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连