mirror of
https://github.com/idrawjs/idraw
synced 2026-05-24 01:58:27 +00:00
refactor: resource reload logic
This commit is contained in:
parent
67eea92f54
commit
7ae92b4c30
6 changed files with 419 additions and 29 deletions
|
|
@ -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",
|
||||
},
|
||||
|
|
|
|||
292
packages/core/examples/test/resource.html
Normal file
292
packages/core/examples/test/resource.html
Normal file
|
|
@ -0,0 +1,292 @@
|
|||
<html>
|
||||
<head>
|
||||
<style></style>
|
||||
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
|
||||
<style>
|
||||
html,body { margin: 0; padding: 0; }
|
||||
.box canvas {
|
||||
border-right: 1px solid #aaaaaa40;
|
||||
border-bottom: 1px solid #aaaaaa40;
|
||||
background-image:
|
||||
linear-gradient(#aaaaaa40 1px, transparent 0),
|
||||
linear-gradient(90deg, #aaaaaa40 1px, transparent 0),
|
||||
linear-gradient(#aaa 1px, transparent 0),
|
||||
linear-gradient(90deg, #aaa 1px, transparent 0);
|
||||
background-size: 10px 10px, 10px 10px, 50px 50px, 50px 50px;
|
||||
}
|
||||
.list {
|
||||
width: 910px;
|
||||
overflow: hidden;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
border-left: 1px solid #f0f0f0;
|
||||
}
|
||||
.box {
|
||||
width: 300;
|
||||
min-height: 220;
|
||||
float: left;
|
||||
border-right: 1px solid #f0f0f0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
padding: 10px 0;
|
||||
}
|
||||
.box .title {
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: #000;
|
||||
display: inline-block;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
width: 100%;
|
||||
font-family: monospace;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="list">
|
||||
<div class="box" id="mount-image">
|
||||
<div class="title">Image</div>
|
||||
</div>
|
||||
<div class="box" id="mount-svg">
|
||||
<div class="title">SVG</div>
|
||||
</div>
|
||||
<div class="box" id="mount-html">
|
||||
<div class="title">HTML</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="./../../dist/index.global.js"></script>
|
||||
<script>
|
||||
var Core = window.iDrawCore;
|
||||
var opts = {
|
||||
width: 300,
|
||||
height: 200,
|
||||
contextWidth: 300,
|
||||
contextHeight: 200,
|
||||
devicePixelRatio: 4,
|
||||
}
|
||||
var config = {
|
||||
elementWrapper: {
|
||||
dotSize: 4,
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
const mount = document.querySelector('#mount-image');
|
||||
const core = new Core(mount, opts, config);
|
||||
core.addElement({
|
||||
name: "image-001",
|
||||
x: 4,
|
||||
y: 4,
|
||||
w: 200,
|
||||
h: 120,
|
||||
type: "image",
|
||||
desc: {
|
||||
src: './../images/building-001.png'
|
||||
},
|
||||
});
|
||||
core.addElement({
|
||||
name: "image-002",
|
||||
x: 120,
|
||||
y: 80,
|
||||
w: 120,
|
||||
h: 120,
|
||||
type: "image",
|
||||
desc: {
|
||||
src: './../images/building-002.png'
|
||||
},
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
const data = core.getData();
|
||||
const temp1 = data.elements[0].desc.src + '?v=123';
|
||||
const temp2 = data.elements[1].desc.src + '?v=123'
|
||||
data.elements[0].desc.src = temp2;
|
||||
data.elements[1].desc.src = temp1;
|
||||
core.setData(data);
|
||||
}, 800);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
const mount = document.querySelector('#mount-svg');
|
||||
const core = new Core(mount, opts, config);
|
||||
core.addElement({
|
||||
name: "svg-001",
|
||||
x: 4,
|
||||
y: 4,
|
||||
w: 120,
|
||||
h: 120,
|
||||
type: "svg",
|
||||
desc: {
|
||||
svg: '<svg t="1622524780663" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8365" width="200" height="200"><path d="M881 442.4H519.7v148.5h206.4c-8.9 48-35.9 88.6-76.6 115.8-34.4 23-78.3 36.6-129.9 36.6-99.9 0-184.4-67.5-214.6-158.2-7.6-23-12-47.6-12-72.9s4.4-49.9 12-72.9c30.3-90.6 114.8-158.1 214.7-158.1 56.3 0 106.8 19.4 146.6 57.4l110-110.1c-66.5-62-153.2-100-256.6-100-149.9 0-279.6 86-342.7 211.4-26 51.8-40.8 110.4-40.8 172.4S151 632.8 177 684.6C240.1 810 369.8 896 519.7 896c103.6 0 190.4-34.4 253.8-93 72.5-66.8 114.4-165.2 114.4-282.1 0-27.2-2.4-53.3-6.9-78.5z" p-id="8366" fill="#1296db"></path></svg>'
|
||||
},
|
||||
});
|
||||
core.addElement({
|
||||
name: "svg-002",
|
||||
x: 120,
|
||||
y: 80,
|
||||
w: 120,
|
||||
h: 120,
|
||||
type: "svg",
|
||||
desc: {
|
||||
svg: '<svg t="1622524835512" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9094" width="200" height="200"><path d="M270.1 741.7c0 23.4 19.1 42.5 42.6 42.5h48.7v120.4c0 30.5 24.5 55.4 54.6 55.4 30.2 0 54.6-24.8 54.6-55.4V784.1h85v120.4c0 30.5 24.5 55.4 54.6 55.4 30.2 0 54.6-24.8 54.6-55.4V784.1h48.7c23.5 0 42.6-19.1 42.6-42.5V346.4h-486v395.3zM627.2 141.6l44.9-65c2.6-3.8 2-8.9-1.5-11.4-3.5-2.4-8.5-1.2-11.1 2.6l-46.6 67.6c-30.7-12.1-64.9-18.8-100.8-18.8-35.9 0-70.1 6.7-100.8 18.8l-46.6-67.5c-2.6-3.8-7.6-5.1-11.1-2.6-3.5 2.4-4.1 7.4-1.5 11.4l44.9 65c-71.4 33.2-121.4 96.1-127.8 169.6h486c-6.6-73.6-56.7-136.5-128-169.7zM409.5 244.1c-14.8 0-26.9-12-26.9-26.9 0-14.8 12-26.9 26.9-26.9 14.8 0 26.9 12 26.9 26.9-0.1 14.9-12.1 26.9-26.9 26.9z m208.4 0c-14.8 0-26.9-12-26.9-26.9 0-14.8 12-26.9 26.9-26.9 14.8 0 26.9 12 26.9 26.9-0.1 14.9-12.1 26.9-26.9 26.9zM841.3 344.8c-30.2 0-54.6 24.8-54.6 55.4v216.4c0 30.5 24.5 55.4 54.6 55.4 30.2 0 54.6-24.8 54.6-55.4V400.1c0.1-30.6-24.3-55.3-54.6-55.3zM182.7 344.8c-30.2 0-54.6 24.8-54.6 55.4v216.4c0 30.5 24.5 55.4 54.6 55.4 30.2 0 54.6-24.8 54.6-55.4V400.1c0-30.6-24.5-55.3-54.6-55.3z" p-id="9095" fill="#2aa515"></path></svg>'
|
||||
},
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
const data = core.getData();
|
||||
const temp1 = data.elements[0].desc.svg;
|
||||
const temp2 = data.elements[1].desc.svg;
|
||||
data.elements[0].desc.svg = temp2;
|
||||
data.elements[1].desc.svg = temp1;
|
||||
core.setData(data);
|
||||
}, 800);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
const mount = document.querySelector('#mount-html');
|
||||
const core = new Core(mount, opts, config);
|
||||
core.addElement({
|
||||
name: "html-001",
|
||||
x: 4,
|
||||
y: 4,
|
||||
w: 120,
|
||||
h: 60,
|
||||
type: "html",
|
||||
desc: {
|
||||
html: `<style>
|
||||
.btn-box {
|
||||
margin: 10px 0;
|
||||
}
|
||||
.btn {
|
||||
line-height: 1.5715;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
font-weight: 400;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
background-image: none;
|
||||
border: 1px solid transparent;
|
||||
box-shadow: 0 2px #00000004;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
height: 32px;
|
||||
padding: 4px 15px;
|
||||
font-size: 14px;
|
||||
border-radius: 2px;
|
||||
color: #000000d9;
|
||||
background: #fff;
|
||||
border-color: #d9d9d9;
|
||||
}
|
||||
.btn-primary {
|
||||
color: #fff;
|
||||
background: #1890ff;
|
||||
border-color: #1890ff;
|
||||
text-shadow: 0 -1px 0 rgb(0 0 0 / 12%);
|
||||
box-shadow: 0 2px #0000000b;
|
||||
}
|
||||
</style>
|
||||
<div>
|
||||
<div class="btn-box" style="margin-top: 0;">
|
||||
<button class="btn" >
|
||||
<span>Button 001</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="btn-box">
|
||||
<button class="btn btn-primary">
|
||||
<span>Button Primary</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
},
|
||||
});
|
||||
core.addElement({
|
||||
name: "html-002",
|
||||
x: 120,
|
||||
y: 80,
|
||||
w: 120,
|
||||
h: 60,
|
||||
type: "html",
|
||||
desc: {
|
||||
width: 120,
|
||||
height: 80,
|
||||
html: `<style>
|
||||
.btn-box {
|
||||
margin: 10px 0;
|
||||
}
|
||||
.btn {
|
||||
line-height: 1.5715;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
font-weight: 400;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
background-image: none;
|
||||
border: 1px solid transparent;
|
||||
box-shadow: 0 2px #00000004;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
height: 32px;
|
||||
padding: 4px 15px;
|
||||
font-size: 14px;
|
||||
border-radius: 2px;
|
||||
color: #000000d9;
|
||||
background: #fff;
|
||||
border-color: #d9d9d9;
|
||||
}
|
||||
.btn-primary {
|
||||
color: #fff;
|
||||
background: #1890ff;
|
||||
border-color: #1890ff;
|
||||
text-shadow: 0 -1px 0 rgb(0 0 0 / 12%);
|
||||
box-shadow: 0 2px #0000000b;
|
||||
}
|
||||
</style>
|
||||
<div>
|
||||
<div class="btn-box" style="margin-top: 0;">
|
||||
<button class="btn" >
|
||||
<span>Button 002</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="btn-box">
|
||||
<button class="btn btn-primary">
|
||||
<span>Button Primary</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
},
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
const data = core.getData();
|
||||
const temp1 = data.elements[0].desc.html;
|
||||
const temp2 = data.elements[1].desc.html;
|
||||
data.elements[0].desc.html = temp2;
|
||||
data.elements[1].desc.html = temp1;
|
||||
core.setData(data);
|
||||
|
||||
setTimeout(() => {
|
||||
const data = core.getData();
|
||||
data.elements[0].desc.height = 50;
|
||||
data.elements[1].desc.height = 100;
|
||||
core.setData(data);
|
||||
}, 800);
|
||||
}, 800);
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -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<keyof TypeElemDesc>) {
|
||||
|
|
|
|||
88
packages/core/src/lib/diff.ts
Normal file
88
packages/core/src/lib/diff.ts
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
import { TypeElement, TypeData, TypeElemDesc } from '@idraw/types';
|
||||
|
||||
type TypeElementMap = {
|
||||
[uuid: string]: TypeElement<keyof TypeElemDesc>
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue