/** * @fileOverview minimap * @author huangtonger@aliyun.com */ const G6 = require('@antv/g6'); const { Util, G } = G6; const Canvas = G.Canvas; class Minimap { constructor(options) { Util.mix(this, { /** * 类型 * @type {string} */ type: 'minimap', /** * dom 容器 * @type {dom} */ container: null, /** * 是否是缩略图 * @type {boolean} */ isMinimap: true, /** * 背景样式 * @type {CSS} */ backgroundCSS: { height: '100%', position: 'absolute', margin: 'auto', left: 0, right: 0, 'z-index': 0 }, /** * 容器样式 * @type {CSS} */ minimapContainerCSS: { background: '#fff', position: 'relative', overflow: 'hidden' }, /** * 缩略图视口框 * @type {CSS} */ viewportCSS: { height: '100%', position: 'absolute', margin: 'auto', left: 0, right: 0, 'z-index': 1 }, /** * 控制图层 * @type {CSS} */ controlLayerCSS: { width: '100%', height: '100%', cursor: 'move', position: 'absolute', 'z-index': 2 }, /** * 缩略图可视区域视窗样式 * @type {G.Rect.ATTRS} */ viewportWindowStyle: { stroke: '#91D5FF' }, /** * 缩略图背景样式 * @type {G.Rect.ATTRS} */ viewportBackStyle: { fill: '#EBEEF2', fillOpacity: 0.65 }, /** * 获取 G6 图 * @type {funtion} */ getGraph() { }, ...options }); this._initContainer(); this._initMiniMap(); this._bindEvent(); } _bindEvent() { const controlLayer = this.controlLayer; let miniMapViewPortActived = false; let startMatrix; let miniMapScale; let graphScale; let startPoint; let graph; controlLayer.on('mousedown', ev => { if (!this.miniMapMatrix) { return; } graph = this.getGraph(); miniMapViewPortActived = true; startMatrix = Util.cloneDeep(graph.getMatrix()); miniMapScale = this.miniMapMatrix[0]; graphScale = startMatrix[0]; startPoint = { clientX: ev.clientX, clientY: ev.clientY }; }); controlLayer.on('mouseup', () => { resetStatus(); }); controlLayer.on('mouseleave', () => { resetStatus(); }); controlLayer.on('mousemove', ev => { if (miniMapViewPortActived && graph) { const dx = startPoint.clientX - ev.clientX; const dy = startPoint.clientY - ev.clientY; const matrix = Util.cloneDeep(startMatrix); Util.mat3.translate(matrix, matrix, [ graphScale * dx / miniMapScale, graphScale * dy / miniMapScale ]); graph.updateMatrix(matrix); } }); function resetStatus() { miniMapViewPortActived = false; miniMapScale = undefined; startPoint = undefined; startMatrix = undefined; graphScale = undefined; graph = undefined; } } _initMiniMap() { const background = this.background; const viewport = this.viewPort; const width = this.width; const height = this.height; const viewportWindowStyle = this.viewportWindowStyle; const viewportBackStyle = this.viewportBackStyle; const miniMapCanvas = new Canvas({ containerDOM: background, width, height }); const viewportCanvas = new Canvas({ containerDOM: viewport, width, height }); const viewportWindow = viewportCanvas.addShape('rect', { attrs: { x: 0, y: 0, width, height, ...viewportWindowStyle } }); const viewportBack = viewportCanvas.addShape('path', { attrs: { path: 'M0,0 L1,1', ...viewportBackStyle } }); background.css({ width: width + 'px', height: height + 'px' }); viewport.css({ position: 'absolute' }); this.miniMapCanvas = miniMapCanvas; this.viewportCanvas = viewportCanvas; this.viewportWindow = viewportWindow; this.viewportBack = viewportBack; } _initContainer() { let container = this.container; let width = this.width; let height = this.height; if (container) { if (Util.isString(container)) { container = document.getElementById(container); } } else { throw new Error('please set the container for the minimap !'); } if (!width) { width = Util.getWidth(container); } if (!height) { height = Util.getHeight(container); } const minimapContainerCSS = this.minimapContainerCSS; minimapContainerCSS.width = width + 'px'; minimapContainerCSS.height = height + 'px'; const backgroundCSS = this.backgroundCSS; const viewportCSS = this.viewportCSS; const controlLayerCSS = this.controlLayerCSS; const minimapContainer = Util.createDOM('
', minimapContainerCSS); const background = Util.createDOM('', backgroundCSS); const viewPort = Util.createDOM('