Skip to content

Commit

Permalink
Merge pull request #16 from gongym12138/main
Browse files Browse the repository at this point in the history
fix: 拖拽rule线时,鼠标样式会反复变化
  • Loading branch information
pengxiaotian authored Jun 9, 2021
2 parents cf45bcd + 30ed207 commit 31ccf8a
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 29 deletions.
165 changes: 138 additions & 27 deletions src/views/screen/canvas-main/datav-transform/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,37 +77,148 @@ export const setHover = (com: DatavComponent, hovered: boolean) => {
com.hovered = hovered
}

/**
* 角度转弧度
* Math.PI = 180 度
* @param angle
* @returns {number}
*/
function angleToRadian(angle) {
return angle * Math.PI / 180
}
/**
* 计算根据圆心旋转后的点的坐标
* @param {Object} point 旋转前的点坐标
* @param {Object} center 旋转中心
* @param {Number} rotate 旋转的角度
* @return {Object} 旋转后的坐标
* https://www.zhihu.com/question/67425734/answer/252724399 旋转矩阵公式
*/
export function calculateRotatedPointCoordinate(point, center, rotate) {
/**
* 旋转公式:
* 点a(x, y)
* 旋转中心c(x, y)
* 旋转后点n(x, y)
* 旋转角度θ tan ??
* nx = cosθ * (ax - cx) - sinθ * (ay - cy) + cx
* ny = sinθ * (ax - cx) + cosθ * (ay - cy) + cy
*/
return {
x: (point.x - center.x) * Math.cos(angleToRadian(rotate)) - (point.y - center.y) * Math.sin(angleToRadian(rotate)) + center.x,
y: (point.x - center.x) * Math.sin(angleToRadian(rotate)) + (point.y - center.y) * Math.cos(angleToRadian(rotate)) + center.y,
}
}

export function getCenterPoint(p1, p2) {
return {
x: p1.x + ((p2.x - p1.x) / 2),
y: p1.y + ((p2.y - p1.y) / 2),
}
}

/**
* 计算缩放后位置大小
* @param direction 拖拽方向
* @param style 当前位置和大小
* @param startPoint 拖拽起始点位置
* @param symmetricPoint 对称点坐标
* @param endPoint 当前拖拽位置
* @returns {{}|any}
*/
export function calcResizeInfo(direction, style, startPoint, symmetricPoint, endPoint) {
// 拖拽角上的点
if (direction.length === 2) {
const newCenter = getCenterPoint(endPoint, symmetricPoint)
const thatPoint = calculateRotatedPointCoordinate(symmetricPoint, newCenter, -style.rotate)
const thisPoint = calculateRotatedPointCoordinate(endPoint, newCenter, -style.rotate)
const newStyle = {
x: undefined,
y: undefined,
width: undefined,
height: undefined,
}
// 判断: 左或者右
if (direction[0] === 'l') {
newStyle.x = Math.round(thisPoint.x / style.scale)
newStyle.width = Math.round((thatPoint.x - thisPoint.x) / style.scale)
} else if (direction[0] === 'r') {
newStyle.x = Math.round(thatPoint.x / style.scale)
newStyle.width = Math.round((thisPoint.x - thatPoint.x) / style.scale)
}
// 判断: 上或者下
if (direction[1] === 't') {
newStyle.y = Math.round(thisPoint.y / style.scale)
newStyle.height = Math.round((thatPoint.y - thisPoint.y) / style.scale)
} else if (direction[1] === 'b') {
newStyle.y = Math.round(thatPoint.y / style.scale)
newStyle.height = Math.round((thisPoint.y - thatPoint.y) / style.scale)
}
return newStyle
}

// 拖拽边上的点
if (direction.length === 1) {
const newStyle = JSON.parse(JSON.stringify(style))
const thisPoint = calculateRotatedPointCoordinate(endPoint, startPoint, -style.rotate)

// 拖拽上下两边
if (direction === 't' || direction === 'b') {
const thatPoint = calculateRotatedPointCoordinate({ x: startPoint.x, y: thisPoint.y }, startPoint, style.rotate)
const height = Math.sqrt((thatPoint.x - symmetricPoint.x) ** 2 + (thatPoint.y - symmetricPoint.y) ** 2)
if (height > 0) {
const center = { x: thatPoint.x - (thatPoint.x - symmetricPoint.x) / 2, y: thatPoint.y + (symmetricPoint.y - thatPoint.y) / 2 }
newStyle.width = Math.round(style.width / style.scale)
newStyle.height = Math.round(height / style.scale)
newStyle.x = Math.round((center.x - (style.width / 2)) / style.scale)
newStyle.y = Math.round((center.y - (height / 2)) / style.scale)
}
}

// 拖拽左右两边
if (direction === 'l' || direction === 'r') {
const thatPoint = calculateRotatedPointCoordinate({ x: thisPoint.x, y: startPoint.y }, startPoint, style.rotate)
const width = Math.sqrt((thatPoint.x - symmetricPoint.x) ** 2 + (thatPoint.y - symmetricPoint.y) ** 2)
if (width > 0) {
const center = { x: thatPoint.x - (thatPoint.x - symmetricPoint.x) / 2, y: thatPoint.y + (symmetricPoint.y - thatPoint.y) / 2 }
newStyle.width = Math.round(width / style.scale)
newStyle.height = Math.round(style.height / style.scale)
newStyle.x = Math.round((center.x - (width / 2)) / style.scale)
newStyle.y = Math.round((center.y - (style.height / 2)) / style.scale)
}
}
return newStyle
}
}

const setAttr = (ev: MouseEvent, dir: Direction | null, com: DatavComponent, scale: number, grid: number) => {
const attr = { ...com.attr }
const pos = Object.create(null) as Partial<ComponentAttr>

const style = {
x: Math.round(attr.x * scale),
y: Math.round(attr.y * scale),
width: Math.round(attr.w * scale),
height: Math.round(attr.h * scale),
rotate: attr.deg,
scale: scale,
}
// 组件中心点
const center = { x: style.x + style.width / 2, y: style.y + style.height / 2 }
// 获取画布位移信息
const layoutRect = document.querySelector('#canvas-coms').getBoundingClientRect()
// 当前点击坐标
const startPoint = { x: ev.clientX - layoutRect.left, y: ev.clientY - layoutRect.top }
// 获取对称点的坐标
const symmetricPoint = { x: center.x - (startPoint.x - center.x), y: center.y - (startPoint.y - center.y) }
const move = (e: MouseEvent) => {
if (dir === 't') {
pos.h = Math.round(attr.h + (ev.clientY - e.clientY) / scale)
pos.y = Math.round(attr.y + (e.clientY - ev.clientY) / scale)
} else if (dir === 'rt') {
pos.h = Math.round(attr.h + (ev.clientY - e.clientY) / scale)
pos.w = Math.round(attr.w + (ev.clientX - e.clientX) / scale)
pos.x = Math.round(attr.x + (e.clientX - ev.clientX) / scale)
pos.y = Math.round(attr.y + (e.clientY - ev.clientY) / scale)
} else if (dir === 'r') {
pos.w = Math.round(attr.w + (e.clientX - ev.clientX) / scale)
} else if (dir === 'rb') {
pos.h = Math.round(attr.h + (e.clientY - ev.clientY) / scale)
pos.w = Math.round(attr.w + (e.clientX - ev.clientX) / scale)
} else if (dir === 'b') {
pos.h = Math.round(attr.h + (e.clientY - ev.clientY) / scale)
} else if (dir === 'lb') {
pos.h = Math.round(attr.h + (e.clientY - ev.clientY) / scale)
pos.w = Math.round(attr.w + (ev.clientX - e.clientX) / scale)
pos.x = Math.round(attr.x + (e.clientX - ev.clientX) / scale)
} else if (dir === 'l') {
pos.w = Math.round(attr.w + (ev.clientX - e.clientX) / scale)
pos.x = Math.round(attr.x + (e.clientX - ev.clientX) / scale)
} else if (dir === 'lt') {
pos.h = Math.round(attr.h + (ev.clientY - e.clientY) / scale)
pos.w = Math.round(attr.w + (ev.clientX - e.clientX) / scale)
pos.x = Math.round(attr.x + (e.clientX - ev.clientX) / scale)
pos.y = Math.round(attr.y + (e.clientY - ev.clientY) / scale)
if (dir !== null) {
const endPoint = { x: e.clientX - layoutRect.left, y: e.clientY - layoutRect.top }
const newPosition = calcResizeInfo(dir, style, startPoint, symmetricPoint, endPoint)
pos.x = newPosition.x
pos.y = newPosition.y
pos.w = newPosition.width
pos.h = newPosition.height
} else {
// grid 是每次移动固定格数
pos.x = attr.x + Math.round((e.clientX - ev.clientX) / scale / grid) * grid
Expand Down
7 changes: 7 additions & 0 deletions src/views/screen/canvas-main/ruler/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,22 @@ class GuideLine {
}

moving(ev: MouseEvent) {
const { options } = this
ev.preventDefault()
ev.stopPropagation()

const { coor: oldCoor } = this
const move = (e: MouseEvent) => {
if (options.direction === 'TB') {
document.body.style.cursor = 'col-resize'
} else {
document.body.style.cursor = 'row-resize'
}
this.setLine(e)
}

const up = () => {
document.body.style.cursor = ''
off(document, 'mousemove', move)
off(document, 'mouseup', up)

Expand Down
4 changes: 2 additions & 2 deletions src/views/screen/canvas-main/ruler/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ export default defineComponent({
.h-container {
left: 20px;
cursor: ew-resize;
cursor: col-resize;
transform: translateX(0);
.ruler-line {
Expand All @@ -191,7 +191,7 @@ export default defineComponent({
}
.v-container {
cursor: ns-resize;
cursor: row-resize;
transform: rotate(90deg) translateX(0);
transform-origin: 0 100% 0;
Expand Down

0 comments on commit 31ccf8a

Please sign in to comment.