Evan Wu d98029d5e7
fix(editor): 修复pad大屏模式下粘贴位置计算错误偏移问题 (#612)
* fix: 修复moveable中custom able旋转中心错误问题

* fix: 修复修复pad大屏模式下粘贴位置偏差问题
2024-05-29 20:01:51 +08:00

107 lines
4.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { toRaw } from 'vue';
import { isEmpty } from 'lodash-es';
import { Id, MContainer, MNode, NodeType } from '@tmagic/schema';
import { calcValueByFontsize, isPage, isPageFragment } from '@tmagic/utils';
import editorService from '@editor/services/editor';
import propsService from '@editor/services/props';
import type { AddMNode, PastePosition } from '@editor/type';
import { generatePageNameByApp, getInitPositionStyle } from '@editor/utils/editor';
/**
* 粘贴前置操作返回分配了新id以及校准了坐标的配置
* @param position 粘贴的坐标
* @param config 待粘贴的元素配置(复制时保存的那份配置)
* @returns
*/
export const beforePaste = (position: PastePosition, config: MNode[], doc?: Document): MNode[] => {
if (!config[0]?.style) return config;
const curNode = editorService.get('node');
// 将数组中第一个元素的坐标作为参照点
const { left: referenceLeft, top: referenceTop } = config[0].style;
// 坐标校准后的粘贴数据
const pasteConfigs: MNode[] = config.map((configItem: MNode): MNode => {
// 解构 position 对象,从 position 删除 offsetX、offsetY字段
const { offsetX = 0, offsetY = 0, ...positionClone } = position;
let pastePosition = positionClone;
if (!isEmpty(pastePosition) && curNode?.items) {
// 如果没有传入粘贴坐标则可能为键盘操作,不再转换
// 如果粘贴时选中了容器,则将元素粘贴到容器内,坐标需要转换为相对于容器的坐标
pastePosition = getPositionInContainer(pastePosition, curNode.id, doc);
}
// 将所有待粘贴元素坐标相对于多选第一个元素坐标重新计算,以保证多选粘贴后元素间距不变
if (pastePosition.left && configItem.style?.left) {
pastePosition.left = configItem.style.left - referenceLeft + pastePosition.left;
}
if (pastePosition.top && configItem.style?.top) {
pastePosition.top = configItem.style?.top - referenceTop + pastePosition.top;
}
const pasteConfig = propsService.setNewItemId(configItem, false);
if (pasteConfig.style) {
const { left, top } = pasteConfig.style;
// 判断能转换为数字时,做粘贴偏移量计算
if (typeof left === 'number' || (!!left && !isNaN(Number(left)))) {
pasteConfig.style.left = Number(left) + offsetX;
}
if (typeof top === 'number' || (!!top && !isNaN(Number(top)))) {
pasteConfig.style.top = Number(top) + offsetY;
}
pasteConfig.style = {
...pasteConfig.style,
...pastePosition,
};
}
const root = editorService.get('root');
if ((isPage(pasteConfig) || isPageFragment(pasteConfig)) && root) {
pasteConfig.name = generatePageNameByApp(root, isPage(pasteConfig) ? NodeType.PAGE : NodeType.PAGE_FRAGMENT);
}
return pasteConfig as MNode;
});
return pasteConfigs;
};
/**
* 将元素粘贴到容器内时,将相对于画布坐标转换为相对于容器的坐标
* @param position PastePosition 粘贴时相对于画布的坐标
* @param id 元素id
* @returns PastePosition 转换后的坐标
*/
export const getPositionInContainer = (position: PastePosition = {}, id: Id, doc?: Document) => {
let { left = 0, top = 0 } = position;
const parentEl = editorService.get('stage')?.renderer?.contentWindow?.document.getElementById(`${id}`);
const parentElRect = parentEl?.getBoundingClientRect();
left = left - calcValueByFontsize(doc, parentElRect?.left || 0);
top = top - calcValueByFontsize(doc, parentElRect?.top || 0);
return {
left,
top,
};
};
export const getAddParent = (node: MNode) => {
const curNode = editorService.get('node');
let parentNode;
if (isPage(node)) {
parentNode = editorService.get('root');
} else if (curNode?.items) {
parentNode = curNode as MContainer;
} else if (curNode?.id) {
parentNode = editorService.getParentById(curNode.id, false);
}
return parentNode;
};
export const getDefaultConfig = async (addNode: AddMNode, parentNode: MContainer) => {
const { type, inputEvent, ...config } = addNode;
const layout = await editorService.getLayout(toRaw(parentNode), addNode as MNode);
const newNode = { ...toRaw(await propsService.getPropsValue(type, config)) };
newNode.style = getInitPositionStyle(newNode.style, layout);
return newNode;
};