From 5efd908e4bda56eddf8769d5b1368f1573776aad Mon Sep 17 00:00:00 2001 From: zhe-he Date: Tue, 15 Oct 2024 10:30:44 +0800 Subject: [PATCH] update(Group): The fromObject method supports custom groups --- CHANGELOG.md | 1 + src/shapes/Group.spec.ts | 32 ++++++++++++++++++++++++++++++++ src/shapes/Group.ts | 33 ++++++++++++++++++++------------- 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7e299f9594..0a6923f7dfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [next] +- fix(): Custom group inherited from the group, and the bug of the custom layout type. [10198](https://github.com/fabricjs/fabric.js/issues/10198) - feat(IText): expose getCursorRenderingData() function. [#10204](https://github.com/fabricjs/fabric.js/pull/10204) - fix(Canvas): allowTouchScrolling interactions [#10078](https://github.com/fabricjs/fabric.js/pull/10078) - update(IText): Add method enterEditingImpl/exitEditingImpl that executes the logic of enterEditing/exitEditing without events [#10187](https://github.com/fabricjs/fabric.js/issues/10187) diff --git a/src/shapes/Group.spec.ts b/src/shapes/Group.spec.ts index 8a073c1840e..efa36aa6301 100644 --- a/src/shapes/Group.spec.ts +++ b/src/shapes/Group.spec.ts @@ -3,6 +3,7 @@ import { LayoutManager, ClipPathLayout, FitContentLayout, + LayoutStrategy, } from '../LayoutManager'; import { Canvas } from '../canvas/Canvas'; import { Group } from './Group'; @@ -11,6 +12,7 @@ import { Rect } from './Rect'; import { FabricObject } from './Object/FabricObject'; import { FabricImage } from './Image'; import { SignalAbortedError } from '../util/internals/console'; +import { classRegistry } from '../ClassRegistry'; const makeGenericGroup = (options?: Partial) => { const objs = [new FabricObject(), new FabricObject()]; @@ -336,4 +338,34 @@ describe('Group', () => { expect(eventsSpy).toBeCalledTimes(3); }); + + it("fromObject of the custom group", async () => { + const group = new Group(); + const customGroup = new CustomGroup(); + const groupData = group.toObject(); + const customGroupData = customGroup.toObject(); + const gLayoutManager = (await Group.fromObject(groupData)).layoutManager; + const cLayoutManager = (await CustomGroup.fromObject(customGroupData)).layoutManager; + + const fakeGroupData = { type: Group.type }; + const fakeCustomGroupData = { type: CustomGroup.type }; + const fakeGLayoutManager = (await Group.fromObject(fakeGroupData)).layoutManager; + const fakeCLayoutManager = (await CustomGroup.fromObject(fakeCustomGroupData)).layoutManager; + + expect(gLayoutManager).toEqual(fakeGLayoutManager); + expect(cLayoutManager).toEqual(fakeCLayoutManager); + }) }); + +class CustomGroup extends Group { + static type = "CustomGroup"; + constructor(objects = [], opts: any = {}) { + if (!opts.layoutManager) opts.layoutManager = new LayoutManager(new CustomLayout()); + super(objects, opts); + } +} +class CustomLayout extends LayoutStrategy { + static type = "custom-layout"; +} +classRegistry.setClass(CustomGroup); +classRegistry.setClass(CustomLayout); diff --git a/src/shapes/Group.ts b/src/shapes/Group.ts index 6c0015f8f9b..68434eeb1fd 100644 --- a/src/shapes/Group.ts +++ b/src/shapes/Group.ts @@ -691,11 +691,8 @@ export class Group enlivenObjects(objects, abortable), enlivenObjectEnlivables(options, abortable), ]).then(([objects, hydratedOptions]) => { - const group = new this(objects, { - ...options, - ...hydratedOptions, - layoutManager: new NoopLayoutManager(), - }); + const isCustomGroup = type && type != Group.type; + let layout; if (layoutManager) { const layoutClass = classRegistry.getClass( layoutManager.type, @@ -703,16 +700,26 @@ export class Group const strategyClass = classRegistry.getClass( layoutManager.strategy, ); - group.layoutManager = new layoutClass(new strategyClass()); - } else { - group.layoutManager = new LayoutManager(); + layout = new layoutClass(new strategyClass()); } - group.layoutManager.subscribeTargets({ - type: LAYOUT_TYPE_INITIALIZATION, - target: group, - targets: group.getObjects(), + const manage = isCustomGroup ? layout : new NoopLayoutManager(); + + const group = new this(objects, { + ...options, + ...hydratedOptions, + layoutManager: manage, }); - group.setCoords(); + if (!isCustomGroup) { + group.layoutManager = layout ?? new LayoutManager(); + + group.layoutManager.subscribeTargets({ + type: LAYOUT_TYPE_INITIALIZATION, + target: group, + targets: group.getObjects(), + }); + group.setCoords(); + } + return group; }); }