fix: markline

This commit is contained in:
hufeixiong
2021-07-27 10:58:41 +08:00
parent 8a178c82f0
commit 858273fe11
12 changed files with 234 additions and 81 deletions

View File

@@ -81,7 +81,7 @@ config可以拿到所有数据用来制作事件时使用。
第六个参数resize 是为了判断是否能进行缩放当为false时无法进行缩放。
第七个参数needPosition某些组件移入画布后会默认采取拖拽的落点该配置项默认为true为false时将使用组件自top和left定位来放置。
第七个参数needPosition某些组件移入画布后会默认采取拖拽的落点该配置项默认为true为false时将使用组件自top和left定位来放置。

View File

@@ -2,7 +2,7 @@
* @Author: yehuozhili
* @Date: 2021-07-07 14:35:38
* @LastEditors: yehuozhili
* @LastEditTime: 2021-07-26 14:03:01
* @LastEditTime: 2021-07-27 10:46:07
* @FilePath: \dooringx\packages\dooringx-example\src\plugin\registComponents\button.tsx
*/
@@ -131,6 +131,7 @@ const MButton = new ComponentItemFactory(
canRotate: true,
value: 0,
},
canDrag: true, // false就不能拖
},
(data, context, store, config) => {
return <ButtonTemp data={data} store={store} context={context} config={config}></ButtonTemp>;

View File

@@ -2,7 +2,7 @@
* @Author: yehuozhili
* @Date: 2021-03-14 04:29:09
* @LastEditors: yehuozhili
* @LastEditTime: 2021-07-20 11:25:31
* @LastEditTime: 2021-07-27 10:17:01
* @FilePath: \dooringx\packages\dooringx-lib\src\components\wrapperMove\index.tsx
*/
import { AllHTMLAttributes, CSSProperties, PropsWithChildren, useRef } from 'react';

View File

@@ -2,7 +2,7 @@
* @Author: yehuozhili
* @Date: 2021-03-14 04:29:09
* @LastEditors: yehuozhili
* @LastEditTime: 2021-07-20 16:12:55
* @LastEditTime: 2021-07-26 20:42:16
* @FilePath: \dooringx\packages\dooringx-lib\src\core\crossDrag\index.ts
*/
import { DragEvent, ReactNode } from 'react';
@@ -51,8 +51,8 @@ export const containerDragResolve = (config: UserConfig) => {
e.preventDefault();
},
onDrop: (e: DragEvent<HTMLDivElement>) => {
const offsetX = e.nativeEvent.offsetX;
const offestY = e.nativeEvent.offsetY;
const offsetX = Math.round(e.nativeEvent.offsetX);
const offestY = Math.round(e.nativeEvent.offsetY);
//drop后修改store
if (currentDrag) {
// 还需要拿到注册的组件状态

View File

@@ -39,8 +39,8 @@ export const innerDrag = function (
ref.current.style.cursor = 'move';
ref.current.style.willChange = 'left,right,width,height';
}
innerDragState.startX = e.clientX;
innerDragState.startY = e.clientY;
innerDragState.startX = Math.round(e.clientX);
innerDragState.startY = Math.round(e.clientY);
innerDragState.item = item;
innerDragState.isDrag = true;
innerDragState.ref = ref;
@@ -69,30 +69,30 @@ export const innerContainerDrag = function (config: UserConfig) {
let { clientX: moveX, clientY: moveY } = e;
const { startX, startY } = innerDragState;
const scale = scaleState.value;
let durX = (moveX - startX) / scale;
let durY = (moveY - startY) / scale;
let durX = Math.round((moveX - startX) / scale);
let durY = Math.round((moveY - startY) / scale);
let newblock: IBlockType[];
if (lastblock !== innerDragState.item) {
const cloneblock: IBlockType[] = deepCopy(store.getData().block);
lastblock = innerDragState.item;
newblock = cloneblock.map((v) => {
if (v.focus && v.position !== 'static') {
v.left = v.left + durX;
v.top = v.top + durY;
v.left = Math.round(v.left + durX);
v.top = Math.round(v.top + durY);
}
return v;
});
} else {
newblock = store.getData().block.map((v) => {
if (v.focus && v.position !== 'static') {
v.left = v.left + durX;
v.top = v.top + durY;
v.left = Math.round(v.left + durX);
v.top = Math.round(v.top + durY);
}
return v;
});
}
innerDragState.startX = moveX;
innerDragState.startY = moveY;
innerDragState.startX = Math.round(moveX);
innerDragState.startY = Math.round(moveY);
store.setData({ ...store.getData(), block: newblock });
}
resizerMouseMove(e, config);

View File

@@ -2,22 +2,64 @@
* @Author: yehuozhili
* @Date: 2021-03-14 04:29:09
* @LastEditors: yehuozhili
* @LastEditTime: 2021-07-26 11:38:11
* @LastEditTime: 2021-07-26 20:51:41
* @FilePath: \dooringx\packages\dooringx-lib\src\core\markline\calcRender.ts
*/
import { innerDragState } from '../innerDrag/state';
import { switchMarklineDisplay } from './normalMode';
import { resizeCurrentCalculate } from './resizeMarkline';
import { newMarklineDisplay } from './normalMode';
import { marklineConfig } from './marklineConfig';
import UserConfig from '../../config';
import { angleToRadian, getContainer } from '../utils';
export interface LinesTypes {
x: number[];
y: number[];
}
export function marklineCalRender(config: UserConfig) {
export function cos(rotate: number) {
return Math.abs(Math.cos(angleToRadian(rotate)));
}
export function sin(rotate: number) {
return Math.abs(Math.sin(angleToRadian(rotate)));
}
export function getComponentRotatedStyle(
rotate: number,
width: number,
height: number,
left: number,
right: number,
top: number,
bottom: number
) {
const style = {
left,
width,
height,
right,
top,
bottom,
};
if (rotate !== 0) {
const newWidth = style.width * cos(rotate) + style.height * sin(rotate);
const diffX = (style.width - newWidth) / 2; // 旋转后范围变小是正值,变大是负值
style.left += diffX;
style.right = style.left + newWidth;
const newHeight = style.height * cos(rotate) + style.width * sin(rotate);
const diffY = (newHeight - style.height) / 2; // 始终是正
style.top -= diffY;
style.bottom = style.top + newHeight;
style.width = newWidth;
style.height = newHeight;
} else {
style.bottom = style.top + style.height;
style.right = style.left + style.width;
}
return style;
}
export function marklineCalRender(config: UserConfig): LinesTypes {
const store = config.getStore();
const scaleState = config.getScaleState();
//focus可能好几个做对比的是拖拽那个
const lines: LinesTypes = { x: [], y: [] };
if (innerDragState.item?.position === 'static' || innerDragState.item?.position === 'relative') {
@@ -28,7 +70,19 @@ export function marklineCalRender(config: UserConfig) {
const ref = innerDragState.ref;
if (item && ref && ref.current && innerDragState.isDrag) {
// 这个被拷贝过,所以必须重新获取
const focus = store.getData().block.find((v) => v.id === item.id)!;
if (!focus) {
return lines;
}
const container = getContainer();
if (!container) {
return lines;
}
if (typeof focus.width !== 'number' || typeof focus.height !== 'number') {
return lines;
}
if (!marklineConfig.marklineUnfocus) {
marklineConfig.marklineUnfocus = store
.getData()
@@ -36,17 +90,25 @@ export function marklineCalRender(config: UserConfig) {
(v) => v.focus === false && v.position !== 'static' && v.position !== 'relative'
);
}
const { width, height } = ref.current.getBoundingClientRect();
// left 和top 被深拷贝过,最新的值需要即时获取
const left = focus?.left;
const top = focus?.top;
const left = focus.left;
const top = focus.top;
const rotate = focus.rotate.value;
const width = focus.width;
const height = focus.height;
const realStyle = getComponentRotatedStyle(
rotate,
width,
height,
left,
left + width,
top,
top + height
);
if (typeof left !== 'number' || typeof top !== 'number') {
return lines; //莫名可能没有这2值
return lines; //可能没有这2值
}
const scale = scaleState.value;
const wwidth = width / scale;
const wheight = height / scale;
marklineConfig.marklineUnfocus.forEach((v) => {
let l = v?.left;
@@ -54,26 +116,19 @@ export function marklineCalRender(config: UserConfig) {
if (typeof l !== 'number' || typeof t !== 'number') {
console.warn(`${v} component miss top or left`);
} else {
// 如果不是由外层容器决定的则没有这2属性
// 如果拿实例可能有性能问题,暂直接计算。
const w = v.width;
const h = v.height;
// 只有满足要求的才进行push
if (marklineConfig.mode === 'normal') {
switchMarklineDisplay(l, t, w, h, left, top, wwidth, wheight, lines, focus);
if (typeof w === 'number' && typeof h === 'number') {
const ro = v.rotate.value;
const r = l + w;
const b = t + h;
const rstyle = getComponentRotatedStyle(ro, w, h, l, r, t, b);
newMarklineDisplay(realStyle, rstyle, lines, focus);
}
}
});
// if (marklineConfig.mode === 'grid' && marklineConfig.isAbsorb) {
// gridModeDisplay(left, top, focus, config);该模式暂废弃
// }
}
// if (marklineConfig.mode === 'grid') {
// grideModeRender(lines, config);该模式暂废弃
// }
resizeCurrentCalculate(lines, config);
return lines;
}

View File

@@ -2,36 +2,14 @@
* @Author: yehuozhili
* @Date: 2021-03-14 04:29:09
* @LastEditors: yehuozhili
* @LastEditTime: 2021-07-13 20:38:59
* @LastEditTime: 2021-07-26 15:01:06
* @FilePath: \dooringx\packages\dooringx-lib\src\core\markline\index.tsx
*/
import React from 'react';
import { useMemo } from 'react';
import UserConfig from '../../config';
import { IBlockType } from '../store/storetype';
import { marklineCalRender } from './calcRender';
// 主要逻辑需要注入组件内拖拽
export interface MarklineConfigType {
indent: number;
isAbsorb: boolean;
mode: 'normal' | 'grid';
gridIndent: number;
resizeIndent: number;
marklineUnfocus: null | IBlockType[];
}
// 间隔距离执行吸附
export const marklineConfig: MarklineConfigType = {
indent: 2,
isAbsorb: true,
mode: 'normal',
gridIndent: 50,
resizeIndent: 0,
marklineUnfocus: null,
};
export function MarklineX(props: any) {
return (
<div

View File

@@ -1,6 +1,121 @@
import { IBlockType } from '../store/storetype';
import { LinesTypes } from './calcRender';
import { marklineConfig } from './marklineConfig';
export interface RealStyle {
width: number;
height: number;
left: number;
right: number;
top: number;
bottom: number;
}
export function newMarklineDisplay(
focusStyle: RealStyle,
unFocusStyle: RealStyle,
lines: LinesTypes,
focus: IBlockType
) {
const { top, height, left, width } = focusStyle;
const { top: t, height: h, left: l, width: w } = unFocusStyle;
let diffY = 0;
// 头对头
if (Math.abs(t - top) < marklineConfig.indent) {
lines.x.push(t);
diffY = t - top;
}
// 中对头
else if (Math.abs(t - (top + height / 2)) < marklineConfig.indent) {
lines.x.push(t);
diffY = t - (top + height / 2);
}
// 尾对头
else if (Math.abs(t - (top + height)) < marklineConfig.indent) {
lines.x.push(t);
diffY = t - (top + height);
}
// 头对中
else if (Math.abs(t + h / 2 - top) < marklineConfig.indent) {
lines.x.push(t + h / 2);
diffY = t + h / 2 - top;
}
// 中对中
else if (Math.abs(t + h / 2 - top - height / 2) < marklineConfig.indent) {
lines.x.push(t + h / 2);
diffY = t + h / 2 - top - height / 2;
}
// 尾对中
else if (Math.abs(t + h / 2 - top - height) < marklineConfig.indent) {
lines.x.push(t + h / 2);
diffY = t + h / 2 - top - height;
}
// 头对尾
else if (Math.abs((t + h - top) / 2) < marklineConfig.indent) {
lines.x.push(t + h);
diffY = (t + h - top) / 2;
}
// 中对尾
else if (Math.abs(t + h - top - height / 2) < marklineConfig.indent) {
lines.x.push(t + h);
diffY = t + h - top - height / 2;
}
// 尾对尾
else if (Math.abs((t + h - top - height) / 2) < marklineConfig.indent) {
lines.x.push(t + h);
diffY = (t + h - top - height) / 2;
}
focus.top = Math.round(focus.top + diffY);
// 纵线
// 头对头
let diffX = 0;
if (Math.abs(l - left) < marklineConfig.indent) {
lines.y.push(l);
diffX = l - left;
}
// 中对头
else if (Math.abs(l - (left + width / 2)) < marklineConfig.indent) {
lines.y.push(l);
diffX = l - (left + width / 2);
}
// 尾对头
else if (Math.abs(l - (left + width)) < marklineConfig.indent) {
lines.y.push(l);
diffX = l - (left + width);
}
// 头对中
else if (Math.abs(l + w / 2 - left) < marklineConfig.indent) {
lines.y.push(l + w / 2);
diffX = l + w / 2 - left;
}
// 中对中
else if (Math.abs(l + w / 2 - left - width / 2) < marklineConfig.indent) {
lines.y.push(l + w / 2);
diffX = l + w / 2 - left - width / 2;
}
// 尾对中
else if (Math.abs(l + w / 2 - left - width) < marklineConfig.indent) {
lines.y.push(l + w / 2);
diffX = l + w / 2 - left - width;
}
// 头对尾
else if (Math.abs((l + w - left) / 2) < marklineConfig.indent) {
lines.y.push(l + w);
diffX = (l + w - left) / 2;
}
// 中对尾
else if (Math.abs(l + w - left - width / 2) < marklineConfig.indent) {
lines.y.push(l + w);
diffX = l + w - left - width / 2;
}
// 尾对尾
else if (Math.abs((l + w - left - width) / 2) < marklineConfig.indent) {
lines.y.push(l + w);
diffX = (l + w - left - width) / 2;
}
focus.left = Math.round(focus.left + diffX);
}
export function switchMarklineDisplay(
l: number,
t: number,

View File

@@ -2,7 +2,7 @@
* @Author: yehuozhili
* @Date: 2021-03-09 15:19:36
* @LastEditors: yehuozhili
* @LastEditTime: 2021-07-20 11:31:44
* @LastEditTime: 2021-07-27 10:18:34
* @FilePath: \dooringx\packages\dooringx-lib\src\core\resizeHandler\containerResizer.ts
*/
@@ -32,8 +32,9 @@ export const containerResizer = {
const diff = ((e.clientY - containerState.startY) / scale) * 2; //可以直接使用movementy
const clonedata: IStoreData = deepCopy(store.getData());
const height = clonedata.container.height;
let tmpHeight =
height + diff < containerState.minHeight ? containerState.minHeight : height + diff;
let tmpHeight = Math.round(
height + diff < containerState.minHeight ? containerState.minHeight : height + diff
);
clonedata.container.height = tmpHeight;
store.setData(clonedata);
containerState.startY = e.clientY;

View File

@@ -1,6 +1,6 @@
import { RefObject, useMemo } from 'react';
import { IBlockType } from '../store/storetype';
import { deepCopy } from '../utils';
import { deepCopy, getContainer } from '../utils';
import React from 'react';
import classnames from 'classnames';
import styles from '../../index.less';
@@ -32,10 +32,7 @@ const onMouseDown = (
resizeState.current = store.getIndex();
resizeState.currentTarget = e.nativeEvent.target as HTMLDivElement;
const curDiv = resizeState.ref.current;
let container = document.querySelector('#yh-container');
if (!container) {
container = document.querySelector('#yh-container-iframe');
}
const container = getContainer();
if (!container) {
return;
}
@@ -148,13 +145,10 @@ export const resizerMouseMove = (e: React.MouseEvent, config: UserConfig) => {
resizeState.ref?.current &&
resizeState.currentTarget
) {
let { clientX: moveX, clientY: moveY } = e;
const { clientX: moveX, clientY: moveY } = e;
const scale = scaleState.value;
let container = document.querySelector('#yh-container');
if (!container) {
container = document.querySelector('#yh-container-iframe');
}
const container = getContainer();
if (!container) {
return;
}

View File

@@ -294,3 +294,11 @@ export function postMessage(value: any, src: string, target = 'yh-container-ifra
export function angleToRadian(angle: number) {
return (angle * Math.PI) / 180;
}
export function getContainer() {
let container = document.querySelector('#yh-container');
if (!container) {
container = document.querySelector('#yh-container-iframe');
}
return container;
}

View File

@@ -2,14 +2,15 @@
* @Author: yehuozhili
* @Date: 2021-03-14 05:02:28
* @LastEditors: yehuozhili
* @LastEditTime: 2021-07-04 16:40:17
* @FilePath: \DooringV2\packages\dooring-v2-lib\tsdx.config.js
* @LastEditTime: 2021-07-26 14:55:29
* @FilePath: \dooringx\packages\dooringx-lib\tsdx.config.js
*/
const postcss = require('rollup-plugin-postcss');
const replace = require('@rollup/plugin-replace');
module.exports = {
rollup(config, options) {
config.output.banner = '// 有问题请加QQ 673632758 by yehuozhili';
config.plugins.push(
postcss({
inject: false,