目录

<element draggable="true|false|auto">
| true | 规定元素是可拖动的。 |
| false | 规定元素是不可拖动的。 |
| auto | 使用浏览器的默认特性。 |
- class="back_box" ref="back_box">
- <div
- v-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->dragover到drag->drag…的原因也是在拖拽的过程中,节点由原来的节点上方范围内到范围外之后只有drag触发,dragover不触发,最后松开鼠标,拖拽结束了,触发dragend
- 至于为什么drop没有触发,这里请看文档的实例,如下。(小编理解是,该事件应该在存放的目标模板中使用,而不是自身)
- event的参数(小编就不一一说明了,这里用到clientX和clientY计算偏移量的)

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

- 点击左边的签名,右边模板出现对应的签名,签章同理,利用定位让签章与签名都在模板的左上角
- 拖拽开始时记录一次最开始的位置
- 拖拽结束鼠标松开时再记录一次位置
- 利用两个位置的差计算偏移量
- 最后再次利用定位top和left将签名和签章固定到模板上
3.2 代码实现
3.2.1 涉及到的点
- 使用dragstart和dragend记录拖拽元素初始位置和结束位置
- 利用宽高比例进行页面初始化(正常屏幕宽高1920*1080,根据需求初始化)
- 了解一下
- clientX:当鼠标事件发生时(不管是onclick,还是omousemovenmouseover等),鼠标对于浏览器(这里说的是浏览器的有效区域)x抽的置
- clientY:当鼠标事件发生时,鼠标相对于浏览器(这里说的是浏览器的有效区域)y轴的位置;
- screenX:当鼠标事件发生时,鼠标相对于显示器屏幕x轴的位置;
- screenY:当鼠标事件发生时,鼠标相对于显示器屏幕y轴的位置;
- offsetX:当鼠标事件发生时,鼠标相对于事件源x轴的位置(这里的事件源是上一个有定位的父级标签)
- offsetY:当鼠标事件发生时,鼠标相对于事件源y轴的位置(这里的事件源是上一个有定位的父级标签)
3.2.2 源代码
- <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">
- <div
- v-if="signShow"
- class="drag_box"
- draggable="true"
- @dragstart="dragstart($event)"
- @dragend="dragend($event)"
- :style="`left:${elLeft}px;top:${elTop}px`"
- >
- div>
- <div
- v-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.startclientY
- this.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.startclientY2
- this.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,看该文章或许会有帮助: