Skip to content

Commit

Permalink
Merge pull request #277 from idrawjs/dev-v0.4
Browse files Browse the repository at this point in the history
feat: improve text-editor, fix getData and fix type error
  • Loading branch information
chenshenhai authored Feb 3, 2024
2 parents b46acde + bf3629a commit e9a7607
Show file tree
Hide file tree
Showing 22 changed files with 438 additions and 94 deletions.
15 changes: 14 additions & 1 deletion packages/board/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class Board<T extends BoardExtendEvent = BoardExtendEvent> {
#viewer: Viewer;
#calculator: Calculator;
#eventHub: EventEmitter<T> = new EventEmitter<T>();

#hasDestroyed: boolean = false;
constructor(opts: BoardOptions) {
const { boardContent } = opts;
const sharer = new Sharer();
Expand Down Expand Up @@ -70,6 +70,10 @@ export class Board<T extends BoardExtendEvent = BoardExtendEvent> {
this.#resetActiveMiddlewareObjs();
}

isDestroyed() {
return this.#hasDestroyed;
}

destroy() {
// #opts
// #middlewareMap
Expand All @@ -81,6 +85,7 @@ export class Board<T extends BoardExtendEvent = BoardExtendEvent> {
// #viewer: Viewer;
this.#calculator.destroy();
this.#eventHub.destroy();
this.#hasDestroyed = true;
}

#init() {
Expand Down Expand Up @@ -376,6 +381,14 @@ export class Board<T extends BoardExtendEvent = BoardExtendEvent> {
getEventHub(): EventEmitter<T> {
return this.#eventHub;
}

onWatcherEvents() {
this.#watcher.onEvents();
}

offWatcherEvents() {
this.#watcher.offEvents();
}
}

export { Sharer, Calculator };
16 changes: 15 additions & 1 deletion packages/board/src/lib/watcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ function isBoardAvailableNum(num: any): boolean {
export class BoardWatcher extends EventEmitter<BoardWatcherEventMap> {
#opts: BoardWatcherOptions;
#store: Store<BoardWatcherStore>;
#hasDestroyed: boolean = false;
constructor(opts: BoardWatcherOptions) {
super();
const store = new Store<BoardWatcherStore>({ defaultStorage: { hasPointDown: false, prevClickPoint: null } });
Expand All @@ -17,6 +18,13 @@ export class BoardWatcher extends EventEmitter<BoardWatcherEventMap> {
}

#init() {
this.onEvents();
}

onEvents() {
if (this.#hasDestroyed) {
return;
}
const container = window;
container.addEventListener('mousemove', this.#onHover);
container.addEventListener('mousedown', this.#onPointStart);
Expand All @@ -28,7 +36,7 @@ export class BoardWatcher extends EventEmitter<BoardWatcherEventMap> {
container.addEventListener('contextmenu', this.#onContextMenu);
}

destroy() {
offEvents() {
const container = window;
container.removeEventListener('mousemove', this.#onHover);
container.removeEventListener('mousedown', this.#onPointStart);
Expand All @@ -40,6 +48,12 @@ export class BoardWatcher extends EventEmitter<BoardWatcherEventMap> {
container.removeEventListener('contextmenu', this.#onContextMenu);
}

destroy() {
this.offEvents();
this.#store.destroy();
this.#hasDestroyed = true;
}

#onWheel = (e: WheelEvent) => {
if (!this.#isInTarget(e)) {
return;
Expand Down
12 changes: 12 additions & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ export class Core<E extends CoreEvent = CoreEvent> {
});
}

isDestroyed() {
return this.#board.isDestroyed();
}

destroy() {
this.#board.destroy();
this.#canvas.remove();
Expand Down Expand Up @@ -129,4 +133,12 @@ export class Core<E extends CoreEvent = CoreEvent> {
getLoadItemMap(): LoadItemMap {
return this.#board.getRenderer().getLoadItemMap();
}

onBoardWatcherEvents() {
this.#board.onWatcherEvents();
}

offBoardWatcherEvents() {
this.#board.offWatcherEvents();
}
}
68 changes: 36 additions & 32 deletions packages/core/src/lib/cursor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { limitAngle, loadImage, parseAngleToRadian } from '@idraw/util';
import { CURSOR, CURSOR_RESIZE, CURSOR_DRAG_DEFAULT, CURSOR_DRAG_ACTIVE } from './cursor-image';

export class Cursor {
private _eventHub: UtilEventEmitter<CoreEvent>;
private _container: HTMLDivElement;
private _cursorType: 'auto' | string | null = null;
private _resizeCursorBaseImage: HTMLImageElement | null = null;
private _cursorImageMap: Record<string, string> = {
#eventHub: UtilEventEmitter<CoreEvent>;
#container: HTMLDivElement;
#cursorType: 'default' | string | null = null;
#resizeCursorBaseImage: HTMLImageElement | null = null;
#cursorImageMap: Record<string, string> = {
auto: CURSOR,
'drag-default': CURSOR_DRAG_DEFAULT,
'drag-active': CURSOR_DRAG_ACTIVE,
Expand All @@ -19,56 +19,60 @@ export class Cursor {
eventHub: UtilEventEmitter<CoreEvent>;
}
) {
this._container = container;
this._eventHub = opts.eventHub;
this._init();
this._loadResizeCursorBaseImage();
this.#container = container;
this.#eventHub = opts.eventHub;
this.#init();
this.#loadResizeCursorBaseImage();
}

private _init() {
const { _eventHub: eventHub } = this;
this._resetCursor('auto');
#init() {
const eventHub = this.#eventHub;
this.#resetCursor('default');
eventHub.on('cursor', (e) => {
if (e.type === 'over-element' || !e.type) {
this._resetCursor('auto');
this.#resetCursor('auto');
} else if (typeof e.type === 'string' && e.type?.startsWith('resize-')) {
this._setCursorResize(e);
this.#setCursorResize(e);
} else if (e.type === 'drag-default') {
this._resetCursor('drag-default');
this.#resetCursor('drag-default');
} else if (e.type === 'drag-active') {
this._resetCursor('drag-active');
this.#resetCursor('drag-active');
} else {
this._resetCursor('auto');
this.#resetCursor('auto');
}
});
}

private _loadResizeCursorBaseImage() {
#loadResizeCursorBaseImage() {
loadImage(CURSOR_RESIZE)
.then((img) => {
this._resizeCursorBaseImage = img;
this.#resizeCursorBaseImage = img;
})
.catch((err) => {
console.error(err);
});
}

private _resetCursor(cursorKey: string) {
if (this._cursorType === cursorKey) {
#resetCursor(cursorKey: string) {
if (this.#cursorType === cursorKey) {
return;
}
this._cursorType = cursorKey;
const image = this._cursorImageMap[this._cursorType] || this._cursorImageMap['auto'];
this.#cursorType = cursorKey;
const image = this.#cursorImageMap[this.#cursorType] || this.#cursorImageMap['auto'];
let offsetX = 0;
let offsetY = 0;
if (cursorKey.startsWith('rotate-') && this._cursorImageMap[this._cursorType]) {
if (cursorKey.startsWith('rotate-') && this.#cursorImageMap[this.#cursorType]) {
offsetX = 10;
offsetY = 10;
}
this._container.style.cursor = `image-set(url(${image})2x) ${offsetX} ${offsetY}, auto`;
if (cursorKey === 'default') {
this.#container.style.cursor = 'default';
} else {
this.#container.style.cursor = `image-set(url(${image})2x) ${offsetX} ${offsetY}, auto`;
}
}

private _setCursorResize(e: CoreEvent['cursor']) {
#setCursorResize(e: CoreEvent['cursor']) {
let totalAngle = 0;
if (e.type === 'resize-top') {
totalAngle += 0;
Expand All @@ -94,14 +98,14 @@ export class Cursor {
});
}
totalAngle = limitAngle(totalAngle);
const cursorKey = this._appendRotateResizeImage(totalAngle);
this._resetCursor(cursorKey);
const cursorKey = this.#appendRotateResizeImage(totalAngle);
this.#resetCursor(cursorKey);
}

private _appendRotateResizeImage(angle: number): string {
#appendRotateResizeImage(angle: number): string {
const key = `rotate-${angle}`;
if (!this._cursorImageMap[key]) {
const baseImage = this._resizeCursorBaseImage;
if (!this.#cursorImageMap[key]) {
const baseImage = this.#resizeCursorBaseImage;
if (baseImage) {
const canvas = document.createElement('canvas');
const w = baseImage.width;
Expand All @@ -126,7 +130,7 @@ export class Cursor {
ctx.translate(-center.x, -center.y);

const base = canvas.toDataURL('image/png');
this._cursorImageMap[key] = base;
this.#cursorImageMap[key] = base;
}
}
return key;
Expand Down
12 changes: 8 additions & 4 deletions packages/core/src/middleware/text-editor/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,10 @@ export const MiddlewareTextEditor: BoardMiddleware<Record<string, any>, CoreEven
}

textarea.style.position = 'absolute';
textarea.style.left = `${elemX}px`;
textarea.style.top = `${elemY}px`;
textarea.style.width = `${elemW}px`;
textarea.style.height = `${elemH}px`;
textarea.style.left = `${elemX - 1}px`;
textarea.style.top = `${elemY - 1}px`;
textarea.style.width = `${elemW + 2}px`;
textarea.style.height = `${elemH + 2}px`;
textarea.style.transform = `rotate(${limitAngle(element.angle || 0)}deg)`;
// textarea.style.border = 'none';
textarea.style.boxSizing = 'border-box';
Expand All @@ -127,6 +127,10 @@ export const MiddlewareTextEditor: BoardMiddleware<Record<string, any>, CoreEven
textarea.style.lineHeight = `${detail.lineHeight * scale}px`;
textarea.style.fontFamily = detail.fontFamily;
textarea.style.fontWeight = `${detail.fontWeight}`;
textarea.style.padding = '0';
textarea.style.margin = '0';
textarea.style.outline = 'none';

textarea.value = detail.text || '';
parent.appendChild(textarea);
};
Expand Down
22 changes: 20 additions & 2 deletions packages/idraw/src/idraw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ import {
getElementPositionFromList,
calcElementListSize,
filterCompactData,
calcViewCenterContent
calcViewCenterContent,
calcViewCenter
} from '@idraw/util';
import { defaultSettings } from './config';
import { exportImageFileBlobURL } from './file';
Expand Down Expand Up @@ -143,7 +144,7 @@ export class iDraw {
centerContent(opts?: { data?: Data }) {
const data = opts?.data || this.#core.getData();
const { viewSizeInfo } = this.getViewInfo();
if (data) {
if (Array.isArray(data?.elements) && data?.elements.length > 0) {
const result = calcViewCenterContent(data, { viewSizeInfo });
this.setViewScale(result);
}
Expand Down Expand Up @@ -274,8 +275,25 @@ export class iDraw {
});
}

isDestroyed() {
return this.#core.isDestroyed();
}

destroy() {
const core = this.#core;
core.destroy();
}

getViewCenter() {
const { viewScaleInfo, viewSizeInfo } = this.getViewInfo();
return calcViewCenter({ viewScaleInfo, viewSizeInfo });
}

$onBoardWatcherEvents() {
this.#core.onBoardWatcherEvents();
}

$offBoardWatcherEvents() {
this.#core.offBoardWatcherEvents();
}
}
3 changes: 2 additions & 1 deletion packages/idraw/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ export {
deleteElementInList,
deepResizeGroupElement,
deepCloneElement,
calcViewCenterContent
calcViewCenterContent,
calcViewCenter
} from '@idraw/util';
export { iDraw } from './idraw';
export type { IDrawEvent, IDrawEventKeys } from './event';
Expand Down
2 changes: 1 addition & 1 deletion packages/renderer/src/draw/html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export function drawHTML(ctx: ViewContext2D, elem: Element<'html'>, opts: Render
const { calculator, viewScaleInfo, viewSizeInfo, parentOpacity } = opts;
const { x, y, w, h, angle } = calculator?.elementSize(elem, viewScaleInfo, viewSizeInfo) || elem;
rotateElement(ctx, { x, y, w, h, angle }, () => {
if (!content) {
if (!content && !opts.loader.isDestroyed()) {
opts.loader.load(elem as Element<'html'>, opts.elementAssets || {});
}
if (elem.type === 'html' && content) {
Expand Down
2 changes: 1 addition & 1 deletion packages/renderer/src/draw/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function drawImage(ctx: ViewContext2D, elem: Element<'image'>, opts: Rend
viewSizeInfo,
parentOpacity,
renderContent: () => {
if (!content) {
if (!content && !opts.loader.isDestroyed()) {
opts.loader.load(elem as Element<'image'>, opts.elementAssets || {});
}
if (elem.type === 'image' && content) {
Expand Down
2 changes: 1 addition & 1 deletion packages/renderer/src/draw/svg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export function drawSVG(ctx: ViewContext2D, elem: Element<'svg'>, opts: Renderer
const { calculator, viewScaleInfo, viewSizeInfo, parentOpacity } = opts;
const { x, y, w, h, angle } = calculator?.elementSize(elem, viewScaleInfo, viewSizeInfo) || elem;
rotateElement(ctx, { x, y, w, h, angle }, () => {
if (!content) {
if (!content && !opts.loader.isDestroyed()) {
opts.loader.load(elem as Element<'svg'>, opts.elementAssets || {});
}
if (elem.type === 'svg' && content) {
Expand Down
7 changes: 7 additions & 0 deletions packages/renderer/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,24 @@ import type { Data, BoardRenderer, RendererOptions, RendererEventMap, RendererDr
export class Renderer extends EventEmitter<RendererEventMap> implements BoardRenderer {
#opts: RendererOptions;
#loader: Loader = new Loader();
#hasDestroyed: boolean = false;

constructor(opts: RendererOptions) {
super();
this.#opts = opts;
this.#init();
}

isDestroyed() {
return this.#hasDestroyed;
}

destroy() {
this.clear();
this.#opts = null as any;
this.#loader.destroy();
this.#loader = null as any;
this.#hasDestroyed = true;
}

#init() {
Expand Down
Loading

0 comments on commit e9a7607

Please sign in to comment.