本文主要讲解元素拖拽移动,调整大小,拖拽旋转角度的基本实现原理。这些也都是一款可视化编辑器内的基本功能。
一、元素拖拽
元素拖拽相对比较简单,主要就是通过监听元素的mousedown和mousemove事件,在拖拽过程中不断设置元素的left和top实现位移。
鼠标在拖动元素的时候,无非就是 上、下、左、右四个方向,通过将鼠标移动前后的坐标对比,算出x、y轴的移动距离,从而计算出元素的最终位置。
// 1.监听元素的鼠标按下和移动事件
<template>
<div id="drag" ref="drag" @mousedown="mouseDown" @mousemove="mouseMove">拖拽</div>
</template>
// 2.定义数据
data() {
return {
startLeft:0, // 元素拖拽时的初始偏移
startTop:0,
startX: 0, // 记录鼠标按下时的初始坐标
startY: 0,
dragState:false, // 判断是否可拖动
};
}
// 3.在元素上按下鼠标时,记录相应数据
mouseDown(e) {
// 鼠标按下时的坐标
this.startX = e.pageX;
this.startY = e.pageY;
// 鼠标按下时元素的初始位置
this.startLeft = this.$refs.drag.offsetLeft;
this.startTop = this.$refs.drag.offsetTop;
//标识是否在可拖拽元素上按下
this.dragState = true;
}
// 4.鼠标移动时进行位置的设置
mouseMove(e){
if(this.mouseState) {
// 通过对比鼠标移动前后的坐标可计算出当前的位置
// diffX > 0 表示向右拖动,反之向左
// diffY > 0 标识向下拖动,反之向上
const diffX = e.pageX - this.startX,
diffY = e.pageY - this.startY;
const left = this.startLeft + diffX,
top = this.startTop + diffY;
this.$refs.drag.style.cssText = `left:${left}px;top:${top}px`;
}
}
Demo:code.juejin.cn/pen/7160500…
二、拖拽调整尺寸
拖拽调节尺寸主要通过附着在元素上的8个节点来操作的,如下图:
拖拽每个节点对应的操作都些许不同:
- topLeft(上左):元素
left、top和width、height都会变化 - topCenter(上中):
top和height会变化 - topRight(上右):
top和width、height会变化 - rightCenter(右中):仅
width会变化 - bottomRight(下右):
width、height会变化 - bottomCenter(下中):仅
height会变化 - bottomLeft(下左):
left和width、height会变化 - leftCenter(左中):
left和width会变化
理清每个节点的作用,编写操作逻辑的时候就明了了。
跟拖拽元素一样,在节点上按下鼠标时,记录鼠标初始坐标,然后在移动过程中计算x、y轴的移动距离,再根据拖拽的节点编写对应的操作逻辑。
1.拖动rightCenter(右中)和bottomCenter(下中)最简单,仅需使用初始宽、高和对应轴线的位移距离相加就行
2.拖动topCenter(上中)和leftCenter(左中),除了要修改对应轴线的偏移之外,同时还需要用宽高减去对应轴线移动的距离,调整尺寸。对应轴线的位移距离为负数时,表示尺寸增大,反之减少。
3.拖动四个对角的节点,有两种操作逻辑:一种是不锁定比例,拖拽元素尺寸自由变化;另一种是锁定比例,等比缩放尺寸,我这边采用的是等比缩放。
- 通常拖动四角的节点会产生x、y轴两个方向的位移,我这边是根据x轴位移距离来做相应的计算。
- 比如我们拖动右下角的节点,x轴移动20像素,y轴移动15像素。我们以x轴为准,计算出元素拖动后的宽度
新的宽度 = 原始宽度 + 20,高度则等比进行放大新的宽度 / 原始宽度 * 原始高度 - 其他几个对角的拖动,中心思想都是一样的,就不赘述了,大家可以看下方demo
正常在项目中,拖拽调整尺寸的时候,应当加一个最小尺寸的限制,低于设置的值就无法再继续缩小,demo中仅简单实现功能,未做细节处理。
Demo:code.juejin.cn/pen/7160599…
三、拖拽旋转
拖拽选旋转角度相对比较简单,通过一个Math.atan2(y,x)这个公式就可以计算出来。
公式简介: Math.atan2() 返回从原点(0,0)到(x,y)点的线段与x轴正方向之间的平面角度(弧度值),也就是Math.atan2(y,x)
注意点: 1.返回的是一个逆时针的弧度 2.先传递 y 坐标,然后是 x 坐标 )
如下图:
蓝点是鼠标位置,橙点作为元素的中心,也就是原点。我们需要计算出蓝点相对于橙点的坐标.
x = 蓝点原始X - A(元素的左偏移) - B(元素宽度 / 2)
y = 蓝点原始Y - C(元素顶部偏移) - D(元素高度 / 2)
计算夹角(弧度):radian = Math.atan2(y, x);
弧度转角度: angle = radian / Math.PI / 180
Demo:code.juejin.cn/pen/7160890…
相关文章