Merge pull request #348 from idrawjs/dev-v0.4

feat: implement reset style feature
This commit is contained in:
Deepsea 2024-08-24 16:40:13 +08:00 committed by GitHub
commit 40aefff723
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 244 additions and 92 deletions

View file

@ -397,6 +397,15 @@ export class Board<T extends BoardExtendEventMap = BoardExtendEventMap> {
}
}
resetMiddlewareConfig<C extends any = any>(middleware: BoardMiddleware<any, any, any>, config?: Partial<C>) {
if (this.#middlewareMap.has(middleware)) {
const item = this.#middlewareMap.get(middleware);
if (item) {
item.middlewareObject.resetConfig?.(config as any);
}
}
}
scale(opts: { scale: number; point: PointSize; ignoreUpdateVisibleStatus?: boolean }) {
const viewer = this.#viewer;
const { ignoreUpdateVisibleStatus } = opts;

View file

@ -73,6 +73,10 @@ export class Core<E extends CoreEventMap = CoreEventMap> {
this.#board.disuse(middleware);
}
resetMiddlewareConfig<C extends any = any>(middleware: BoardMiddleware<any, any, any>, config?: Partial<C>) {
this.#board.resetMiddlewareConfig(middleware, config);
}
setData(
data: Data,
opts?: {

View file

@ -19,15 +19,10 @@ export const MiddlewareInfo: BoardMiddleware<
> = (opts, config) => {
const { boardContent, calculator, eventHub } = opts;
const { overlayContext } = boardContent;
const innerConfig = {
let innerConfig = {
...defaltStyle,
...config
};
const { textBackground, textColor } = innerConfig;
const style = {
textBackground,
textColor
};
let showAngleInfo = true;
@ -46,7 +41,16 @@ export const MiddlewareInfo: BoardMiddleware<
eventHub.off(MIDDLEWARE_INTERNAL_EVENT_SHOW_INFO_ANGLE, showInfoAngleCallback);
},
resetConfig(config) {
innerConfig = { ...innerConfig, ...config };
},
beforeDrawFrame({ snapshot }) {
const { textBackground, textColor } = innerConfig;
const style = {
textBackground,
textColor
};
const { sharedStore } = snapshot;
const selectedElementList = sharedStore[keySelectedElementList];

View file

@ -24,12 +24,10 @@ export { keyLayoutIsSelected, keyLayoutIsBusyMoving };
export const MiddlewareLayoutSelector: BoardMiddleware<LayoutSelectorSharedStorage, CoreEventMap, MiddlewareLayoutSelectorConfig> = (opts, config) => {
const { sharer, boardContent, calculator, viewer, eventHub } = opts;
const { overlayContext } = boardContent;
const innerConfig = {
let innerConfig = {
...defaultStyle,
...config
};
const { activeColor } = innerConfig;
const style = { activeColor };
let prevPoint: Point | null = null;
let prevIsHoverContent: boolean | null = null;
@ -158,6 +156,10 @@ export const MiddlewareLayoutSelector: BoardMiddleware<LayoutSelectorSharedStora
resetController();
},
resetConfig(config) {
innerConfig = { ...innerConfig, ...config };
},
hover: (e) => {
if (sharer.getSharedStorage(keyLayoutIsBusyMoving) === true) {
return;
@ -362,6 +364,9 @@ export const MiddlewareLayoutSelector: BoardMiddleware<LayoutSelectorSharedStora
return;
}
const { activeColor } = innerConfig;
const style = { activeColor };
const { sharedStore, activeStore } = snapshot;
const layoutActionType = sharedStore[keyLayoutActionType];
const layoutIsHover = sharedStore[keyLayoutIsHoverContent];

View file

@ -8,20 +8,10 @@ import { coreEventKeys } from '../../config';
export const MiddlewareRuler: BoardMiddleware<DeepRulerSharedStorage, CoreEventMap, MiddlewareRulerConfig> = (opts, config) => {
const { boardContent, viewer, eventHub, calculator } = opts;
const { overlayContext, underlayContext } = boardContent;
const innerConfig = {
let innerConfig = {
...defaultStyle,
...config
};
const { background, borderColor, scaleColor, textColor, gridColor, gridPrimaryColor, selectedAreaColor } = innerConfig;
const style = {
background,
borderColor,
scaleColor,
textColor,
gridColor,
gridPrimaryColor,
selectedAreaColor
};
let show: boolean = true;
let showGrid: boolean = true;
@ -41,13 +31,31 @@ export const MiddlewareRuler: BoardMiddleware<DeepRulerSharedStorage, CoreEventM
return {
name: '@middleware/ruler',
use() {
eventHub.on(coreEventKeys.RULER, rulerCallback);
},
disuse() {
eventHub.off(coreEventKeys.RULER, rulerCallback);
},
resetConfig(config) {
innerConfig = { ...innerConfig, ...config };
},
beforeDrawFrame: ({ snapshot }) => {
const { background, borderColor, scaleColor, textColor, gridColor, gridPrimaryColor, selectedAreaColor } = innerConfig;
const style = {
background,
borderColor,
scaleColor,
textColor,
gridColor,
gridPrimaryColor,
selectedAreaColor
};
if (show === true) {
const viewScaleInfo = getViewScaleInfoFromSnapshot(snapshot);
const viewSizeInfo = getViewSizeInfoFromSnapshot(snapshot);

View file

@ -1,6 +1,15 @@
import type { Element, ViewScaleInfo, ViewSizeInfo, ViewContext2D, BoardViewerFrameSnapshot, ViewRectInfo, ViewCalculator } from '@idraw/types';
import type {
Element,
ViewScaleInfo,
ViewSizeInfo,
ViewContext2D,
BoardViewerFrameSnapshot,
ViewRectInfo,
ViewCalculator,
MiddlewareRulerStyle
} from '@idraw/types';
import { formatNumber, rotateByCenter, getViewScaleInfoFromSnapshot, getViewSizeInfoFromSnapshot } from '@idraw/util';
import type { DeepRulerSharedStorage, MiddlewareRulerStyle } from './types';
import type { DeepRulerSharedStorage } from './types';
import { keySelectedElementList, keyActionType } from '../selector';
import { rulerSize, fontSize, fontWeight, lineSize, fontFamily } from './config';
@ -201,14 +210,17 @@ export function drawRulerBackground(
const { background, borderColor } = style;
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(width + 1, 0);
// const basePosition = 0;
const basePosition = -1;
ctx.moveTo(basePosition, basePosition);
ctx.lineTo(width + 1, basePosition);
ctx.lineTo(width + 1, rulerSize);
ctx.lineTo(rulerSize, rulerSize);
ctx.lineTo(rulerSize, height + 1);
ctx.lineTo(0, height + 1);
ctx.lineTo(0, 0);
ctx.lineTo(basePosition, height + 1);
ctx.lineTo(basePosition, basePosition);
ctx.closePath();
ctx.fillStyle = background;
ctx.fill();
ctx.lineWidth = lineSize;

View file

@ -12,22 +12,11 @@ export const MiddlewareScroller: BoardMiddleware<DeepScrollerSharedStorage, any,
sharer.setSharedStorage(keyYThumbRect, null); // null | ElementSize
let isBusy: boolean = false;
const innerConfig = {
let innerConfig = {
...defaultStyle,
...config
};
const { thumbBackground, thumbBorderColor, hoverThumbBackground, hoverThumbBorderColor, activeThumbBackground, activeThumbBorderColor } = innerConfig;
const style = {
thumbBackground,
thumbBorderColor,
hoverThumbBackground,
hoverThumbBorderColor,
activeThumbBackground,
activeThumbBorderColor
};
// viewer.drawFrame();
const clear = () => {
sharer.setSharedStorage(keyPrevPoint, null); // null | Point;
@ -77,6 +66,11 @@ export const MiddlewareScroller: BoardMiddleware<DeepScrollerSharedStorage, any,
return {
name: '@middleware/scroller',
resetConfig(config) {
innerConfig = { ...innerConfig, ...config };
},
wheel: (e: BoardWatherWheelEvent) => {
viewer.scroll({
moveX: 0 - e.deltaX,
@ -142,6 +136,16 @@ export const MiddlewareScroller: BoardMiddleware<DeepScrollerSharedStorage, any,
}
},
beforeDrawFrame({ snapshot }) {
const { thumbBackground, thumbBorderColor, hoverThumbBackground, hoverThumbBorderColor, activeThumbBackground, activeThumbBorderColor } = innerConfig;
const style = {
thumbBackground,
thumbBorderColor,
hoverThumbBackground,
hoverThumbBorderColor,
activeThumbBackground,
activeThumbBorderColor
};
const { xThumbRect, yThumbRect } = drawScroller(overlayContext, { snapshot, style });
sharer.setSharedStorage(keyXThumbRect, xThumbRect);
sharer.setSharedStorage(keyYThumbRect, yThumbRect);

View file

@ -100,12 +100,10 @@ export const MiddlewareSelector: BoardMiddleware<
},
MiddlewareSelectorConfig
> = (opts, config) => {
const innerConfig = {
let innerConfig = {
...defaultStyle,
...config
};
const { activeColor, activeAreaColor, lockedColor, referenceColor } = innerConfig;
const style = { activeColor, activeAreaColor, lockedColor, referenceColor };
const { viewer, sharer, boardContent, calculator, eventHub } = opts;
const { overlayContext } = boardContent;
let prevPoint: Point | null = null;
@ -114,8 +112,8 @@ export const MiddlewareSelector: BoardMiddleware<
let inBusyMode: 'resize' | 'drag' | 'drag-list' | 'area' | null = null;
let hasChangedData: boolean | null = null;
const rotateControllerPattern = createRotateControllerPattern({
fill: style.activeColor,
let rotateControllerPattern = createRotateControllerPattern({
fill: innerConfig.activeColor,
devicePixelRatio: sharer.getActiveViewSizeInfo().devicePixelRatio
});
@ -280,6 +278,10 @@ export const MiddlewareSelector: BoardMiddleware<
eventHub.off(coreEventKeys.SNAP_TO_GRID, setSnapToSnapCallback);
},
resetConfig(config) {
innerConfig = { ...innerConfig, ...config };
},
hover: (e: PointWatcherEvent) => {
const layoutIsSelected = sharer.getSharedStorage(keyLayoutIsSelected);
const layoutIsBusyMoving = sharer.getSharedStorage(keyLayoutIsBusyMoving);
@ -852,8 +854,17 @@ export const MiddlewareSelector: BoardMiddleware<
},
beforeDrawFrame({ snapshot }) {
const { activeColor, activeAreaColor, lockedColor, referenceColor } = innerConfig;
const style = { activeColor, activeAreaColor, lockedColor, referenceColor };
const { activeStore, sharedStore } = snapshot;
const { scale, offsetLeft, offsetTop, offsetRight, offsetBottom, width, height, contextHeight, contextWidth, devicePixelRatio } = activeStore;
if (rotateControllerPattern.fill !== activeColor) {
rotateControllerPattern = createRotateControllerPattern({
fill: innerConfig.activeColor,
devicePixelRatio
});
}
const sharer = opts.sharer;
const viewScaleInfo = { scale, offsetLeft, offsetTop, offsetRight, offsetBottom };
@ -908,7 +919,7 @@ export const MiddlewareSelector: BoardMiddleware<
element: elem,
calculator,
hideControllers: !!isMoving && actionType === 'drag',
rotateControllerPattern,
rotateControllerPattern: rotateControllerPattern.context2d,
style
});
if (actionType === 'drag') {
@ -952,7 +963,7 @@ export const MiddlewareSelector: BoardMiddleware<
element: elem,
calculator,
hideControllers: !!isMoving && actionType === 'drag',
rotateControllerPattern,
rotateControllerPattern: rotateControllerPattern.context2d,
style
});
if (actionType === 'drag') {

View file

@ -3,7 +3,7 @@ import { createOffscreenContext2D } from '@idraw/util';
import { drawElement } from '@idraw/renderer';
import { createIconRotate } from './icon-rotate';
export function createRotateControllerPattern(opts: { fill: string; devicePixelRatio: number }): ViewContext2D {
export function createRotateControllerPattern(opts: { fill: string; devicePixelRatio: number }): { context2d: ViewContext2D; fill: string } {
const { fill, devicePixelRatio } = opts;
const iconRotate = createIconRotate({ fill });
const { w, h } = iconRotate;
@ -41,5 +41,7 @@ export function createRotateControllerPattern(opts: { fill: string; devicePixelR
parentOpacity: 1
});
return context2d;
// context2d.fill = fill;
return { context2d, fill };
}

View file

@ -2,42 +2,44 @@
import { iDraw } from '../src/index';
import { getData } from './data';
const styles = {
selector: {
activeColor: 'red',
activeAreaColor: '#FF00001C',
lockedColor: 'black',
referenceColor: 'green'
},
info: {
textBackground: 'yellow',
textColor: 'red'
},
ruler: {
background: '#0000FF1A',
borderColor: '#0000FF',
scaleColor: '#FF0000',
textColor: '#000000',
gridColor: '#0000FF1C',
gridPrimaryColor: '#0000FFAC',
selectedAreaColor: '#FF0000CC'
},
scroller: {
thumbBackground: '#FF00003A',
thumbBorderColor: '#FF00008A',
hoverThumbBackground: '#FF00006E',
hoverThumbBorderColor: '#FF0000EE',
activeThumbBackground: '#FF00005E',
activeThumbBorderColor: '#FF0000F0'
},
layoutSelector: {
activeColor: '#00FF00'
}
};
const opts = {
width: 800,
height: 500,
devicePixelRatio: 2,
styles: {
selector: {
activeColor: 'red',
activeAreaColor: '#FF00001C',
lockedColor: 'black',
referenceColor: 'green'
},
info: {
textBackground: 'yellow',
textColor: 'red'
},
ruler: {
background: '#0000FF1A',
borderColor: '#0000FF',
scaleColor: '#FF0000',
textColor: '#000000',
gridColor: '#0000FF1C',
gridPrimaryColor: '#0000FFAC',
selectedAreaColor: '#FF0000CC'
},
scroller: {
thumbBackground: '#FF00003A',
thumbBorderColor: '#FF00008A',
hoverThumbBackground: '#FF00006E',
hoverThumbBorderColor: '#FF0000EE',
activeThumbBackground: '#FF00005E',
activeThumbBorderColor: '#FF0000F0'
},
layoutSelector: {
activeColor: '#00FF00'
}
}
devicePixelRatio: 2
// styles,
};
const mount = document.querySelector('#mount') as HTMLDivElement;
@ -45,6 +47,10 @@ const data = getData();
const idraw = new iDraw(mount, opts);
idraw.setData(data);
idraw.centerContent();
setTimeout(() => {
idraw.reset({ styles });
}, 2000);
// idraw.scale(0.5);
// idraw.scale(2);
// idraw.scrollX(-80);

View file

@ -27,11 +27,12 @@ import {
calcViewCenter,
Store
} from '@idraw/util';
import { defaultSettings, getDefaultStorage, defaultMode, parseStyles } from './config';
import { defaultSettings, getDefaultStorage, defaultMode, parseStyles, parseSettings } from './setting/config';
import { exportImageFileBlobURL } from './file';
import type { ExportImageFileBaseOptions, ExportImageFileResult } from './file';
import type { IDrawEvent } from './event';
import { changeMode, runMiddlewares } from './mode';
import { changeMode, runMiddlewares } from './setting/mode';
import { changeStyles } from './setting/style';
export class iDraw {
#core: Core<IDrawEvent>;
@ -82,12 +83,28 @@ export class iDraw {
reset(opts: IDrawSettings) {
const core = this.#core;
const store = this.#store;
const { mode, styles } = parseSettings(opts);
let needFresh = false;
let newOpts: IDrawSettings = {};
store.clear();
changeMode(opts.mode || defaultMode, core, store);
core.refresh();
if (mode) {
changeMode(mode, core, store);
newOpts.mode = mode;
needFresh = true;
}
if (styles) {
changeStyles(styles, core, store);
newOpts.styles = styles;
needFresh = true;
}
if (needFresh === true) {
core.refresh();
}
this.#opts = {
...this.#opts,
...opts
...newOpts
};
}

View file

@ -28,7 +28,45 @@ export function getDefaultStorage(): IDrawStorage {
return storage;
}
export function parseStyles(opts: IDrawSettings) {
export function parseSettings(opts: IDrawSettings) {
const { mode, styles } = opts;
const settings: IDrawSettings = {};
if (istype.string(mode)) {
settings.mode = mode;
}
if (styles) {
settings.styles = parseStrictStyles(opts);
}
return settings;
}
export function parseStrictStyles(settings: IDrawSettings): IDrawSettings['styles'] {
const styles = parseStyles(settings);
const strictStyles: IDrawSettings['styles'] = {};
const { selector, info, ruler, scroller, layoutSelector } = styles;
if (Object.keys(selector).length > 0) {
strictStyles.selector = selector;
}
if (Object.keys(info).length > 0) {
strictStyles.info = info;
}
if (Object.keys(ruler).length > 0) {
strictStyles.ruler = ruler;
}
if (Object.keys(scroller).length > 0) {
strictStyles.scroller = scroller;
}
if (Object.keys(layoutSelector).length > 0) {
strictStyles.layoutSelector = layoutSelector;
}
return strictStyles;
}
export function parseStyles(settings: IDrawSettings): Required<Required<IDrawSettings>['styles']> {
const styles: Required<IDrawSettings['styles']> = {
selector: {},
ruler: {},
@ -36,9 +74,9 @@ export function parseStyles(opts: IDrawSettings) {
scroller: {},
layoutSelector: {}
};
if (opts.styles) {
if (settings.styles) {
// selector
const { selector, info, ruler, scroller, layoutSelector } = opts.styles;
const { selector, info, ruler, scroller, layoutSelector } = settings.styles;
if (istype.string(selector?.activeColor)) {
styles.selector.activeColor = selector?.activeColor;
}
@ -108,5 +146,6 @@ export function parseStyles(opts: IDrawSettings) {
styles.layoutSelector.activeColor = layoutSelector?.activeColor;
}
}
return styles;
}

View file

@ -12,7 +12,7 @@ import {
MiddlewareInfo,
MiddlewarePointer
} from '@idraw/core';
import { IDrawEvent } from './event';
import { IDrawEvent } from '../event';
function isValidMode(mode: string | IDrawMode) {
return ['select', 'drag', 'readOnly'].includes(mode);

View file

@ -0,0 +1,29 @@
import { Core, MiddlewareInfo, MiddlewareLayoutSelector, MiddlewareRuler, MiddlewareScroller, MiddlewareSelector } from '@idraw/core';
import { Store } from '@idraw/util';
import type { IDrawSettings, IDrawStorage } from '@idraw/types';
import type { IDrawEvent } from '../event';
export function changeStyles(styles: Required<IDrawSettings>['styles'], core: Core<IDrawEvent>, store: Store<IDrawStorage>) {
const { selector, info, ruler, scroller, layoutSelector } = styles;
const middlewareStyles = store.get('middlewareStyles');
if (selector) {
core.resetMiddlewareConfig(MiddlewareSelector, selector);
middlewareStyles.selector = { ...middlewareStyles.selector, ...selector };
}
if (info) {
core.resetMiddlewareConfig(MiddlewareInfo, info);
middlewareStyles.info = { ...middlewareStyles.info, ...info };
}
if (ruler) {
core.resetMiddlewareConfig(MiddlewareRuler, ruler);
middlewareStyles.ruler = { ...middlewareStyles.ruler, ...ruler };
}
if (scroller) {
core.resetMiddlewareConfig(MiddlewareScroller, scroller);
middlewareStyles.scroller = { ...middlewareStyles.scroller, ...scroller };
}
if (layoutSelector) {
core.resetMiddlewareConfig(MiddlewareLayoutSelector, layoutSelector);
middlewareStyles.layoutSelector = { ...middlewareStyles.layoutSelector, ...layoutSelector };
}
}

View file

@ -60,10 +60,12 @@ export interface BoardWatcherEventMap<S extends Record<any | symbol, any> = any>
clear: void;
}
export interface BoardMiddlewareObject<S extends Record<any | symbol, any> = any> {
export interface BoardMiddlewareObject<S extends Record<any | symbol, any> = any, C extends any = undefined> {
name?: string;
use?: () => void;
disuse?: () => void;
resetConfig?: (config?: Partial<C>) => void;
// action
hover?: (e: BoardWatcherEventMap<S>['hover']) => void | boolean;
pointStart?: (e: BoardWatcherEventMap<S>['pointStart']) => void | boolean;
@ -99,7 +101,7 @@ export interface BoardMiddlewareOptions<S extends Record<any | symbol, any> = Re
export type BoardMiddleware<S extends Record<any | symbol, any> = any, E extends BoardExtendEventMap = BoardExtendEventMap, C extends any = undefined> = (
opts: BoardMiddlewareOptions<S, E>,
config?: C
) => BoardMiddlewareObject<S>;
) => BoardMiddlewareObject<S, C>;
export interface BoardOptions {
boardContent: BoardContent;

View file

@ -27,5 +27,5 @@ export interface IDrawStorage {
enableTextEdit: boolean;
enableDrag: boolean;
enableInfo: boolean;
middlewareStyles: Required<IDrawSettings['styles']>;
middlewareStyles: Required<Required<IDrawSettings>['styles']>;
}