Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 修复旋转后,拖拽缩放的BUG #16

Merged
merged 2 commits into from
Jun 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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