diff --git a/packages/g6-extension-react/__tests__/demos/euro-cup.tsx b/packages/g6-extension-react/__tests__/demos/euro-cup.tsx
index 7f13dd10f9f..5fd20113521 100644
--- a/packages/g6-extension-react/__tests__/demos/euro-cup.tsx
+++ b/packages/g6-extension-react/__tests__/demos/euro-cup.tsx
@@ -86,8 +86,6 @@ export const EuroCup = () => {
y: 50,
width: 480,
height: 720,
- background:
- 'url(https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*EmPXQLrX2xIAAAAAAAAAAAAADmJ7AQ/original)no-repeat',
node: {
type: 'react',
style: {
@@ -99,6 +97,18 @@ export const EuroCup = () => {
component: (data: any) => ,
},
},
+ plugins: [
+ {
+ type: 'background',
+ width: '480px',
+ height: '720px',
+ backgroundImage:
+ 'url(https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*EmPXQLrX2xIAAAAAAAAAAAAADmJ7AQ/original)',
+ backgroundRepeat: 'no-repeat',
+ backgroundSize: 'contain',
+ opacity: 1,
+ },
+ ],
}}
/>
diff --git a/packages/g6/__tests__/demos/index.ts b/packages/g6/__tests__/demos/index.ts
index 8dc23fd0e21..e9f0ef6473f 100644
--- a/packages/g6/__tests__/demos/index.ts
+++ b/packages/g6/__tests__/demos/index.ts
@@ -94,6 +94,7 @@ export { layoutRadialPreventOverlap } from './layout-radial-prevent-overlap';
export { layoutRadialPreventOverlapUnstrict } from './layout-radial-prevent-overlap-unstrict';
export { layoutRadialSort } from './layout-radial-sort';
export { perfFCP } from './perf-fcp';
+export { pluginBackground } from './plugin-background';
export { pluginBubbleSets } from './plugin-bubble-sets';
export { pluginCameraSetting } from './plugin-camera-setting';
export { pluginContextmenu } from './plugin-contextmenu';
diff --git a/packages/g6/__tests__/demos/plugin-background.ts b/packages/g6/__tests__/demos/plugin-background.ts
new file mode 100644
index 00000000000..7269b08b427
--- /dev/null
+++ b/packages/g6/__tests__/demos/plugin-background.ts
@@ -0,0 +1,44 @@
+import { Graph } from '@/src';
+import data from '@@/dataset/cluster.json';
+
+export const pluginBackground: TestCase = async (context) => {
+ const graph = new Graph({
+ ...context,
+ autoResize: true,
+ data,
+ layout: { type: 'd3force' },
+ behaviors: ['drag-canvas', 'drag-element'],
+ plugins: [
+ {
+ type: 'background',
+ key: 'background',
+ backgroundImage:
+ 'url(https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*0Qq0ToQm1rEAAAAAAAAAAAAADmJ7AQ/original)',
+ },
+ ],
+ });
+
+ await graph.render();
+
+ pluginBackground.form = (panel) => {
+ const config = {
+ backgroundSize: 'cover',
+ };
+ return [
+ panel
+ .add(config, 'backgroundSize', {
+ Cover: 'cover',
+ Contain: 'contain',
+ })
+ .name('backgroundSize')
+ .onChange((backgroundSize: string) => {
+ graph.updatePlugin({
+ key: 'background',
+ backgroundSize,
+ });
+ }),
+ ];
+ };
+
+ return graph;
+};
diff --git a/packages/g6/__tests__/unit/plugins/background.spec.ts b/packages/g6/__tests__/unit/plugins/background.spec.ts
new file mode 100644
index 00000000000..93710765684
--- /dev/null
+++ b/packages/g6/__tests__/unit/plugins/background.spec.ts
@@ -0,0 +1,26 @@
+import { pluginBackground } from '@/__tests__/demos';
+import { createDemoGraph } from '@@/utils';
+
+describe('plugin background', () => {
+ it('background', async () => {
+ const graph = await createDemoGraph(pluginBackground);
+ const container = graph.getCanvas().getContainer()!;
+
+ const el = container.querySelector('.g6-background') as HTMLDivElement;
+
+ expect(graph.getPlugins()).toEqual([
+ {
+ type: 'background',
+ key: 'background',
+ backgroundImage:
+ 'url(https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*0Qq0ToQm1rEAAAAAAAAAAAAADmJ7AQ/original)',
+ },
+ ]);
+ expect(el.style.backgroundImage).toContain(
+ 'url(https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*0Qq0ToQm1rEAAAAAAAAAAAAADmJ7AQ/original)',
+ );
+
+ await graph.destroy();
+ expect(container.querySelector('.g6-background')).toBeFalsy();
+ });
+});
diff --git a/packages/g6/__tests__/unit/plugins/history/utils.spec.ts b/packages/g6/__tests__/unit/plugins/history/utils.spec.ts
index a6f932704dc..6bee6d752f6 100644
--- a/packages/g6/__tests__/unit/plugins/history/utils.spec.ts
+++ b/packages/g6/__tests__/unit/plugins/history/utils.spec.ts
@@ -1,4 +1,4 @@
-import { alignFields, parseCommand } from '@/src/plugins/history/utils';
+import { alignFields, parseCommand } from '@/src/plugins/history/util';
import type { DataChange } from '@/src/types';
describe('history utils', () => {
diff --git a/packages/g6/__tests__/unit/utils/contextmenu.spec.ts b/packages/g6/__tests__/unit/utils/contextmenu.spec.ts
index 7438bed0f37..5c93c6465d5 100644
--- a/packages/g6/__tests__/unit/utils/contextmenu.spec.ts
+++ b/packages/g6/__tests__/unit/utils/contextmenu.spec.ts
@@ -1,4 +1,4 @@
-import { getContentFromItems } from '../../../src/utils/contextmenu';
+import { getContentFromItems } from '../../../src/plugins/contextmenu/util';
describe('contextmenu', () => {
it('getContentFromItems', () => {
diff --git a/packages/g6/__tests__/unit/utils/dom.spec.ts b/packages/g6/__tests__/unit/utils/dom.spec.ts
index 202cb67ff58..cbdab31d8ff 100644
--- a/packages/g6/__tests__/unit/utils/dom.spec.ts
+++ b/packages/g6/__tests__/unit/utils/dom.spec.ts
@@ -19,8 +19,7 @@ describe('sizeOf', () => {
expect(el.getAttribute('class')).toBe('g6-test');
expect(el.style.position).toBe('absolute');
expect(el.style.display).toBe('block');
- expect(el.style.top).toBe('0px');
- expect(el.style.left).toBe('0px');
+ expect(el.style.inset).toBe('0px');
expect(el.style.height).toBe('100%');
expect(el.style.width).toBe('100%');
expect(el.style.overflow).toBe('hidden');
diff --git a/packages/g6/src/plugins/background/index.ts b/packages/g6/src/plugins/background/index.ts
new file mode 100644
index 00000000000..3132c2294a6
--- /dev/null
+++ b/packages/g6/src/plugins/background/index.ts
@@ -0,0 +1,65 @@
+import { omit } from '@antv/util';
+import type { RuntimeContext } from '../../runtime/types';
+import { createPluginContainer } from '../../utils/dom';
+import type { BasePluginOptions } from '../base-plugin';
+import { BasePlugin } from '../base-plugin';
+
+/**
+ * 背景配置项
+ *
+ * Background options
+ */
+export interface BackgroundOptions extends BasePluginOptions, CSSStyleDeclaration {}
+
+/**
+ * 背景图
+ *
+ * Background image
+ * @remarks
+ * 支持为图画布设置一个背景图片,让画布更有层次感、叙事性。
+ *
+ * Support setting a background image for the canvas to make the canvas more hierarchical and narrative.
+ */
+export class Background extends BasePlugin {
+ static defaultOptions: Partial = {
+ transition: 'background 0.5s',
+ backgroundSize: 'cover',
+ opacity: '0.35',
+ };
+
+ private $element: HTMLElement = createPluginContainer('background');
+
+ constructor(context: RuntimeContext, options: BackgroundOptions) {
+ super(context, Object.assign({}, Background.defaultOptions, options));
+
+ const $container = this.context.canvas.getContainer();
+ $container!.appendChild(this.$element);
+
+ this.update(options);
+ }
+
+ /**
+ * 更新背景图配置
+ *
+ * Update the background image configuration
+ * @param options - 配置项 | Options
+ * @internal
+ */
+ public async update(options: Partial) {
+ super.update(options);
+
+ // Set the background style.
+ Object.assign(this.$element.style, omit(this.options, ['key', 'type']));
+ }
+
+ /**
+ * 销毁背景图
+ *
+ * Destroy the background image
+ */
+ public destroy(): void {
+ super.destroy();
+ // Remove the background dom.
+ this.$element.remove();
+ }
+}
diff --git a/packages/g6/src/plugins/contextmenu.ts b/packages/g6/src/plugins/contextmenu/index.ts
similarity index 94%
rename from packages/g6/src/plugins/contextmenu.ts
rename to packages/g6/src/plugins/contextmenu/index.ts
index 1255cccd13e..eac48429c4e 100644
--- a/packages/g6/src/plugins/contextmenu.ts
+++ b/packages/g6/src/plugins/contextmenu/index.ts
@@ -1,10 +1,10 @@
-import type { RuntimeContext } from '../runtime/types';
-import type { IElementEvent } from '../types/event';
-import type { Item } from '../utils/contextmenu';
-import { CONTEXTMENU_CSS, getContentFromItems } from '../utils/contextmenu';
-import { createPluginContainer, insertDOM } from '../utils/dom';
-import type { BasePluginOptions } from './base-plugin';
-import { BasePlugin } from './base-plugin';
+import type { RuntimeContext } from '../../runtime/types';
+import type { IElementEvent } from '../../types/event';
+import { createPluginContainer, insertDOM } from '../../utils/dom';
+import type { BasePluginOptions } from '../base-plugin';
+import { BasePlugin } from '../base-plugin';
+import type { Item } from './util';
+import { CONTEXTMENU_CSS, getContentFromItems } from './util';
/**
* 上下文菜单配置项
diff --git a/packages/g6/src/utils/contextmenu.ts b/packages/g6/src/plugins/contextmenu/util.ts
similarity index 100%
rename from packages/g6/src/utils/contextmenu.ts
rename to packages/g6/src/plugins/contextmenu/util.ts
diff --git a/packages/g6/src/plugins/history/index.ts b/packages/g6/src/plugins/history/index.ts
index 4d290f014ec..0c27c375bed 100644
--- a/packages/g6/src/plugins/history/index.ts
+++ b/packages/g6/src/plugins/history/index.ts
@@ -8,7 +8,7 @@ import type { GraphLifeCycleEvent } from '../../utils/event';
import { idsOf } from '../../utils/id';
import type { BasePluginOptions } from '../base-plugin';
import { BasePlugin } from '../base-plugin';
-import { parseCommand } from './utils';
+import { parseCommand } from './util';
/**
* 历史记录配置项
diff --git a/packages/g6/src/plugins/history/utils.ts b/packages/g6/src/plugins/history/util.ts
similarity index 100%
rename from packages/g6/src/plugins/history/utils.ts
rename to packages/g6/src/plugins/history/util.ts
diff --git a/packages/g6/src/plugins/index.ts b/packages/g6/src/plugins/index.ts
index 59589837609..20f49d1e0e5 100644
--- a/packages/g6/src/plugins/index.ts
+++ b/packages/g6/src/plugins/index.ts
@@ -1,3 +1,4 @@
+export { Background } from './background';
export { BasePlugin } from './base-plugin';
export { BubbleSets } from './bubble-sets';
export { CameraSetting } from './camera-setting';
@@ -11,6 +12,7 @@ export { Toolbar } from './toolbar';
export { Tooltip } from './tooltip';
export { Watermark } from './watermark';
+export type { BackgroundOptions } from './background';
export type { BasePluginOptions } from './base-plugin';
export type { BubbleSetsOptions } from './bubble-sets';
export type { CameraSettingOptions } from './camera-setting';
diff --git a/packages/g6/src/plugins/watermark.ts b/packages/g6/src/plugins/watermark/index.ts
similarity index 95%
rename from packages/g6/src/plugins/watermark.ts
rename to packages/g6/src/plugins/watermark/index.ts
index cbe4f3d349f..1cc9924b8a1 100644
--- a/packages/g6/src/plugins/watermark.ts
+++ b/packages/g6/src/plugins/watermark/index.ts
@@ -1,8 +1,8 @@
-import type { RuntimeContext } from '../runtime/types';
-import { createPluginContainer } from '../utils/dom';
-import { getImageWatermark, getTextWatermark } from '../utils/watermark';
-import type { BasePluginOptions } from './base-plugin';
-import { BasePlugin } from './base-plugin';
+import type { RuntimeContext } from '../../runtime/types';
+import { createPluginContainer } from '../../utils/dom';
+import type { BasePluginOptions } from '../base-plugin';
+import { BasePlugin } from '../base-plugin';
+import { getImageWatermark, getTextWatermark } from './util';
/**
* 水印配置项
diff --git a/packages/g6/src/utils/watermark.ts b/packages/g6/src/plugins/watermark/util.ts
similarity index 100%
rename from packages/g6/src/utils/watermark.ts
rename to packages/g6/src/plugins/watermark/util.ts
diff --git a/packages/g6/src/registry/build-in.ts b/packages/g6/src/registry/build-in.ts
index 790cb50f45e..90dcfdf48ad 100644
--- a/packages/g6/src/registry/build-in.ts
+++ b/packages/g6/src/registry/build-in.ts
@@ -55,6 +55,7 @@ import {
} from '../layouts';
import { blues, greens, oranges, spectral, tableau } from '../palettes';
import {
+ Background,
BubbleSets,
Contextmenu,
GridLine,
@@ -172,6 +173,7 @@ export const BUILT_IN_EXTENSIONS: ExtensionRegistry = {
toolbar: Toolbar,
tooltip: Tooltip,
watermark: Watermark,
+ background: Background,
},
transform: {
'update-related-edges': UpdateRelatedEdge,
diff --git a/packages/g6/src/runtime/canvas.ts b/packages/g6/src/runtime/canvas.ts
index 1319ae3b308..36c749c554c 100644
--- a/packages/g6/src/runtime/canvas.ts
+++ b/packages/g6/src/runtime/canvas.ts
@@ -151,35 +151,8 @@ export class Canvas {
return this.config;
}
- private backgroundElement!: HTMLDivElement;
-
- private initBackgroundElement(options: Record) {
- if (this.backgroundElement) {
- Object.assign(this.backgroundElement.style, options);
- return this.backgroundElement;
- }
-
- const { width, height } = this.config;
-
- const element = document.createElement('div');
- Object.assign(element.style, options, {
- width: `${width}px`,
- height: `${height}px`,
- pointerEvents: 'none',
- transition: 'background 0.5s',
- backgroundSize: 'contain',
- });
- this.backgroundElement = element;
- return element;
- }
-
public setBackground(background = this.config.background) {
- const container = this.getContainer();
this.config.background = background;
- if (container && background) {
- const dom = this.initBackgroundElement({ background });
- container.appendChild(dom);
- }
}
public setCursor(cursor: Cursor) {
diff --git a/packages/g6/src/utils/dom.ts b/packages/g6/src/utils/dom.ts
index 87204822cf0..f972cc812f9 100644
--- a/packages/g6/src/utils/dom.ts
+++ b/packages/g6/src/utils/dom.ts
@@ -58,8 +58,7 @@ export function createPluginContainer(type: string, cover = true) {
el.style.display = 'block';
if (cover) {
- el.style.top = '0px';
- el.style.left = '0px';
+ el.style.inset = '0px';
el.style.height = '100%';
el.style.width = '100%';
el.style.overflow = 'hidden';
diff --git a/packages/site/common/api/plugins/background.md b/packages/site/common/api/plugins/background.md
new file mode 100644
index 00000000000..574be784559
--- /dev/null
+++ b/packages/site/common/api/plugins/background.md
@@ -0,0 +1,54 @@
+```js | ob { pin: false }
+createGraph(
+ {
+ data: {
+ nodes: [
+ { id: 'node-0' },
+ { id: 'node-1' },
+ { id: 'node-2' },
+ { id: 'node-3' },
+ { id: 'node-4' },
+ { id: 'node-5' },
+ ],
+ edges: [
+ { source: 'node-0', target: 'node-1' },
+ { source: 'node-0', target: 'node-2' },
+ { source: 'node-0', target: 'node-3' },
+ { source: 'node-0', target: 'node-4' },
+ { source: 'node-1', target: 'node-0' },
+ { source: 'node-2', target: 'node-0' },
+ { source: 'node-3', target: 'node-0' },
+ { source: 'node-4', target: 'node-0' },
+ { source: 'node-5', target: 'node-0' },
+ ],
+ },
+ layout: { type: 'grid' },
+ behaviors: ['drag-canvas'],
+ plugins: ['grid-line', {
+ type: 'background',
+ key: 'background',
+ backgroundImage: 'url(https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*0Qq0ToQm1rEAAAAAAAAAAAAADmJ7AQ/original)',
+ backgrounfRepeat: 'no-repeat',
+ backgroundSize: 'contain',
+ }],
+ },
+ { width: 600, height: 300 },
+ (gui, graph) => {
+ const options = {
+ type: 'background',
+ backgroundSize: 'contain',
+ };
+ const optionFolder = gui.addFolder('Background Options');
+ optionFolder.add(options, 'type').disable(true);
+ optionFolder.add(options, 'backgroundSize', ['cover', 'contain', 'auto', '50%']);
+
+ optionFolder.onChange(({ property, value }) => {
+ graph.updatePlugin({
+ key: 'background',
+ [property]: value,
+ });
+ graph.render();
+ });
+ },
+);
+```
diff --git a/packages/site/examples/plugin/watermark/demo/background.js b/packages/site/examples/plugin/background/demo/background.js
similarity index 76%
rename from packages/site/examples/plugin/watermark/demo/background.js
rename to packages/site/examples/plugin/background/demo/background.js
index d7d1e459b4b..b36d4d1242f 100644
--- a/packages/site/examples/plugin/watermark/demo/background.js
+++ b/packages/site/examples/plugin/background/demo/background.js
@@ -24,13 +24,13 @@ const graph = new Graph({
behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],
plugins: [
{
- type: 'watermark',
- width: 1280,
- height: 830,
- rotate: 0,
- opacity: 0.7,
- imageURL: 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*0Qq0ToQm1rEAAAAAAAAAAAAADmJ7AQ/original',
+ type: 'background',
+ width: '800px',
+ height: '600px',
+ backgroundImage: 'url(https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*0Qq0ToQm1rEAAAAAAAAAAAAADmJ7AQ/original)',
+ backgrounfRepeat: 'no-repeat',
backgroundSize: 'cover',
+ opacity: 0.2,
},
],
});
diff --git a/packages/site/examples/plugin/background/demo/meta.json b/packages/site/examples/plugin/background/demo/meta.json
new file mode 100644
index 00000000000..ee0352e153d
--- /dev/null
+++ b/packages/site/examples/plugin/background/demo/meta.json
@@ -0,0 +1,16 @@
+{
+ "title": {
+ "zh": "中文分类",
+ "en": "Category"
+ },
+ "demos": [
+ {
+ "filename": "background.js",
+ "title": {
+ "zh": "背景图片",
+ "en": "Background Image"
+ },
+ "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*eCkYR7cLfWwAAAAAAAAAAAAADmJ7AQ/original"
+ }
+ ]
+}
diff --git a/packages/site/examples/plugin/background/index.en.md b/packages/site/examples/plugin/background/index.en.md
new file mode 100644
index 00000000000..2f09d88cff3
--- /dev/null
+++ b/packages/site/examples/plugin/background/index.en.md
@@ -0,0 +1,3 @@
+---
+title: Background
+---
diff --git a/packages/site/examples/plugin/background/index.zh.md b/packages/site/examples/plugin/background/index.zh.md
new file mode 100644
index 00000000000..05137b9ed9e
--- /dev/null
+++ b/packages/site/examples/plugin/background/index.zh.md
@@ -0,0 +1,3 @@
+---
+title: Background 背景图
+---
diff --git a/packages/site/examples/plugin/watermark/demo/meta.json b/packages/site/examples/plugin/watermark/demo/meta.json
index 88a19e4b1c7..53235f53623 100644
--- a/packages/site/examples/plugin/watermark/demo/meta.json
+++ b/packages/site/examples/plugin/watermark/demo/meta.json
@@ -19,14 +19,6 @@
"en": "Repeat Image"
},
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*8NfwR5QEXvIAAAAAAAAAAAAADmJ7AQ/original"
- },
- {
- "filename": "background.js",
- "title": {
- "zh": "背景图片",
- "en": "Background Image"
- },
- "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*eCkYR7cLfWwAAAAAAAAAAAAADmJ7AQ/original"
}
]
}
diff --git a/packages/site/examples/scene-case/euro-cup/demo/battle-array.jsx b/packages/site/examples/scene-case/euro-cup/demo/battle-array.jsx
index 71e484c0b78..71594f82762 100644
--- a/packages/site/examples/scene-case/euro-cup/demo/battle-array.jsx
+++ b/packages/site/examples/scene-case/euro-cup/demo/battle-array.jsx
@@ -196,8 +196,6 @@ const graph = new Graph({
y: 50,
width: 480,
height: 720,
- background:
- 'url(https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*EmPXQLrX2xIAAAAAAAAAAAAADmJ7AQ/original)no-repeat',
node: {
type: 'react',
style: {
@@ -209,6 +207,17 @@ const graph = new Graph({
component: (data) => ,
},
},
+ plugins: [
+ {
+ type: 'background',
+ width: '480px',
+ height: '720px',
+ backgroundImage: 'url(https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*EmPXQLrX2xIAAAAAAAAAAAAADmJ7AQ/original)',
+ backgroundRepeat: 'no-repeat',
+ backgroundSize: 'contain',
+ opacity: 1,
+ }
+ ],
});
graph.render();