diff --git a/packages/dooringx-lib/src/components/rightConfig.tsx b/packages/dooringx-lib/src/components/rightConfig.tsx index b9868a8..16b64f1 100644 --- a/packages/dooringx-lib/src/components/rightConfig.tsx +++ b/packages/dooringx-lib/src/components/rightConfig.tsx @@ -2,7 +2,7 @@ * @Author: yehuozhili * @Date: 2021-03-14 05:42:13 * @LastEditors: yehuozhili - * @LastEditTime: 2022-04-29 23:36:45 + * @LastEditTime: 2022-04-30 23:07:13 * @FilePath: \dooringx\packages\dooringx-lib\src\components\rightConfig.tsx */ import { CreateOptionsRes } from '../core/components/formTypes'; diff --git a/packages/dooringx-lib/src/core/selectRange/index.ts b/packages/dooringx-lib/src/core/selectRange/index.ts index 1ff45f4..dcf22f5 100644 --- a/packages/dooringx-lib/src/core/selectRange/index.ts +++ b/packages/dooringx-lib/src/core/selectRange/index.ts @@ -2,7 +2,7 @@ import { IStoreData } from '../store/storetype'; import { deepCopy } from '../utils'; import style from '../../index.less'; import UserConfig from '../../config'; -import { getComponentRotatedStyle } from '../markline/calcRender'; +import { Sat } from './sat'; export interface SelectDataProps { selectDiv: HTMLDivElement | null; posx: number; @@ -60,8 +60,6 @@ function selectFocus(left: number, top: number, width: number, height: number, c const focusState = config.getFocusState(); const blocks = clonedata.block; let change = false; - const maxleft = left + width; - const maxtop = top + height; blocks.forEach((v) => { const l = v.left; const t = v.top; @@ -74,13 +72,21 @@ function selectFocus(left: number, top: number, width: number, height: number, c typeof h === 'number' && v.canDrag === true ) { - const style = getComponentRotatedStyle(v.rotate.value, w, h, l, t); - if ( - style.left >= left && - style.right <= maxleft && - style.top >= top && - style.bottom <= maxtop - ) { + const curItem = { + left: l, + top: t, + width: w, + height: h, + rotate: v.rotate.value, + }; + const res = Sat(curItem, { + left, + width, + height, + top, + rotate: 0, + }); + if (res) { change = true; v.focus = true; focusState.blocks.push(v); diff --git a/packages/dooringx-lib/src/core/selectRange/sat.ts b/packages/dooringx-lib/src/core/selectRange/sat.ts new file mode 100644 index 0000000..b1ac47b --- /dev/null +++ b/packages/dooringx-lib/src/core/selectRange/sat.ts @@ -0,0 +1,123 @@ +/* + * @Author: yehuozhili + * @Date: 2022-04-30 23:25:05 + * @LastEditors: yehuozhili + * @LastEditTime: 2022-05-01 19:16:08 + * @FilePath: \dooringx\packages\dooringx-lib\src\core\selectRange\sat.ts + */ + +import { angleToRadian } from '../utils'; + +interface BlockItem { + width: number; + left: number; + top: number; + height: number; + rotate: number; +} +function getCenter(item: BlockItem) { + return { x: item.left + item.width / 2, y: item.top + item.height / 2 }; +} +function revert({ x, y }: { x: number; y: number }) { + return { x: y, y: -x }; +} +function substract(a: { x: number; y: number }, b: { x: number; y: number }) { + return { x: a.x - b.x, y: a.y - b.y }; +} +function getSides(list: { x: number; y: number }[]) { + let len = list.length; + let res = []; + for (let j = 1, pre = list[0]; j < len; j++) { + let p = list[j]; + res.push(substract(p, pre)); + pre = p; + } + res.push(substract(list[0], list[len - 1])); + return res; +} +function len(axis: { x: number; y: number }) { + return Math.sqrt(axis.x * axis.x + axis.y * axis.y); +} +function dot(a: { x: number; y: number }, b: { x: number; y: number }) { + return a.x * b.x + a.y * b.y; +} +function getProjection(axis: { x: number; y: number }, list: { x: number; y: number }[]) { + let min = null; + let max = null; + for (let i = 0, l = list.length; i < l; i++) { + let p = list[i]; + let pro = dot(p, axis) / len(axis); + if (min === null || pro < min) { + min = pro; + } + if (max === null || pro > max) { + max = pro; + } + } + return { min: min, max: max }; +} + +function getOriginPoint(item: BlockItem) { + const center = getCenter(item); + let a = center.x; + let b = center.y; + const transfer = [ + { x: item.left, y: item.top }, + { x: item.left + item.width, y: item.top }, + { x: item.left + item.width, y: item.top + item.height }, + { x: item.left, y: item.top + item.height }, + ]; + const relativePoint: { x: number; y: number }[] = []; + const rootPoint = transfer.map((v) => { + const x0 = v.x; + const y0 = v.y; + const rx = + a + + (x0 - a) * Math.cos(angleToRadian(item.rotate)) - + (y0 - b) * Math.sin(angleToRadian(item.rotate)); + const ry = + b + + (x0 - a) * Math.sin(angleToRadian(item.rotate)) + + (y0 - b) * Math.cos(angleToRadian(item.rotate)); + relativePoint.push({ x: a - rx, y: b - ry }); + return { x: rx, y: ry }; + }); + + return { rootPoint, relativePoint }; +} + +function polygonsCollisionTest(A: BlockItem, B: BlockItem) { + const resa = getOriginPoint(A); + const resb = getOriginPoint(B); + const sidesa = getSides(resa.relativePoint); + const sidesb = getSides(resb.relativePoint); + const sides = sidesa.concat(sidesb); + for (let j = 0, l = sides.length; j < l; j++) { + let axis = revert(sides[j]); + let proA = getProjection(axis, resa.rootPoint), + proB = getProjection(axis, resb.rootPoint); + if (isOverlay(proA, proB)) { + return false; + } + } + + return true; +} +function isOverlay(proA: any, proB: any) { + let min, max; + if (proA.min < proB.min) { + min = proA.min; + } else { + min = proB.min; + } + if (proA.max > proB.max) { + max = proA.max; + } else { + max = proB.max; + } + return proA.max - proA.min + (proB.max - proB.min) < max - min; +} + +export function Sat(v: BlockItem, select: BlockItem) { + return polygonsCollisionTest(v, select); +}