首页 > 其他分享 >vue 组件封装——可自由拖拽移动的盒子

vue 组件封装——可自由拖拽移动的盒子

时间:2023-02-22 14:24:34浏览次数:33  
标签:vue moveStart nodeInfo mouseY mouseX originNodeInfo 封装 null 拖拽

<template>
  <div
    ref="box_Ref"
    class="box"
    @mousedown="moveStart"
    @mousemove="moving"
    @mouseup="moveEnd"
    :style="{
      width: (nodeInfo.width || 40) + 'px',
      height: (nodeInfo.height || 60) + 'px',
      left: (nodeInfo.x || 0) + 'px',
      top: (nodeInfo.y || 0) + 'px',
      backgroundColor: nodeInfo.color || 'black',
      zIndex: zIndex,
    }"
  ></div>
</template>

<script>
export default {
  props: {
    nodeInfo: Object,
  },
  data() {
    return {
      zIndex: "auto",
      // 移动开始时,鼠标的x坐标
      moveStart_mouseX: null,
      // 移动开始时,鼠标的y坐标
      moveStart_mouseY: null,
      ifMove: false,
      originNodeInfo: null,
    };
  },

  methods: {
    // 移动开始
    moveStart(e) {
      this.moveStart_mouseX = e.clientX;
      this.moveStart_mouseY = e.clientY;
      this.ifMove = true;
      this.originNodeInfo = JSON.parse(JSON.stringify(this.nodeInfo));
      //   移动时,临时提升元素至顶层,避免因元素遮挡而无法继续移动
      this.zIndex = 99999;
    },
    // 移动中
    moving(e) {
      if (this.ifMove) {
        let moveing_mouseX = e.clientX;
        let moveing_mouseY = e.clientY;
        let xChange = moveing_mouseX - this.moveStart_mouseX;
        let yChange = moveing_mouseY - this.moveStart_mouseY;
        this.$emit("moved", {
          newX: this.originNodeInfo.x + xChange,
          newY: this.originNodeInfo.y + yChange,
        });
      }
    },
    // 移动结束
    moveEnd() {
      this.ifMove = false;
      this.moveStart_mouseX = null;
      this.moveStart_mouseY = null;
      this.originNodeInfo = null;
      this.zIndex = "auto";
    },
  },
};
</script>

<style scoped>
.box {
  position: absolute;
  cursor: move;
}
</style>

使用组件 index.vue

<template>
  <div>
    <SuperBox @moved="moved($event, node1)" :nodeInfo="node1" />
    <SuperBox @moved="moved($event, node2)" :nodeInfo="node2" />
  </div>
</template>

<script>
import SuperBox from "./superBox.vue";
export default {
  components: {
    SuperBox,
  },
  data() {
    return {
      node1: {
        x: 100,
        y: 10,
        color: "red",
      },

      node2: {
        x: 400,
        y: 10,
        color: "blue",
      },
    };
  },

  methods: {
    moved(movedInfo, nodeInfo) {
      // < 0 时置为0,避免元素移出浏览器窗口
      nodeInfo.x = movedInfo.newX < 0 ? 0 : movedInfo.newX;
      nodeInfo.y = movedInfo.newY < 0 ? 0 : movedInfo.newY;
    },
  },
};
</script>

遗留问题
当鼠标拖拽过快时,元素无法跟随移动,且 ifMove 无法正常恢复 false 导致拖拽异常。

想到解决方案的朋友,欢迎留言哦!

标签:vue,moveStart,nodeInfo,mouseY,mouseX,originNodeInfo,封装,null,拖拽
From: https://www.cnblogs.com/Jishuyang/p/17144150.html

相关文章

  • vue $bus 和 settimeout 实现setinterval
    main.js实现用settimeout实现setintervalwindow.$bus=newVue()window.setTimeToInterval=function(delay){if(window.intervalTimeout){clearTime......
  • Springboot 系列 (22) - Springboot+Netty | 使用 Netty 封装的 WebSocket 实现消息实
    Netty是由JBOSS提供的一个Java开源框架。Netty是一个基于JavaNIO的开发框架,主要针对在TCP协议下,面向Client端的高并发应用,或者Peer-to-Peer场景下的大量数......
  • vue项目中img动态导入的问题
    相信有些人应该都会遇到vue项目中动态加载图片的问题。就是觉得路径没有问题,但是还是报错。错误代码template:<el-cardv-for="(o,s_i)instyleList":key="s_i">......
  • Vue配置文件中的proxy配置
    Vue配置文件中的proxy配置https://huaweicloud.csdn.net/638eec24dacf622b8df8dafa.html?spm=1001.2101.3001.6650.11&utm_medium=distribute.pc_relevant.none-task-blog......
  • Vue3开发教程(一、学习Vue前需要了解的内容)
    前言本文是笔者学习vue前端技术过程的总结,其中包括vue开发需要了解的相关技术如:node、ES6、TypeScript、vite、ElementUI。以vue作为主线来介绍相关技术,最后通过一个典型的......
  • vue3 ThreeJS 引入obj模型过暗的问题
      当我单纯地用MTLLoader引入材质,OBJLoader引入模型并添加到场景中时, 发现模型非常得暗. 需要将环境光的强度设置到3.5左右看起来才比较正常. 但正常情况下环境光......
  • vue3 门户网站搭建3-pinia
    引入pinia来方便处理全局变量。npminstallpinia 1、创建pinia 2、main中引入(我这里是直接写的index,所以导出的是stores) 3、定义变量 使用: ......
  • vue axios异步处理方案
    vueaxios异步处理方案1.使用setTimeout函数用延时处理(复杂一点逻辑会达不到效果) 实例:setTimeout(()=>{console.log('1');},300......
  • 在vue中动态的引入图片为什么要使用require
    在vue中动态的引入图片为什么要使用require有些小伙伴,可能会轻蔑一笑:呵,就这,因为动态添加src被当做静态资源处理了,没有进行编译,所以要加上require,我倒着都能背出来............
  • Vue - eslint默认验证,函数名称和括号相连报错
    如果函数名和括号相连,eslint验证会报错,这个可以通过eslint的设置解决:一,打开eslintrc.js,在rules配置中加入:'space-before-function-paren':0完整配置:rules:{/......