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

前言:

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

目标:

  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上的拖拽设计,以上代码都不可直接使用,因为代码不全,仅仅能提供参考,或者自行修改也可

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

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值