趁着还没有被降本增笑,先做一个很low的组态系统乐呵乐呵

自从上次发布这篇帖子# 还是没记住,浏览器托拽再总结一年多了,一直觉得拖拽没有什么用处。以前项目偶尔要进行组态相关开发,也只是在开源基础上稍微改了改。

项目的需求是这样的,我需要把左边的按钮拖拽到右边背景图上,生成JSON数据保存到数据库。

这个需求看起来很简单,起初的思路是这样。背景框做成一个相对定位,拖拽的内部元素做成绝对定位。只要改变内部元素的相对位置,那么就完成了这个功能。

这么想想挺开心,关键是怎么拖动。主要涉及三个问题

  1. 把元素从左侧拖动到右侧
  2. 元素可以在右侧区域自由滑动
  3. 需要生成json数据存到数据库

解决第一个问题

第一步:创建需要拖动的元素,这里将dragDom设置为false,主要是防止这个dom元素被拖走。

我这里只创建了一个拖动元素,没有创建太多,只为了说明这个过程

html 复制代码
<how-drag-drop :dragDom="false" :data="{ name: '张三', age: 18 }">
   <div class="drag">HOWUSE</div>
</how-drag-drop>

第二步:创建接收区域,背景图所在区,这里就不放背景图片了,这个很简单也不是重点。

draggable 属性设置为false,确保目标区域不是被拖动的。对应js逻辑参考三、四步骤

html 复制代码
  <div class="target-data-wrapper" ref="boundary">
      <!-- 单向拖动,该元素draggable设置为false -->
      <how-drag-drop :draggable="false" @drop="drop" style="position: relative">
        <template v-for="(postion, index) in postions">
          <UseDraggable :boundary="boundary" :position="[postion.x, postion.y]"
            @update-data="(data) => updataData(index, data)">
            <div class="drag">HOWUSE</div>
          </UseDraggable>
        </template>
      </how-drag-drop>
    </div>

这样我们解决掉了第一问题,实现了元素的单项拖拽。

元素自由滑动

第三步:可拖拽容器组件,上边目标区域已经用到了

js 复制代码
// 可拖拽组件容器
const UseDraggable = defineComponent<{ boundary: any; position: [number, number] }>({
  name: 'UseDraggable',
  props: [
    'position',
    'boundary', // 边界元素
  ] as unknown as undefined,
  setup(props, { slots, emit }) {
    const target = ref() // 当前拖动的位置
    const handle = computed(() => target.value)  // 整体元素

    const data = useDraggable(target, {
      handle,
      initialValue: computed(() => props.position ? { x: props.position[0], y: props.position[1] } : { x: 0, y: 0 }),
      containerElement: computed(() => props.boundary),
    })

    watchEffect(() => emit("update-data", data))

    return () => {
      if (slots.default)
        return h('div', { ref: target, style: `touch-action:none;position: absolute;${unref(data.style)}` }, slots.default(reactive(data)))
    }
  },
})

存取JSON数据

第四步:数据接收部分

js 复制代码
const boundary = ref()
const postions = ref<{ x: number, y: number, data: [] }[]>([]) // 数据保存,实际的json数据保存位置

function drop(ev, data) {
  postions.value.push({ x: ev.offsetX, y: ev.offsetY, data: data.dropData })
}

function updataData(index, data) {
  postions.value[index] = { ...postions.value[index], x: data.x, y: data.y}
}

效果如下:

在线地址,参考示例【拖拽元素到另一个可拖拽区域 】:howuse.netlify.app/#/component...

源码地址:github.com/biancangmin...

相关推荐
10share6 小时前
基于大模型的 i18n 方案:把中文原文当 Key,轻松搞定多语言维护
前端·vue.js
啾咪orJIUMI11 小时前
Vue 3 + 高德地图封装实战:点位、区域、Loca 流光与 Vue 信息窗体
前端·vue.js
FRing0311 小时前
vue2干货总结8(路由模块封装、router-link、声明式导航、路由重定向、编程式导航)
开发语言·前端·vue.js·vue2
无懈可击12 小时前
Vue 可视化AI表单设计器 FcDesigner v3.6 版本发布,支持导出 SQL功能!
vue.js·开源·ai编程
徐小夕13 小时前
JitArchives,一款基于JitWord协同AI文档打造的企业级电子档案系统
前端·vue.js·github
头发还在的女程序员15 小时前
基于 Spring Boot + Vue 3 + uni-app 的灵活用工系统:四端架构与业务流程设计
vue.js·spring boot·uni-app·灵活用工·灵工系统
FRing031 天前
vue2干货总结7(自定义指令、插槽、单页应用程序、路由的使用(VueRouter))
开发语言·前端·vue.js·vue2
ruanno_top2 天前
点全选,已选的被清空了:Transfer 三态复选框的三个 bug
vue.js
时间的情敌2 天前
Cesium 加载 3D Tiles 倾斜摄影、压平、样式设置(Vue3 实战)
vue.js·3d·cesium
usdoc文档预览2 天前
USDOC系列之PPT文件在线编辑-VUE前端实现在线浏览器在线编辑PPT文档
前端·vue.js·编辑器·office365·ppt在线编辑·office文件在线编辑·文件在线编辑