diff --git a/.vscode/settings.json b/.vscode/settings.json index 7d1b241559..07c0ae6476 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -42,6 +42,7 @@ "elementvisibilitychange", "Forceatlas", "Fruchterman", + "Fullscreen", "gforce", "graphlib", "GSHAPE", diff --git a/packages/g6/__tests__/demos/index.ts b/packages/g6/__tests__/demos/index.ts index 3389a2f733..8303ab4c39 100644 --- a/packages/g6/__tests__/demos/index.ts +++ b/packages/g6/__tests__/demos/index.ts @@ -100,6 +100,7 @@ export { pluginBackground } from './plugin-background'; export { pluginBubbleSets } from './plugin-bubble-sets'; export { pluginCameraSetting } from './plugin-camera-setting'; export { pluginContextmenu } from './plugin-contextmenu'; +export { pluginFullscreen } from './plugin-fullscreen'; export { pluginGridLine } from './plugin-grid-line'; export { pluginHistory } from './plugin-history'; export { pluginHull } from './plugin-hull'; diff --git a/packages/g6/__tests__/demos/plugin-fullscreen.ts b/packages/g6/__tests__/demos/plugin-fullscreen.ts new file mode 100644 index 0000000000..01a55c31bb --- /dev/null +++ b/packages/g6/__tests__/demos/plugin-fullscreen.ts @@ -0,0 +1,43 @@ +import { Fullscreen, Graph } from '@/src'; +import data from '@@/dataset/cluster.json'; + +export const pluginFullscreen: TestCase = async (context) => { + const graph = new Graph({ + ...context, + data, + layout: { type: 'd3-force' }, + plugins: [ + { + type: 'fullscreen', + key: 'fullscreen', + }, + ], + }); + + graph.setPlugins((prev) => [ + ...prev, + { + type: 'toolbar', + key: 'toolbar', + position: 'top-left', + onClick: (item: string) => { + const fullscreenPlugin = graph.getPluginInstance('fullscreen'); + if (item === 'request-fullscreen') { + fullscreenPlugin.request(); + } + if (item === 'exit-fullscreen') { + fullscreenPlugin.exit(); + } + }, + getItems: () => { + return [ + { id: 'request-fullscreen', value: 'request-fullscreen' }, + { id: 'exit-fullscreen', value: 'exit-fullscreen' }, + ]; + }, + }, + ]); + + await graph.render(); + return graph; +}; diff --git a/packages/g6/__tests__/snapshots/plugins/fullscreen/exit.svg b/packages/g6/__tests__/snapshots/plugins/fullscreen/exit.svg new file mode 100644 index 0000000000..419c50e17d --- /dev/null +++ b/packages/g6/__tests__/snapshots/plugins/fullscreen/exit.svg @@ -0,0 +1,602 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/g6/__tests__/snapshots/plugins/fullscreen/request.svg b/packages/g6/__tests__/snapshots/plugins/fullscreen/request.svg new file mode 100644 index 0000000000..419c50e17d --- /dev/null +++ b/packages/g6/__tests__/snapshots/plugins/fullscreen/request.svg @@ -0,0 +1,602 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/g6/src/exports.ts b/packages/g6/src/exports.ts index e5aefd3ab6..2317ecbb17 100644 --- a/packages/g6/src/exports.ts +++ b/packages/g6/src/exports.ts @@ -65,6 +65,7 @@ export { BubbleSets, CameraSetting, Contextmenu, + Fullscreen, GridLine, History, Hull, @@ -156,6 +157,7 @@ export type { BubbleSetsOptions, CameraSettingOptions, ContextmenuOptions, + FullscreenOptions, GridLineOptions, HistoryOptions, HullOptions, diff --git a/packages/g6/src/plugins/fullscreen/index.ts b/packages/g6/src/plugins/fullscreen/index.ts new file mode 100644 index 0000000000..3bde1a5a2c --- /dev/null +++ b/packages/g6/src/plugins/fullscreen/index.ts @@ -0,0 +1,168 @@ +import type { RuntimeContext } from '../../runtime/types'; +import type { ShortcutKey } from '../../utils/shortcut'; +import { Shortcut } from '../../utils/shortcut'; +import type { BasePluginOptions } from '../base-plugin'; +import { BasePlugin } from '../base-plugin'; + +/** + * 全屏配置项 + * + * Full screen options + */ +export interface FullscreenOptions extends BasePluginOptions { + /** + * 触发全屏的方式 + * - `request` : 请求全屏 + * - `exit` : 退出全屏 + * + * The way to trigger full screen + * - `request`: request full screen + * - `exit`: exit full screen + */ + trigger?: { + request?: ShortcutKey; + exit?: ShortcutKey; + }; + /** + * 是否自适应画布尺寸,全屏后画布尺寸会自动适应屏幕尺寸 + * + * Whether to adapt the canvas size + * @defaultValue true + */ + autoFit?: boolean; + /** + * 进入全屏后的回调 + * + * Callback after entering full screen + */ + onEnter?: () => void; + /** + * 退出全屏后的回调 + * + * Callback after exiting full screen + */ + onExit?: () => void; +} + +/** + * 全屏 + * + * Full screen + */ +export class Fullscreen extends BasePlugin { + static defaultOptions: Partial = { + trigger: {}, + autoFit: true, + }; + + private shortcut: Shortcut; + + private $el = this.context.canvas.getContainer()!; + private graphSize: [number, number] = [0, 0]; + + constructor(context: RuntimeContext, options: FullscreenOptions) { + super(context, Object.assign({}, Fullscreen.defaultOptions, options)); + + this.shortcut = new Shortcut(context.graph); + + this.bindEvents(); + + this.$el.style.backgroundColor = this.context.graph.getBackground()!; + } + + private bindEvents() { + this.unbindEvents(); + this.shortcut.unbindAll(); + + const { request = [], exit = [] } = this.options.trigger; + this.shortcut.bind(request, this.request); + this.shortcut.bind(exit, this.exit); + + const events = ['webkitfullscreenchange', 'mozfullscreenchange', 'fullscreenchange', 'MSFullscreenChange']; + events.forEach((eventName) => { + document.addEventListener(eventName, this.onFullscreenChange, false); + }); + } + + private unbindEvents() { + this.shortcut.unbindAll(); + const events = ['webkitfullscreenchange', 'mozfullscreenchange', 'fullscreenchange', 'MSFullscreenChange']; + events.forEach((eventName) => { + document.removeEventListener(eventName, this.onFullscreenChange, false); + }); + } + + private setGraphSize(fullScreen = true) { + let width, height; + if (fullScreen) { + width = window.screen.width; + height = window.screen.height; + this.graphSize = this.context.graph.getSize(); + } else { + [width, height] = this.graphSize; + } + this.context.graph.setSize(width, height); + this.context.graph.render(); + } + + private onFullscreenChange = () => { + const isFull = !!document.fullscreenElement; + if (this.options.autoFit) this.setGraphSize(isFull); + if (isFull) { + this.options.onEnter?.(); + } else { + this.options.onExit?.(); + } + }; + + /** + * 请求全屏 + * + * Request full screen + */ + public request() { + if (document.fullscreenElement || !isFullscreenEnabled()) return; + this.$el.requestFullscreen().catch((err: Error) => { + console.debug(`Error attempting to enable full-screen: ${err.message} (${err.name})`); + }); + } + + /** + * 退出全屏 + * + * Exit full screen + */ + public exit() { + if (!document.fullscreenElement) return; + document.exitFullscreen(); + } + + /** + * 更新配置 + * + * Update options + * @param options - 配置项 | Options + * @internal + */ + public update(options: Partial): void { + this.unbindEvents(); + super.update(options); + this.bindEvents(); + } +} + +/** + * 判断是否支持全屏 + * + * Determine whether full screen is enabled + * @returns 是否支持全屏 | Whether full screen is enabled + */ +function isFullscreenEnabled() { + return ( + document.fullscreenEnabled || + // 使用 Reflect 语法规避 ts 检查 | use Reflect to avoid ts checking + Reflect.get(document, 'webkitFullscreenEnabled') || + Reflect.get(document, 'mozFullscreenEnabled') || + Reflect.get(document, 'msFullscreenEnabled') + ); +} diff --git a/packages/g6/src/plugins/index.ts b/packages/g6/src/plugins/index.ts index 20f49d1e0e..d76e5fe39d 100644 --- a/packages/g6/src/plugins/index.ts +++ b/packages/g6/src/plugins/index.ts @@ -3,6 +3,7 @@ export { BasePlugin } from './base-plugin'; export { BubbleSets } from './bubble-sets'; export { CameraSetting } from './camera-setting'; export { Contextmenu } from './contextmenu'; +export { Fullscreen } from './fullscreen'; export { GridLine } from './grid-line'; export { History } from './history'; export { Hull } from './hull'; @@ -17,6 +18,7 @@ export type { BasePluginOptions } from './base-plugin'; export type { BubbleSetsOptions } from './bubble-sets'; export type { CameraSettingOptions } from './camera-setting'; export type { ContextmenuOptions } from './contextmenu'; +export type { FullscreenOptions } from './fullscreen'; export type { GridLineOptions } from './grid-line'; export type { HistoryOptions } from './history'; export type { HullOptions } from './hull'; diff --git a/packages/g6/src/plugins/toolbar/util.ts b/packages/g6/src/plugins/toolbar/util.ts index 5a0c09ad91..db5ddb3ae2 100644 --- a/packages/g6/src/plugins/toolbar/util.ts +++ b/packages/g6/src/plugins/toolbar/util.ts @@ -111,5 +111,9 @@ export const BUILD_IN_SVG_ICON = ` + + + + `; diff --git a/packages/g6/src/registry/build-in.ts b/packages/g6/src/registry/build-in.ts index d4cb6af78f..4dad074861 100644 --- a/packages/g6/src/registry/build-in.ts +++ b/packages/g6/src/registry/build-in.ts @@ -57,6 +57,7 @@ import { Background, BubbleSets, Contextmenu, + Fullscreen, GridLine, History, Hull, @@ -163,15 +164,16 @@ export const BUILT_IN_EXTENSIONS: ExtensionRegistry = { plugin: { 'bubble-sets': BubbleSets, 'grid-line': GridLine, + background: Background, contextmenu: Contextmenu, + fullscreen: Fullscreen, history: History, - timebar: Timebar, hull: Hull, legend: Legend, + timebar: Timebar, toolbar: Toolbar, tooltip: Tooltip, watermark: Watermark, - background: Background, }, transform: { 'update-related-edges': UpdateRelatedEdge, diff --git a/packages/site/src/constants/locales/page-name.json b/packages/site/src/constants/locales/page-name.json index b022affa3e..af2d836527 100644 --- a/packages/site/src/constants/locales/page-name.json +++ b/packages/site/src/constants/locales/page-name.json @@ -55,9 +55,11 @@ "LassoSelect": ["LassoSelect", "套索选择"], "ScrollCanvas": ["ScrollCanvas", "滚动画布"], "ZoomCanvas": ["ZoomCanvas", "缩放画布"], + "Background": ["Background", "背景"], "BubbleSets": ["BubbleSets", "气泡集"], "CameraSetting": ["CameraSetting", "相机设置"], "ContextMenu": ["ContextMenu", "上下文菜单"], + "Fullscreen": ["Fullscreen", "全屏展示"], "GridLine": ["GridLine", "网格线"], "History": ["History", "历史记录"], "Hull": ["Hull", "轮廓包围"],