feat: support custom style for middleware layout selector

This commit is contained in:
chenshenhai 2024-07-06 21:37:14 +08:00
parent 6cbf7673a8
commit e2eaa25a97
13 changed files with 79 additions and 97 deletions

View file

@ -1,3 +1,5 @@
import type { MiddlewareLayoutSelectorStyle } from '@idraw/types';
export const key = 'LAYOUT_SELECT';
// export const keyHoverElement = Symbol(`${key}_hoverElementSize`);
export const keyLayoutActionType = Symbol(`${key}_layoutActionType`); // 'resize' | null = null;
@ -6,7 +8,11 @@ export const keyLayoutController = Symbol(`${key}_layoutController`); // Element
export const keyLayoutIsHover = Symbol(`${key}_layoutIsHover`); // boolean | null
export const keyLayoutIsSelected = Symbol(`${key}_layoutIsSelected`); // boolean | null
// export const selectColor = '#1973ba';
export const selectColor = '#b331c9';
export const disableColor = '#5b5959b5';
// const selectColor = '#b331c9';
// const disabledColor = '#5b5959b5';
export const controllerSize = 10;
export const defaultStyle: MiddlewareLayoutSelectorStyle = {
activeColor: '#b331c9'
};

View file

@ -1,16 +1,22 @@
import type { BoardMiddleware, ElementSize, Point } from '@idraw/types';
import type { BoardMiddleware, ElementSize, Point, MiddlewareLayoutSelectorConfig } from '@idraw/types';
import { calcLayoutSizeController, isViewPointInVertexes, getViewScaleInfoFromSnapshot, isViewPointInElementSize, calcViewElementSize } from '@idraw/util';
import type { LayoutSelectorSharedStorage, ControlType } from './types';
import { keyLayoutActionType, keyLayoutController, keyLayoutControlType, keyLayoutIsHover, keyLayoutIsSelected, controllerSize } from './config';
import { keyLayoutActionType, keyLayoutController, keyLayoutControlType, keyLayoutIsHover, keyLayoutIsSelected, controllerSize, defaultStyle } from './config';
import { keyActionType as keyElementActionType, keyHoverElement, middlewareEventSelectClear } from '../selector';
import { drawLayoutController, drawLayoutHover } from './util';
import { eventChange } from '../../config';
export { keyLayoutIsSelected };
export const MiddlewareLayoutSelector: BoardMiddleware<LayoutSelectorSharedStorage> = (opts) => {
export const MiddlewareLayoutSelector: BoardMiddleware<LayoutSelectorSharedStorage, any, MiddlewareLayoutSelectorConfig> = (opts, config) => {
const { sharer, boardContent, calculator, viewer, eventHub } = opts;
const { overlayContext } = boardContent;
const innerConfig = {
...defaultStyle,
...config
};
const { activeColor } = innerConfig;
const style = { activeColor };
let prevPoint: Point | null = null;
let prevIsHover: boolean | null = null;
@ -327,11 +333,11 @@ export const MiddlewareLayoutSelector: BoardMiddleware<LayoutSelectorSharedStora
if (layoutIsHover === true) {
const viewSize = calcViewElementSize(size, { viewScaleInfo });
drawLayoutHover(overlayContext, { layoutSize: viewSize });
drawLayoutHover(overlayContext, { layoutSize: viewSize, style });
}
if ((layoutActionType && ['resize'].includes(layoutActionType)) || layoutIsSelected === true) {
drawLayoutController(overlayContext, { controller, operations: activeStore.data.layout.operations || {} });
drawLayoutController(overlayContext, { controller, style });
}
}
},

View file

@ -1,7 +1,7 @@
import type { ViewContext2D, LayoutSizeController, DataLayout, ViewRectVertexes, PointSize, ElementSize } from '@idraw/types';
import { selectColor, disableColor } from './config';
import type { ViewContext2D, LayoutSizeController, ViewRectVertexes, PointSize, ElementSize, MiddlewareLayoutSelectorStyle } from '@idraw/types';
function drawControllerBox(ctx: ViewContext2D, boxVertexes: ViewRectVertexes) {
function drawControllerBox(ctx: ViewContext2D, boxVertexes: ViewRectVertexes, style: MiddlewareLayoutSelectorStyle) {
const { activeColor } = style;
ctx.setLineDash([]);
ctx.fillStyle = '#FFFFFF';
ctx.beginPath();
@ -12,7 +12,7 @@ function drawControllerBox(ctx: ViewContext2D, boxVertexes: ViewRectVertexes) {
ctx.closePath();
ctx.fill();
ctx.strokeStyle = selectColor;
ctx.strokeStyle = activeColor;
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(boxVertexes[0].x, boxVertexes[0].y);
@ -23,30 +23,14 @@ function drawControllerBox(ctx: ViewContext2D, boxVertexes: ViewRectVertexes) {
ctx.stroke();
}
function drawControllerCross(ctx: ViewContext2D, opts: { vertexes: ViewRectVertexes; strokeStyle: string; lineWidth: number }) {
const { vertexes, strokeStyle, lineWidth } = opts;
ctx.setLineDash([]);
ctx.strokeStyle = strokeStyle;
ctx.lineWidth = lineWidth;
ctx.beginPath();
ctx.moveTo(vertexes[0].x, vertexes[0].y);
ctx.lineTo(vertexes[2].x, vertexes[2].y);
ctx.closePath();
ctx.stroke();
ctx.beginPath();
ctx.moveTo(vertexes[1].x, vertexes[1].y);
ctx.lineTo(vertexes[3].x, vertexes[3].y);
ctx.closePath();
ctx.stroke();
}
function drawControllerLine(ctx: ViewContext2D, opts: { start: PointSize; end: PointSize; centerVertexes: ViewRectVertexes; disabled: boolean }) {
const { start, end, centerVertexes, disabled } = opts;
const lineWidth = disabled === true ? 1 : 2;
const strokeStyle = disabled === true ? disableColor : selectColor;
function drawControllerLine(
ctx: ViewContext2D,
opts: { start: PointSize; end: PointSize; centerVertexes: ViewRectVertexes; style: MiddlewareLayoutSelectorStyle }
) {
const { start, end, style } = opts;
const { activeColor } = style;
const lineWidth = 2;
const strokeStyle = activeColor;
ctx.setLineDash([]);
ctx.strokeStyle = strokeStyle;
ctx.lineWidth = lineWidth;
@ -55,71 +39,41 @@ function drawControllerLine(ctx: ViewContext2D, opts: { start: PointSize; end: P
ctx.lineTo(end.x, end.y);
ctx.closePath();
ctx.stroke();
if (disabled === true) {
drawControllerCross(ctx, {
vertexes: centerVertexes,
lineWidth,
strokeStyle
});
}
}
export function drawLayoutController(
ctx: ViewContext2D,
opts: {
controller: LayoutSizeController;
operations: DataLayout['operations'];
style: MiddlewareLayoutSelectorStyle;
}
) {
// TODO
const { controller, operations } = opts;
const { controller, style } = opts;
const { topLeft, topRight, bottomLeft, bottomRight, topMiddle, rightMiddle, bottomMiddle, leftMiddle } = controller;
drawControllerLine(ctx, { start: topLeft.center, end: topRight.center, centerVertexes: topMiddle.vertexes, disabled: !!operations?.disabledTop });
drawControllerLine(ctx, { start: topRight.center, end: bottomRight.center, centerVertexes: rightMiddle.vertexes, disabled: !!operations?.disabledRight });
drawControllerLine(ctx, { start: bottomRight.center, end: bottomLeft.center, centerVertexes: bottomMiddle.vertexes, disabled: !!operations?.disabledBottom });
drawControllerLine(ctx, { start: bottomLeft.center, end: topLeft.center, centerVertexes: leftMiddle.vertexes, disabled: !!operations?.disabledLeft });
drawControllerLine(ctx, { start: topLeft.center, end: topRight.center, centerVertexes: topMiddle.vertexes, style });
drawControllerLine(ctx, { start: topRight.center, end: bottomRight.center, centerVertexes: rightMiddle.vertexes, style });
drawControllerLine(ctx, { start: bottomRight.center, end: bottomLeft.center, centerVertexes: bottomMiddle.vertexes, style });
drawControllerLine(ctx, { start: bottomLeft.center, end: topLeft.center, centerVertexes: leftMiddle.vertexes, style });
const disabledOpts = {
lineWidth: 1,
strokeStyle: disableColor
};
if (operations?.disabledTopLeft === true) {
drawControllerCross(ctx, { vertexes: topLeft.vertexes, ...disabledOpts });
} else {
drawControllerBox(ctx, topLeft.vertexes);
}
if (operations?.disabledTopRight === true) {
drawControllerCross(ctx, { vertexes: topRight.vertexes, ...disabledOpts });
} else {
drawControllerBox(ctx, topRight.vertexes);
}
if (operations?.disabledBottomRight === true) {
drawControllerCross(ctx, { vertexes: bottomRight.vertexes, ...disabledOpts });
} else {
drawControllerBox(ctx, bottomRight.vertexes);
}
if (operations?.disabledBottomLeft === true) {
drawControllerCross(ctx, { vertexes: bottomLeft.vertexes, ...disabledOpts });
} else {
drawControllerBox(ctx, bottomLeft.vertexes);
}
drawControllerBox(ctx, topLeft.vertexes, style);
drawControllerBox(ctx, topRight.vertexes, style);
drawControllerBox(ctx, bottomRight.vertexes, style);
drawControllerBox(ctx, bottomLeft.vertexes, style);
}
export function drawLayoutHover(
ctx: ViewContext2D,
opts: {
layoutSize: ElementSize;
style: MiddlewareLayoutSelectorStyle;
}
) {
const { layoutSize } = opts;
const { layoutSize, style } = opts;
const { activeColor } = style;
const { x, y, w, h } = layoutSize;
ctx.setLineDash([]);
ctx.strokeStyle = selectColor;
ctx.strokeStyle = activeColor;
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(x, y);

View file

@ -191,7 +191,6 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage, Core
sharer.setSharedStorage(keySelectedElementController, null);
sharer.setSharedStorage(keySelectedElementPosition, []);
sharer.setSharedStorage(keyIsMoving, null);
sharer.setSharedStorage(keyEnableSelectInGroup, null);
};
clear();

View file

@ -62,8 +62,8 @@ export function nodeToBaseDetail(node: FigmaNode<FigmaNodeType>): ElementBaseDet
opacity
} = node as FigmaNode<'ROUNDED_RECTANGLE'>;
const background = figmaPaintsToColor(fillPaints, {
w: node.size.x,
h: node.size.y
w: node?.size?.x || 0,
h: node?.size?.y || 0
});
if (background) {
detail.background = background;

View file

@ -80,16 +80,18 @@ async function nestedNodeToGroupElement<T extends 'CANVAS' | 'FRAME' | 'SYMBOL'
const overrideData = mergeNodeOverrideData<T>(figmaNode as any, opts);
const node: FigmaNode = { ...figmaNode, ...overrideData } as FigmaNode;
const elemBase = nodeToElementBase(node);
const baseDetail = nodeToBaseDetail(node);
let group: Element<'group'> = {
...elemBase,
type: 'group',
detail: {
...baseDetail,
children: [],
overflow: 'visible'
},
operations: nodeToOperations(node)
};
// const baseDetail = nodeToBaseDetail(treeNode.node);
if ((node as unknown as FigmaNode<'FRAME'>).type === 'FRAME') {
// const background = figmaPaintsToHexColor(node.fillPaints);
const background = figmaPaintsToColor(node.fillPaints, { w: elemBase.w, h: elemBase.h });
@ -117,7 +119,7 @@ async function nestedNodeToGroupElement<T extends 'CANVAS' | 'FRAME' | 'SYMBOL'
}
if (['FRAME', 'BOOLEAN_OPERATION'].includes(node.type)) {
if (group.x === 0 || group.y === 0) {
if (group.w === 0 || group.h === 0) {
const size = resetGroupSize(group);
group = {
...size,

View file

@ -62,8 +62,8 @@ export async function figmaMapToIDrawData(figmaMap: FigmaMap): Promise<Data> {
const canvasFig: FigmaMap['canvas.fig'] = figmaMap['canvas.fig'];
const { root } = canvasFig;
// // TODO
// console.log('root =', root);
// TODO
console.log('root =', root);
if (Array.isArray(root.children)) {
for (let i = 0; i < root.children.length; i++) {

View file

@ -33,6 +33,9 @@ const opts = {
hoverThumbBorderColor: '#FF0000EE',
activeThumbBackground: '#FF00005E',
activeThumbBorderColor: '#FF0000F0'
},
layoutSelector: {
activeColor: '#00FF00'
}
}
};

View file

@ -21,7 +21,8 @@ export function getDefaultStorage(): IDrawStorage {
selector: {},
info: {},
ruler: {},
scroller: {}
scroller: {},
layoutSelector: {}
}
};
return storage;
@ -32,11 +33,12 @@ export function parseStyles(opts: IDrawSettings) {
selector: {},
ruler: {},
info: {},
scroller: {}
scroller: {},
layoutSelector: {}
};
if (opts.styles) {
// selector
const { selector, info, ruler, scroller } = opts.styles;
const { selector, info, ruler, scroller, layoutSelector } = opts.styles;
if (istype.string(selector?.activeColor)) {
styles.selector.activeColor = selector?.activeColor;
}
@ -100,6 +102,11 @@ export function parseStyles(opts: IDrawSettings) {
if (istype.string(scroller?.activeThumbBorderColor)) {
styles.scroller.activeThumbBorderColor = scroller?.activeThumbBorderColor;
}
// layoutSelector
if (istype.string(layoutSelector?.activeColor)) {
styles.layoutSelector.activeColor = layoutSelector?.activeColor;
}
}
return styles;
}

View file

@ -122,7 +122,8 @@ export {
calcElementViewRectInfo,
calcElementOriginRectInfo,
calcElementViewRectInfoMap,
sortElementsViewVisiableInfoMap
sortElementsViewVisiableInfoMap,
flatElementList
} from '@idraw/util';
export { iDraw } from './idraw';
export { eventKeys } from './event';

View file

@ -27,7 +27,7 @@ export function runMiddlewares(core: Core<IDrawEvent>, store: Store<IDrawStorage
}
if (enableSelect === true) {
core.use(MiddlewareLayoutSelector);
core.use(MiddlewareLayoutSelector, styles?.layoutSelector);
core.use(MiddlewareSelector, styles?.selector);
} else if (enableSelect === false) {
core.disuse(MiddlewareLayoutSelector);
@ -72,7 +72,7 @@ export function changeMode(mode: IDrawMode, core: Core<IDrawEvent>, store: Store
let enableTextEdit: boolean = false;
let enableDrag: boolean = false;
let enableRuler: boolean = false;
const enableInfo: boolean = true;
let enableInfo: boolean = false;
let innerMode: IDrawMode = 'select';
store.set('mode', innerMode);
@ -87,6 +87,7 @@ export function changeMode(mode: IDrawMode, core: Core<IDrawEvent>, store: Store
enableScale = true;
enableScroll = true;
enableSelect = true;
enableInfo = true;
enableTextEdit = true;
enableDrag = false;
enableRuler = true;

View file

@ -1,5 +1,5 @@
import type { CoreOptions } from './core';
import type { MiddlewareSelectorStyle, MiddlewareInfoStyle, MiddlewareRulerStyle, MiddlewareScrollerStyle } from './middleware';
import type { MiddlewareSelectorStyle, MiddlewareInfoStyle, MiddlewareRulerStyle, MiddlewareScrollerStyle, MiddlewareLayoutSelectorStyle } from './middleware';
export type IDrawMode = 'select' | 'drag' | 'readOnly';
@ -12,6 +12,7 @@ export interface IDrawSettings {
info?: Partial<MiddlewareInfoStyle>;
ruler?: Partial<MiddlewareRulerStyle>;
scroller?: Partial<MiddlewareScrollerStyle>;
layoutSelector?: Partial<MiddlewareLayoutSelectorStyle>;
};
}

View file

@ -16,7 +16,6 @@ export type MiddlewareInfoStyle = {
textBackground: string;
textColor: string;
};
export type MiddlewareInfoConfig = MiddlewareInfoStyle & {};
export type MiddlewareRulerStyle = {
@ -28,7 +27,6 @@ export type MiddlewareRulerStyle = {
gridPrimaryColor: string;
selectedAreaColor: string;
};
export type MiddlewareRulerConfig = MiddlewareRulerStyle & {};
export type MiddlewareScrollerStyle = {
@ -39,5 +37,9 @@ export type MiddlewareScrollerStyle = {
activeThumbBackground: string;
activeThumbBorderColor: string;
};
export type MiddlewareScrollerConfig = MiddlewareScrollerStyle & {};
export type MiddlewareLayoutSelectorStyle = {
activeColor: string;
};
export type MiddlewareLayoutSelectorConfig = MiddlewareLayoutSelectorStyle & {};