From 7ae92b4c303bd5157fabf991ebe4c6010ceece1c Mon Sep 17 00:00:00 2001 From: chenshenhai Date: Fri, 27 Aug 2021 23:38:28 +0800 Subject: [PATCH] refactor: resource reload logic --- .../core/examples/features/lib/data/image.js | 4 +- packages/core/examples/test/resource.html | 292 ++++++++++++++++++ packages/core/src/index.ts | 12 +- packages/core/src/lib/diff.ts | 88 ++++++ packages/core/src/lib/loader.ts | 48 +-- packages/core/src/lib/renderer.ts | 4 +- 6 files changed, 419 insertions(+), 29 deletions(-) create mode 100644 packages/core/examples/test/resource.html create mode 100644 packages/core/src/lib/diff.ts diff --git a/packages/core/examples/features/lib/data/image.js b/packages/core/examples/features/lib/data/image.js index a956aba..02ed840 100644 --- a/packages/core/examples/features/lib/data/image.js +++ b/packages/core/examples/features/lib/data/image.js @@ -37,9 +37,9 @@ const data = { x: 160, y: 160, w: 200, - h: 20, + h: 100, type: "image", - angle: 80, + angle: 45, desc: { src: "./../images/phone.png", }, diff --git a/packages/core/examples/test/resource.html b/packages/core/examples/test/resource.html new file mode 100644 index 0000000..8cb55a9 --- /dev/null +++ b/packages/core/examples/test/resource.html @@ -0,0 +1,292 @@ + + + + + + + + +
+
+
Image
+
+
+
SVG
+
+
+
HTML
+
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 7d2d223..1c88ae2 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -24,6 +24,7 @@ import { _transfromElement, _emitChangeScreen, _emitChangeData, _onlyRender, _cursorStatus, } from './names'; import { Mode, CursorStatus } from './constant/static'; +import { diffElementResourceChangeList } from './lib/diff'; const { time } = util; const { deepClone } = util.data; @@ -77,7 +78,11 @@ class Core { this[_hasInited] = true; } - [_draw](): void { + [_draw]( + opts?: { + resourceChangeUUIDs?: string[], + } + ): void { const transfrom = this[_board].getTransform(); this[_helper].updateConfig(this[_data], { width: this[_opts].width, @@ -90,7 +95,7 @@ class Core { scrollX: transfrom.scrollX, scrollY: transfrom.scrollY, }); - this[_renderer].render(this[_data], this[_helper].getConfig()); + this[_renderer].render(this[_data], this[_helper].getConfig(), opts?.resourceChangeUUIDs || []); } resetSize(opts: TypeBoardSizeOptions) { @@ -183,11 +188,12 @@ class Core { } setData(data: any | TypeData, opts?: { triggerChangeEvent: boolean }): void { + const resourceChangeUUIDs = diffElementResourceChangeList(this[_data], data); this[_data] = this[_element].initData(deepClone(parseData(data))); if (opts && opts.triggerChangeEvent === true) { this[_emitChangeData](); } - this[_draw](); + this[_draw]({ resourceChangeUUIDs }); } updateElement(elem: TypeElement) { diff --git a/packages/core/src/lib/diff.ts b/packages/core/src/lib/diff.ts new file mode 100644 index 0000000..119b897 --- /dev/null +++ b/packages/core/src/lib/diff.ts @@ -0,0 +1,88 @@ +import { TypeElement, TypeData, TypeElemDesc } from '@idraw/types'; + +type TypeElementMap = { + [uuid: string]: TypeElement +} + + +export function isChangeImageElementResource( + before: TypeElement<'image'>, + after: TypeElement<'image'>, +): boolean { + return (before?.desc?.src !== after?.desc?.src); +} + + +export function isChangeSVGElementResource( + before: TypeElement<'svg'>, + after: TypeElement<'svg'>, +): boolean { + return (before?.desc?.svg !== after?.desc?.svg); +} + +export function isChangeHTMLElementResource( + before: TypeElement<'html'>, + after: TypeElement<'html'>, +): boolean { + return ( + before?.desc?.html !== after?.desc?.html + || before?.desc?.width !== after?.desc?.width + || before?.desc?.height !== after?.desc?.height + ); +} + +export function diffElementResourceChangeList( + before: TypeData, + after: TypeData, +): string[] { + const uuids: string[] = []; + const beforeMap = parseDataElementMap(before); + const afterMap = parseDataElementMap(after); + for (const uuid in afterMap) { + if (['image', 'svg', 'html'].includes(afterMap[uuid]?.type) !== true) { + continue; + } + if (beforeMap[uuid]) { + let isChange = false; + switch (beforeMap[uuid].type) { + case 'image': { + isChange = isChangeImageElementResource( + beforeMap[uuid] as TypeElement<'image'>, + afterMap[uuid] as TypeElement<'image'> + ); + break; + } + case 'svg': { + isChange = isChangeSVGElementResource( + beforeMap[uuid] as TypeElement<'svg'>, + afterMap[uuid] as TypeElement<'svg'> + ); + break; + } + case 'html': { + isChange = isChangeHTMLElementResource( + beforeMap[uuid] as TypeElement<'html'>, + afterMap[uuid] as TypeElement<'html'> + ); + break; + } + default: break; + } + if (isChange === true) { + uuids.push(uuid); + } + } else { + uuids.push(uuid); + } + } + return uuids; +} + + +function parseDataElementMap(data: TypeData): TypeElementMap { + const elemMap: TypeElementMap = {}; + data.elements.forEach((elem) => { + elemMap[elem.uuid] = elem; + }) + return elemMap; +} \ No newline at end of file diff --git a/packages/core/src/lib/loader.ts b/packages/core/src/lib/loader.ts index b50620e..d53bd2f 100644 --- a/packages/core/src/lib/loader.ts +++ b/packages/core/src/lib/loader.ts @@ -38,8 +38,8 @@ export default class Loader { this._waitingLoadQueue = []; } - load(data: TypeData): void { - const [uuidQueue, loadData] = this._resetLoadData(data); + load(data: TypeData, changeResourceUUIDs: string[]): void { + const [uuidQueue, loadData] = this._resetLoadData(data, changeResourceUUIDs); if (this._status === LoaderStatus.FREE || this._status === LoaderStatus.COMPLETE) { this._currentUUIDQueue = uuidQueue; this._currentLoadData = loadData; @@ -105,7 +105,7 @@ export default class Loader { // return null; // } - private _resetLoadData(data: TypeData): [string[], TypeLoadData] { + private _resetLoadData(data: TypeData, changeResourceUUIDs: string[]): [string[], TypeLoadData] { const loadData: TypeLoadData = {}; const uuidQueue: string[] = []; @@ -119,25 +119,29 @@ export default class Loader { loadData[elem.uuid] = this._createEmptyLoadItem(elem); uuidQueue.push(elem.uuid); } else { - if (elem.type === 'image') { - const _ele = elem as TypeElement<'image'>; - if (_ele.desc.src !== storageLoadData[elem.uuid].source) { - loadData[elem.uuid] = this._createEmptyLoadItem(elem); - uuidQueue.push(elem.uuid); - } - } else if (elem.type === 'svg') { - const _ele = elem as TypeElement<'svg'>; - if (_ele.desc.svg !== storageLoadData[elem.uuid].source) { - loadData[elem.uuid] = this._createEmptyLoadItem(elem); - uuidQueue.push(elem.uuid); - } - } else if (elem.type === 'html') { - const _ele = elem as TypeElement<'html'>; - if (filterScript(_ele.desc.html) !== storageLoadData[elem.uuid].source) { - loadData[elem.uuid] = this._createEmptyLoadItem(elem); - uuidQueue.push(elem.uuid); - } - } + if (changeResourceUUIDs.includes(elem.uuid)) { + loadData[elem.uuid] = this._createEmptyLoadItem(elem); + uuidQueue.push(elem.uuid); + } + // if (elem.type === 'image') { + // const _ele = elem as TypeElement<'image'>; + // if (_ele.desc.src !== storageLoadData[elem.uuid].source) { + // loadData[elem.uuid] = this._createEmptyLoadItem(elem); + // uuidQueue.push(elem.uuid); + // } + // } else if (elem.type === 'svg') { + // const _ele = elem as TypeElement<'svg'>; + // if (_ele.desc.svg !== storageLoadData[elem.uuid].source) { + // loadData[elem.uuid] = this._createEmptyLoadItem(elem); + // uuidQueue.push(elem.uuid); + // } + // } else if (elem.type === 'html') { + // const _ele = elem as TypeElement<'html'>; + // if (filterScript(_ele.desc.html) !== storageLoadData[elem.uuid].source) { + // loadData[elem.uuid] = this._createEmptyLoadItem(elem); + // uuidQueue.push(elem.uuid); + // } + // } } } } diff --git a/packages/core/src/lib/renderer.ts b/packages/core/src/lib/renderer.ts index 436fa2c..c6a83a2 100644 --- a/packages/core/src/lib/renderer.ts +++ b/packages/core/src/lib/renderer.ts @@ -37,14 +37,14 @@ export class Renderer { }); } - render(data: TypeData, helper: TypeHelperConfig): void { + render(data: TypeData, helper: TypeHelperConfig, changeResourceUUIDs: string[]): void { const _data: QueueItem = deepClone({ data, helper }) as QueueItem; this._queue.push(_data); if (this._status !== DrawStatus.DRAWING) { this._status = DrawStatus.DRAWING; this._drawFrame(); } - this._loader.load(data); + this._loader.load(data, changeResourceUUIDs); } private _drawFrame() {