Skip to content

Commit

Permalink
Merge pull request #323 from idrawjs/dev-v0.4
Browse files Browse the repository at this point in the history
feat: improve renderer and middleware
  • Loading branch information
chenshenhai authored Jun 8, 2024
2 parents b167d07 + ac60ce4 commit ac206ca
Show file tree
Hide file tree
Showing 12 changed files with 114 additions and 83 deletions.
8 changes: 7 additions & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ import { Cursor } from './lib/cursor';
export { eventChange } from './config';

// export { MiddlewareSelector } from './middleware/selector';
export { MiddlewareSelector, middlewareEventSelect, middlewareEventSelectClear, middlewareEventSelectInGroup } from './middleware/selector';
export {
MiddlewareSelector,
middlewareEventSelect,
middlewareEventSelectClear,
middlewareEventSelectInGroup,
middlewareEventSnapToGrid
} from './middleware/selector';
export { MiddlewareScroller } from './middleware/scroller';
export { MiddlewareScaler, middlewareEventScale } from './middleware/scaler';
export { MiddlewareRuler, middlewareEventRuler } from './middleware/ruler';
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/middleware/selector/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ export const keySelectedReferenceYLines = Symbol(`${key}_selectedReferenceYLines
export const keyGroupQueue = Symbol(`${key}_groupQueue`); // Array<Element<'group'>> | []
export const keyGroupQueueVertexesList = Symbol(`${key}_groupQueueVertexesList`); // Array<ViewRectVertexes> | []
export const keyIsMoving = Symbol(`${key}_isMoving`); // boolean | null
export const keyEnableSelectInGroup = Symbol(`${key}_canSelectInGroup`);
export const keyEnableSelectInGroup = Symbol(`${key}_enableSelectInGroup`);
export const keyEnableSnapToGrid = Symbol(`${key}_enableSnapToGrid`);

export const keyDebugElemCenter = Symbol(`${key}_debug_elemCenter`);
export const keyDebugStartVertical = Symbol(`${key}_debug_startVertical`);
Expand Down Expand Up @@ -44,3 +45,5 @@ export const middlewareEventSelect: string = '@middleware/select';
export const middlewareEventSelectClear: string = '@middleware/select-clear';

export const middlewareEventSelectInGroup: string = '@middleware/select-in-group';

export const middlewareEventSnapToGrid: string = '@middleware/snap-to-grid';
74 changes: 46 additions & 28 deletions packages/core/src/middleware/selector/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
middlewareEventSelect,
middlewareEventSelectClear,
middlewareEventSelectInGroup,
middlewareEventSnapToGrid,
keyActionType,
keyResizeType,
keyAreaStart,
Expand All @@ -64,6 +65,7 @@ import {
keySelectedReferenceYLines,
keyIsMoving,
keyEnableSelectInGroup,
keyEnableSnapToGrid,
controllerSize
// keyDebugElemCenter,
// keyDebugEnd0,
Expand All @@ -79,7 +81,7 @@ import { eventChange } from '../../config';
export { keySelectedElementList, keyActionType, keyResizeType, keyGroupQueue };
export type { DeepSelectorSharedStorage, ActionType };

export { middlewareEventSelect, middlewareEventSelectClear, middlewareEventSelectInGroup };
export { middlewareEventSelect, middlewareEventSelectClear, middlewareEventSelectInGroup, middlewareEventSnapToGrid };

export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage, CoreEventMap> = (opts) => {
const { viewer, sharer, boardContent, calculator, eventHub } = opts;
Expand All @@ -88,6 +90,7 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage, Core
let inBusyMode: 'resize' | 'drag' | 'drag-list' | 'area' | null = null;

sharer.setSharedStorage(keyActionType, null);
sharer.setSharedStorage(keyEnableSnapToGrid, true);

const getActiveElements = () => {
return sharer.getSharedStorage(keySelectedElementList);
Expand Down Expand Up @@ -213,6 +216,10 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage, Core
viewer.drawFrame();
};

const setSnapToSnapCallback = (e: { enable: boolean }) => {
sharer.setSharedStorage(keyEnableSnapToGrid, !!e.enable);
};

const selectInGroupCallback = (e: { enable: boolean }) => {
sharer.setSharedStorage(keyEnableSelectInGroup, !!e.enable);
};
Expand All @@ -223,12 +230,14 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage, Core
eventHub.on(middlewareEventSelect, selectCallback);
eventHub.on(middlewareEventSelectClear, selectClearCallback);
eventHub.on(middlewareEventSelectInGroup, selectInGroupCallback);
eventHub.on(middlewareEventSnapToGrid, setSnapToSnapCallback);
},

disuse() {
eventHub.off(middlewareEventSelect, selectCallback);
eventHub.off(middlewareEventSelectClear, selectClearCallback);
eventHub.off(middlewareEventSelectInGroup, selectInGroupCallback);
eventHub.off(middlewareEventSnapToGrid, setSnapToSnapCallback);
},

hover: (e: PointWatcherEvent) => {
Expand Down Expand Up @@ -435,6 +444,8 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage, Core
const actionType = sharer.getSharedStorage(keyActionType);
const groupQueue = sharer.getSharedStorage(keyGroupQueue);

const enableSnapToGrid = sharer.getSharedStorage(keyEnableSnapToGrid);

if (actionType === 'drag') {
inBusyMode = 'drag';
if (data && elems?.length === 1 && start && end && elems[0]?.operations?.lock !== true) {
Expand All @@ -443,27 +454,29 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage, Core
let totalMoveX = calculator.toGridNum(moveX / scale);
let totalMoveY = calculator.toGridNum(moveY / scale);

const referenceInfo = calcReferenceInfo(elems[0].uuid, {
calculator,
data,
groupQueue,
viewScaleInfo,
viewSizeInfo
});
try {
if (referenceInfo) {
if (is.x(referenceInfo.offsetX) && referenceInfo.offsetX !== null) {
totalMoveX = calculator.toGridNum(totalMoveX + referenceInfo.offsetX);
}
if (is.y(referenceInfo.offsetY) && referenceInfo.offsetY !== null) {
totalMoveY = calculator.toGridNum(totalMoveY + referenceInfo.offsetY);
if (enableSnapToGrid === true) {
const referenceInfo = calcReferenceInfo(elems[0].uuid, {
calculator,
data,
groupQueue,
viewScaleInfo,
viewSizeInfo
});
try {
if (referenceInfo) {
if (is.x(referenceInfo.offsetX) && referenceInfo.offsetX !== null) {
totalMoveX = calculator.toGridNum(totalMoveX + referenceInfo.offsetX);
}
if (is.y(referenceInfo.offsetY) && referenceInfo.offsetY !== null) {
totalMoveY = calculator.toGridNum(totalMoveY + referenceInfo.offsetY);
}
sharer.setSharedStorage(keySelectedReferenceXLines, referenceInfo.xLines);
sharer.setSharedStorage(keySelectedReferenceYLines, referenceInfo.yLines);
}
sharer.setSharedStorage(keySelectedReferenceXLines, referenceInfo.xLines);
sharer.setSharedStorage(keySelectedReferenceYLines, referenceInfo.yLines);
} catch (err) {
// eslint-disable-next-line no-console
console.error(err);
}
} catch (err) {
// eslint-disable-next-line no-console
console.error(err);
}

elems[0].x = calculator.toGridNum(elems[0].x + totalMoveX);
Expand Down Expand Up @@ -733,6 +746,7 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage, Core
const groupQueue: Element<'group'>[] = sharedStore[keyGroupQueue];
const groupQueueVertexesList: ViewRectVertexes[] = sharedStore[keyGroupQueueVertexesList];
const isMoving = sharedStore[keyIsMoving];
const enableSnapToGrid = sharedStore[keyEnableSnapToGrid];

const drawBaseOpts = { calculator, viewScaleInfo, viewSizeInfo };
// const selectedElementController = sharedStore[keySelectedElementController];
Expand Down Expand Up @@ -775,10 +789,12 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage, Core
if (actionType === 'drag') {
const xLines = sharer.getSharedStorage(keySelectedReferenceXLines);
const yLines = sharer.getSharedStorage(keySelectedReferenceYLines);
drawReferenceLines(overlayContext, {
xLines,
yLines
});
if (enableSnapToGrid === true) {
drawReferenceLines(overlayContext, {
xLines,
yLines
});
}
}
}
} else {
Expand Down Expand Up @@ -807,10 +823,12 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage, Core
if (actionType === 'drag') {
const xLines = sharer.getSharedStorage(keySelectedReferenceXLines);
const yLines = sharer.getSharedStorage(keySelectedReferenceYLines);
drawReferenceLines(overlayContext, {
xLines,
yLines
});
if (enableSnapToGrid === true) {
drawReferenceLines(overlayContext, {
xLines,
yLines
});
}
}
} else if (actionType === 'area' && areaStart && areaEnd) {
drawArea(overlayContext, { start: areaStart, end: areaEnd });
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/middleware/selector/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
keySelectedReferenceYLines,
keyIsMoving,
keyEnableSelectInGroup,
keyEnableSnapToGrid,

// debug keys
keyDebugElemCenter,
Expand Down Expand Up @@ -107,6 +108,7 @@ export type DeepSelectorSharedStorage = {
[keySelectedReferenceYLines]: Array<PointSize[]>;
[keyIsMoving]: boolean | null;
[keyEnableSelectInGroup]: boolean | null;
[keyEnableSnapToGrid]: boolean | null;

[keyDebugElemCenter]: PointSize | null;
[keyDebugEnd0]: PointSize | null;
Expand Down
41 changes: 1 addition & 40 deletions packages/figma/dev/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,53 +25,14 @@ async function action(params: { data: Data }) {
idraw.centerContent();
}

// async function main() {
// if (targetFile) {
// const filePath = `/demo/lab-figma-to-elements/figma/${targetFile}`;
// const figma = await fetch(filePath).then((res) => res.blob());
// const buffer = await figma.arrayBuffer();

// {
// const filePath = `/demo/lab-figma-to-elements/figma/${targetFile}`;
// const figma = await fetch(filePath).then((res) => res.blob());
// const buff = await figma.arrayBuffer();
// const bytes = new Uint8Array(buff);
// const figmaMap = await figmaBytesToMap(bytes);
// console.log('figmaMap ===== ', figmaMap);
// const data = await figmaMapToIDrawData(figmaMap);
// console.log('object ===== ', data);
// }

// let data = await figmaBufferToIDrawData(buffer);
// // console.log('object ====== ', object);

// // const map = figmaObjectToMap(object);
// // console.log('map ==== ', map);

// // const tree = figmaObjectToTree(object);
// // console.log('tree ==== ', tree);

// // let data = figmaObjectToIDrawData(object);
// // TODO
// data = {
// elements: (data.elements[0] as Element<'group'>).detail.children
// };
// // console.log('data ===== ', data);
// await action({ data });
// } else {
// list();
// }
// }

async function main() {
const filePath = `/dev/figma/iOS-Native-Wireframes-Community.fig`;
console.log('filePath ------ ', filePath);
const figma = await fetch(filePath).then((res) => res.blob());
const arrayBuffer = await figma.arrayBuffer();
const buffer = new Uint8Array(arrayBuffer);

let data: Data = await figmaBytesToIDrawData(buffer);
// // TODO

data = {
elements: (data.elements[0] as Element<'group'>).detail.children,
global: data.elements[0].global
Expand Down
6 changes: 5 additions & 1 deletion packages/idraw/src/idraw.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Core, middlewareEventSelectInGroup } from '@idraw/core';
import { Core, middlewareEventSelectInGroup, middlewareEventSnapToGrid } from '@idraw/core';
import type {
PointSize,
IDrawOptions,
Expand Down Expand Up @@ -72,6 +72,10 @@ export class iDraw {
this.#core.trigger(middlewareEventSelectInGroup, {
enable: !!status
});
} else if (feat === 'snapToGrid') {
this.#core.trigger(middlewareEventSnapToGrid, {
enable: !!status
});
}
}

Expand Down
1 change: 0 additions & 1 deletion packages/idraw/src/mode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,5 @@ export function changeMode(mode: IDrawMode, core: Core<IDrawEvent>, store: Store
store.set('enableDrag', enableDrag);
store.set('enableRuler', enableRuler);
store.set('enableInfo', enableInfo);

runMiddlewares(core, store);
}
4 changes: 3 additions & 1 deletion packages/renderer/src/draw/group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ import { drawHTML } from './html';
import { drawBox, drawBoxShadow, getOpacity } from './box';
import { drawPath } from './path';

const visiableMinSize = 0.4; // px;

export function drawElement(ctx: ViewContext2D, elem: Element<ElementType>, opts: RendererDrawElementOptions) {
if (elem?.operations?.invisible === true) {
return;
}
const { w, h } = elem;
const { scale } = opts.viewScaleInfo;
if ((scale < 1 && (w * scale < 1 || h * scale < 1)) || opts.parentOpacity === 0) {
if ((scale < 1 && (w * scale < visiableMinSize || h * scale < visiableMinSize)) || opts.parentOpacity === 0) {
return;
}

Expand Down
46 changes: 41 additions & 5 deletions packages/renderer/src/draw/path.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Element, RendererDrawElementOptions, ViewContext2D } from '@idraw/types';
import type { Element, RendererDrawElementOptions, ViewContext2D, LinearGradientColor, RadialGradientColor } from '@idraw/types';
import { rotateElement, generateSVGPath, calcViewElementSize } from '@idraw/util';
import { drawBox, drawBoxShadow } from './box';

Expand All @@ -13,13 +13,41 @@ export function drawPath(ctx: ViewContext2D, elem: Element<'path'>, opts: Render
const viewOriginY = originY * scaleH;
const internalX = x - viewOriginX;
const internalY = y - viewOriginY;
const { clipPath, clipPathStrokeColor, clipPathStrokeWidth, ...restDetail } = elem.detail as any;

const scaleNum = viewScaleInfo.scale * viewSizeInfo.devicePixelRatio;
const viewElem = { ...elem, ...{ x, y, w, h, angle } };
// rotateElement(ctx, { x: viewOriginX, y: viewOriginY, w, h, angle }, () => {

let boxViewElem = { ...viewElem };
boxViewElem.detail = restDetail;
let boxOriginElem = { ...elem };
boxOriginElem.detail = restDetail;

if (detail.fill && detail.fill !== 'string' && (detail.fill as LinearGradientColor | RadialGradientColor)?.type?.includes('gradient')) {
boxViewElem = {
...viewElem,
...{
detail: {
...viewElem.detail,
...{
background: detail.fill,
clipPath: {
commands: detail.commands,
originX,
originY,
originW,
originH
}
}
}
}
};
boxOriginElem.detail = { ...boxViewElem.detail };
}

rotateElement(ctx, { x, y, w, h, angle }, () => {
drawBox(ctx, viewElem, {
originElem: elem,
drawBox(ctx, boxViewElem, {
originElem: boxOriginElem,
calcElemSize: { x, y, w, h, angle },
viewScaleInfo,
viewSizeInfo,
Expand All @@ -41,8 +69,16 @@ export function drawPath(ctx: ViewContext2D, elem: Element<'path'>, opts: Render
ctx.scale((scaleNum * scaleW) / viewScaleInfo.scale, (scaleNum * scaleH) / viewScaleInfo.scale);
const pathStr = generateSVGPath(detail.commands || []);
const path2d = new Path2D(pathStr);

if (detail.fill) {
if (typeof detail.fill === 'string') {
ctx.fillStyle = detail.fill;
} else {
ctx.fillStyle = 'transparent';
}
}

if (detail.fill) {
ctx.fillStyle = detail.fill;
ctx.fill(path2d, fillRule as CanvasFillRule);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/renderer/src/draw/rect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { drawBox, drawBoxShadow } from './box';

export function drawRect(ctx: ViewContext2D, elem: Element<'rect'>, opts: RendererDrawElementOptions) {
const { viewScaleInfo, viewSizeInfo, parentOpacity } = opts;
const { x, y, w, h, angle } = calcViewElementSize(elem, { viewScaleInfo, viewSizeInfo }) || elem;
const { x, y, w, h, angle } = calcViewElementSize(elem, { viewScaleInfo }) || elem;

const viewElem = { ...elem, ...{ x, y, w, h, angle } };
rotateElement(ctx, { x, y, w, h, angle }, () => {
Expand Down
Loading

0 comments on commit ac206ca

Please sign in to comment.