首页 前端知识 使用vue3 draggable实现元素的拖拽、缩放

使用vue3 draggable实现元素的拖拽、缩放

2024-04-15 21:04:50 前端知识 前端哥 192 210 我要收藏

在使用draggable的时候遇到了一些问题 好在最终解决了 记录下希望能帮助到有缘人

页面功能 可实现模块的放大缩小以及位置的更换 同时echarts会跟着父元素大小而变化,有兴趣者自己研究吧 代码放在下面了 直接cv就好 不难 但是有些细节要注意 比如draggable需要绑定唯一的key值否则改变元素样式时会出问题 以及echarts跟随父盒子自适应需要在echarts中配置grid属性并结合window的监听事件去实现

<template>
  <div class="itxst">
    <div class="group">
      <draggable
        v-model="group"
        ghost-class="ghost"
        handle=".move"
        filter=".forbid"
        :force-fallback="true"
        chosen-class="chosenClass"
        animation="300"
        @start="onStart"
        @end="onEnd"
        group="group1"
        :fallback-class="true"
        :fallback-on-body="true"
        :touch-start-threshold="50"
        :fallback-tolerance="50"
        :move="onMove"
        class="draggablesty"
        item-key="id"
      >
        <template #item="{ element }">
          <div
            :class="element.disabledMove ? 'forbid item' : 'item'"
            :key="element.id"
          >
            <label class="move">{{ element.name }}</label>
            <div class="echarts" :ref="setItemRef"></div>
            <span class="icon" @mousedown="mouseScale"></span>
          </div>
        </template>
      </draggable>
    </div>
  </div>
</template>
<script setup>
import { reactive, toRefs, onMounted } from "vue";
import * as echarts from "echarts";
//导入draggable组件
import draggable from "vuedraggable";
const state = reactive({
  /*工作台的数据结构
    disabledMove:禁止移动
    disabledPark:禁止停靠
  */
  group: [
    {
      name: "消息",
      id: 1,
      disabledMove: false,
      disabledPark: false,
      refVal: "ref1",
    },
    {
      name: "库存",
      id: 2,
      disabledMove: false,
      disabledPark: false,
      refVal: "ref2",
    },
    {
      name: "销量",
      id: 3,
      disabledMove: false,
      disabledPark: false,
      refVal: "ref3",
    },
    {
      name: "日志",
      id: 4,
      disabledMove: false,
      disabledPark: false,
      refVal: "ref4",
    },
  ],
});
const { group } = toRefs(state);
let itemRefs = [];
const setItemRef = (el) => {
  if (el) {
    itemRefs.push(el);
  }
};
//拖拽开始的事件
const onStart = (e) => {
  console.log("开始拖拽");
};

//拖拽结束的事件
const onEnd = (e) => {
  console.log("结束拖拽");
};

const mouseScale = (ev) => {
  //   子节点
  let target = ev.target;
  //   父节点
  let parent = ev.target.parentNode;
  let myEvent = ev;
  var distanceX = myEvent.clientX - parent.offsetWidth;
  var distanceY = myEvent.clientY - parent.offsetHeight;
  document.onmousemove = function (ev) {
    var myEvent = ev;
    parent.style.width =
      myEvent.clientX - distanceX + target.offsetWidth + "px";
    parent.style.height =
      myEvent.clientY - distanceY + target.offsetHeight + "px";
  };
  document.onmouseup = function () {
    document.onmousemove = null;
    document.onmouseup = null;
  };
};
const myECharts = () => {
  let myChart = echarts.init(itemRefs[0]);
  // 基于准备好的dom,初始化echarts实例
  // 绘制图表
  myChart.setOption({
    title: {
      text: "ECharts 入门示例",
      x: "center",
    },
    tooltip: {},
    xAxis: {
      data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"],
    },
    yAxis: {},
    grid: {
      top: 35,
      left: 55,
      right: 45,
      bottom: 20,
      width: "auto",
      height: "auto",
    },
    series: [
      {
        name: "销量",
        type: "bar",
        data: [5, 20, 36, 10, 10, 20],
      },
    ],
  });
  window.addEventListener("resize", function () {
    myChart.resize();
  });
  window.addEventListener("mousemove", function () {
    myChart.resize();
  });
};
const onMove = (e, originalEvent) => {
  //不允许停靠
  if (e.relatedContext.element.disabledPark == true) return false;
  return true;
};
onMounted(() => {
  myECharts();
});
</script>
<style>
body {
  padding: 0px;
  margin: 0px;
  background-color: #f1f1f1;
}
.itxst {
  background-color: #f1f1f1;
  display: flex;
  padding: 20px;
  width: 100%;
}

.group {
  width: 100%;
  height: 100%;
}
.draggablesty {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
  height: 100%;
}
.item {
  border: solid 1px #ddd;
  padding: 0px;
  text-align: left;
  background-color: #fff;
  margin-bottom: 10px;
  display: flex;
  flex-direction: column;
  user-select: none;
  width: 48%;
  height: 250px;
  margin: 1%;
  position: relative;
}
.echarts {
  width: 100%;
  height: 80%;
}

.icon {
  position: absolute;
  right: 0;
  bottom: 0;
  border-right: 5px solid aquamarine;
  border-bottom: 5px solid aquamarine;
  border-top: 5px solid transparent;
  border-left: 5px solid transparent;
  cursor: nw-resize;
}

.item > label {
  border-bottom: solid 1px #ddd;
  padding: 6px 10px;
  color: #333;
}
.item > label:hover {
  cursor: move;
}
.item > p {
  padding: 6px 10px;
  color: #666;
}
.ghost {
  border: solid 1px rgb(19, 41, 239) !important;
}
.chosenClass {
  opacity: 1;
  border: solid 1px red;
}
.fallbackClass {
  background-color: aquamarine;
}
</style>

转载请注明出处或者链接地址:https://www.qianduange.cn//article/5005.html
标签
评论
发布的文章

用js生成小米商城

2024-04-27 21:04:59

网页汇率计算器vue代码

2024-04-26 13:04:44

Python读写Json文件

2024-04-23 22:04:19

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!