vue2 + Lodop 制作可视化设计页面 实现打印设计功能(一)

news2025/2/21 21:49:51

前言:

        此功能的来源来自于当时需要制作一个便于客户操作的打印设计功能,然后就有了这个项目。这个帖子主要是用于分享与谈论,相互学习。

目标:

  1. 能在vue页面中拖拽组件
  2. 支持批量操作拖动
  3. 通过拖拽组件列表里的组件到page进行添加
  4. 实现多种组件,如文本,图片,表格,网格等
  5. 便于扩展组件
  6. 页面中的单位统一,实现所见即所得
  7. 等等

当全部功能整理完毕后,会把此demo开源

目前效果:

设计

设计页面

预览

预览图片

实现:

组件在页面中的显示与拖拽移动位置

显示主要是使用了在page这个div上相对定位(position: relative;),里面的组件使用绝对定位(position: absolute;)使用top和left来绑定x坐标与y坐标即可。

这里使用了vue中的component标签来v-for动态生成组件,这个具体的后面会说明

<component
          :is="moduleData.type"
          :com="moduleData"
          :class="[moduleData.isSelect && moduleData.config.isChildren? 'active':'']"
          :data-title="moduleData.type"
          :key="moduleData.uuid"
          :val="moduleData"
          class="layer"
        ></component>

拖拽移动主要使用了@mousedown获取点击的元素是否是组件,(这个我就是通过在组件html原始上绑定data-xxx属性来判断的)如果是组件就给组件元素或者在页面上绑定一个mousemove事件(这里选择的是在页面上绑定),当鼠标mouseup时移除事件即可

关键代码:

    handleMouseDown(e){

              // 如果没有选中组件 在画布上点击时需要调用 e.preventDefault() 防止触发 drop 事件
              if(recursionGetSelectCom(this.$vptd.state.page.tempItems).length===0)
                e.preventDefault()


              var target = this.selectTarget(e.target)
              //判断是不是选中了组件,如果是组件不向下执行
              if (target) {
                e.stopPropagation()
                e.preventDefault()
                var uuid = target.getAttribute('data-uuid')
                // 设置选中元素
                this.$vptd.commit('select', {
                  uuid: uuid,
                })
                // 绑定移动事件:除背景图以外的元件才能移动
                let element = recursionGetSelectCom(this.$vptd.state.page.tempItems).filter(i=>i.uuid===uuid)

                if (element.length > 0 && element[0].config.dragable) {
                  //绑定选中com事件
                  this.initmovement(e,element[0]) // 参见 mixins
                  return
                }
              }


              this.hideArea()
              // 获取编辑器的位移信息,每次点击时都需要获取一次。主要是为了方便开发时调试用。
              const rectInfo = this.$refs.edit.getBoundingClientRect()
              this.editorX = rectInfo.x
              this.editorY = rectInfo.y

              const startX = e.clientX
              const startY = e.clientY
              this.start.x = startX - this.editorX
              this.start.y = startY - this.editorY
              // 展示选中区域
              this.isShowArea = true

              const move = (moveEvent) => {
                this.width = Math.abs(moveEvent.clientX - startX)
                this.height = Math.abs(moveEvent.clientY - startY)
                if (moveEvent.clientX < startX) {
                  this.start.x = moveEvent.clientX - this.editorX
                }

                if (moveEvent.clientY < startY) {
                  this.start.y = moveEvent.clientY - this.editorY
                }
              }

              const up = (e) => {
                document.removeEventListener('mousemove', move)
                document.removeEventListener('mouseup', up)

                if (e.clientX === startX && e.clientY === startY) {
                  console.log("鼠标未移动,取消选中")
                  this.$vptd.commit('setSelectElement', [])
                }else {
                  //获取选中的组件然后给选中组件中的isSelect值进行改变
                  console.log("鼠标框选")
                  this.$vptd.commit('setSelectElement', this.getSelectArea())
                }

                this.hideArea()
              }

              document.addEventListener('mousemove', move)
              document.addEventListener('mouseup', up)
            },

通过拖拽组件列表里的组件到page进行添加

其中主要是用了@dragstart与@drop与@dragover方法

组件列表:html

<div class="item"
           :key="index"
           :draggable="true"
           @dragstart="dragStart($event, index)"
           @click="(e) => {addTempItem(e,item)}">
        <span :style="{fontWeight:item.config.isEdit? 'bold':'',fontStyle:item.config.isEdit? '':'italic'}">{{ item.title }}</span>
      </div>

组件列表:js

  methods: {
    // 添加组件
    addTempItem (e, item) {
      this.$vptd.dispatch('addTempItem', item)
    },
    dragStart (ev, index) {
      ev.dataTransfer.setData('index', index)
    }
  },

设计页面html

<div
        :style="{
          height: '100px',
          width: '100px',
    
          }"
        ref="edit"
        class="screen"
        @dragover.prevent="dragOver"
        @drop="dropToAddCom($event)"
        @mousedown="handleMouseDown"
      >
</div>

设计页面js

 dragOver(ev){
              ev.preventDefault()
            },
dropToAddCom(ev){
              ev.preventDefault()
              const rest = this.$refs.edit.getBoundingClientRect();
              this.$vptd.dispatch('addTempItemByIndex',
                { index : ev.dataTransfer.getData('index'),
                          x: Math.round(ev.clientX-rest.x),
                          y :Math.round(ev.clientY-rest.y)
                        })
            },

以上就是组件拖拽添加与在page上的拖拽设计,以上代码都不可直接使用,因为代码不全,仅仅能提供参考,或者自行修改也可

后续的更新等我忙完这段时间了补上。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1848088.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

四,SSM整合-前后端分离(实现分页+前后端校验)

分页与校验 实现功能07-分页显示列表需求分析/图解思路分析代码实现完成测试 实现功能08-带条件查询分页显示列表需求分析/图解思路分析代码实现 实现功能09-添加家居表单前端校验需求分析/图解思路分析代码实现 实现功能10-添加家居表单后端校验需求分析/图解思路分析代码实现…

普通变频器位置闭环控制(S7-1200PLC工艺对象模拟量轴)

1、S7-1200PLC控制V90总线伺服通过工艺对象实现定位控制 S7-1200PLC和V90总线伺服通过工艺对象实现定位控制(标准报文3应用)_1200报文3控制v90-CSDN博客文章浏览阅读182次。V90伺服驱动器调试软件SINAMICS V-ASSISTANT Commissioning tool下载地址如下:西门子官网选型|资料CS…

【Kafka】Kafka Broker工作流程、节点服役与退役、副本、文件存储、高效读写数据-08

【Kafka】Kafka Broker工作流程、节点服役与退役、副本、文件存储、高效读写数据 1. Kafka Broker 工作流程1.1 Zookeeper 存储的 Kafka 信息1.2 Kafka Broker总体工作流程1.2.1 Controller介绍 1.3 Broker 重要参数 2. 节点服役与退役3. Kafka副本 1. Kafka Broker 工作流程 …

Matplotlib绘图9种经典风格,你喜欢哪种?

学过Python的小伙伴都会知道&#xff0c;Matplotlib是Python生态最好用的可视化工具库&#xff0c;吹爆也不为过。&#x1f44d; Matplotlib作为高度定制化的绘图工具&#xff0c;只要你使用Python编程便可完美绘制二维统计图表、三维图表、动态图表、交互图表&#xff0c;甚至…

找不到d3dx9_43.dll无法继续执行代码的几种解决方法

在工作或生活使用电脑都会遇到丢失dll文件应用无法启动的情况&#xff0c;比如你安装完一款你最喜欢的游戏在启动的时候提示系统缺少d3dx9_39.dll、d3dx9_40.dll、d3dx9_41.dll、d3dx9_42.dll、d3dx9_43.dll、xinput1_3.dll 文件而无法正常游戏&#xff0c;或你在工作的时候安装…

vue:vue2与vue3如何全局注册公共组件(包括涉及到的相关方法函数的讲解)

目录 第一章 vue2全局注册公共组件 1.1 方法一&#xff1a;逐个注册 1.2 方法二&#xff1a;批量注册 1.2.1 require.context()方法解释 第二章 vue3全局注册公共组件 1.1 方法一&#xff1a;逐个注册 1.2 方法二&#xff1a;批量注册 第一章 vue2全局注册公共组件 Vue…

Golang并发控制的三种方案

Channel Channel是Go在语言层面提供的一种协程间的通信方式&#xff0c;我们可以通过在协程中向管道写入数据和在待等待的协程中读取对应协程的次数来实现并发控制。 func main() {intChan : make(chan int, 5)waitCount : 5for i : 0; i < waitCount; i {go func() {intC…

【计算机网络体系结构】计算机网络体系结构实验-FTP实验

1. 2. 3. wireshark 第一行&#xff1a;帧Frame 545&#xff1a;要发送的数据块&#xff0c;所抓帧的序号为545&#xff0c;捕获字节数等于传送字节数&#xff1a;451字节第二行&#xff1a;源Mac地址为a4:bb:6d:6e:28:9a&#xff1b;目标Mac地址为24:00:fa:e4:df:d8第三行&…

安卓逆向案例——X酷APP逆向分析

X酷APP逆向分析 这里介绍一下两种不同的挂载证书的方法。 chls.pro/ssl无法在浏览器中下载证书是什么原因解决方法&#xff1a; 法一 1. 挂载系统分区为读写 使用正确的挂载点来挂载系统分区为读写&#xff1a; su mount -o remount,rw /dev/uijISjR/.magisk/block/syste…

Spring Boot连接Redis集群

1、问题写在前面 1.1、问题描述&#xff1a;Redis集群节点地址发现失败 Unable to connect to [172.17.0.4:7303]: connection timed out: /172.17.0.4:7303 1.2、解决方案&#xff1a; redis.conf 中添加配置 cluster-announce-ip 192.168.56.11 1.3、方案出处&#xff1a;…

何在 Vue3 中使用 Cytoscape.js 创建交互式网络图

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 Cytoscape.js集成到Vue应用中 应用场景介绍 Cytoscape.js是一个用于可视化复杂网络数据的JavaScript库。它提供了丰富的功能&#xff0c;包括节点和边的创建、布局算法、交互式操作等。本文将介绍如何在Vue应…

如何将办公文档压缩成rar格式文件?

压缩包格式是我们生活工作中常用到的文件格式&#xff0c;那么如何得到一个rar格式的压缩文件&#xff1f;或者说如何将文件压缩成rar格式而不是zip格式呢&#xff1f;今天我们来了解一下如何压缩为rar格式文件。 首先&#xff0c;下载并安装WinRAR&#xff0c;然后用鼠标选择需…

Flat Ads:互动广告助力开发者高效流量变现

Flat Ads作为掌握7亿独家开发者流量的全球化营销推广平台,始终致力于为全球广告主提供高效、精准的效果营销和品牌宣传服务,同时为发布商提供高效变现、最大化收益的一站式解决方案。 Flat Ads旗下的互动广告平台作为高效能广告媒介,通过丰富的广告形式和变现场景有效地提升开…

【Ubuntu下 qmqtt6.2编译及使用】

这里写自定义目录标题 一、编译二、使用 背景&#xff1a;最近用QT编写简单的HMI软件&#xff0c;mqtt通信&#xff0c;记录下编译过程&#xff0c;供参考。 一、编译 QT6.5.3 qmqtt6.2&#xff08;源码地址&#xff1a;https://github.com/qt/qtmqtt/tree/6.5.3&#xff09; …

工具与技术:如何使用工具创建和实现导航栏图标动效

这篇教程的目的主要是带领大家做UI交互的入门引导,让大家理解做交互动效的一些基本逻辑思维,利用原型交互动画做导航栏icon动画效果。 导航栏icon动效的详细教程&#xff1a; 即时设计 - 可实时协作的专业 UI 设计工具即时设计是一款支持在线协作的专业级 UI 设计工具&#x…

Linux入门攻坚——26、Web Service基础知识与httpd配置-2

http协议 URL&#xff1a;Uniform Resource Locator&#xff0c;统一资源定位符 URL方案&#xff1a;scheme&#xff0c;如http://&#xff0c;https:// 服务器地址&#xff1a;IP&#xff1a;port 资源路径&#xff1a; 示例&#xff1a;http://www.test.com:80/bbs/…

【mysql 安装启动失败】 没有网下 libssl.so.10 not found 如何解决?

问题描述&#xff1a; libssl.so.10 > not found libcrypto.so.10 > not found [rootmysql tools]# ls -l /usr/sbin/mysqld -rwxr-xr-x. 1 root root 64290024 Sep 14 2022 /usr/sbin/mysqld [rootmysql tools]# ldd /usr/sbin/mysqldlinux-vdso.so.1 (0x00007fff97105…

网络流量 数据包length计算

MTUMSSIP header(20 bytes)tcp header(20 bytes) lengthMTUEthernet header(14bytes) 其中MSS为Maximum Segment Size&#xff0c;即最大报文段长度&#xff0c;其受MTU大小影响&#xff0c;这里的MTU指的是三层的&#xff0c;二层的MTU固定为1500&#xff0c;不能修改。 MT…

SFF2004A-ASEMI无人机专用SFF2004A

编辑&#xff1a;ll SFF2004A-ASEMI无人机专用SFF2004A 型号&#xff1a;SFF1006A 品牌&#xff1a;ASEMI 封装&#xff1a;ITO-220AC 最大平均正向电流&#xff08;IF&#xff09;&#xff1a;20A 最大循环峰值反向电压&#xff08;VRRM&#xff09;&#xff1a;400V 最…

一种快速设计PCB外壳的方法

设计PCB外壳比较好用的工具是SW但是有时候需要快速设计外壳的情况下使用立创EDA的外壳设计功能很好用&#xff0c;设计完成之后可以直接导出STL文件&#xff1a; 可以看到设计的外壳还是蛮精美的&#xff1a; 特别注意&#xff0c;设计外壳的时候要考虑如何把PCB放进壳子中&…