Sidebar-Charts.js 8.41 KB
(function () {

	const enumConst = {

		/**
		 * @description 图表cell 默认宽度
		 */
		CHART_CELL_DEFAULT_WIDTH: 400,

		/**
		 * @description 图表cell 默认高度
		 */
		CHART_CELL_DEFAULT_HEIGHT: 400,

		/**
		 * @description 图表cell的 width attribute
		 */
		CHART_CELL_WIDTH: 'width',

		/**
		 * @description 图表cell的 height attribute
		 */
		CHART_CELL_HEIGHT: 'height',

		/**
		 * @description cell 类型是否为 charts
		 */
		IS_CHART_COMP: 'charts',

		/**
		 * @description cell id key
		 */
		CHART_CELL_ID: 'chartInstanceId',

		/**
		 * @description 图表类型key
		 */
		CHART_CELL_TYPE: 'componentsType',

		/**
		 * @description 图表容器 class name
		 */
		CHART_CONTAINER_CLS: 'echarts__instance',

		/**
		 * @description 图表容器  id 前缀
		 */
		CHART_CONTAINER_ID_PREFIX: 'echarts__instance__',

		/**
		 * @description 图表图片占位符大小
		 */
		CHART_IMG_PLACEHOLDER_SIZE: 30,
	}

	// Adds Atlassian shapes
	// 图表
	Sidebar.prototype.addChartsPalette = function () {
		const graph = this.graph
		chartsComponentInit(graph)

		const s = 'html=1;shadow=0;dashed=0;shape=mxgraph.atlassian.';
		const s2 = 'html=1;shadow=0;dashed=0;fillColor=none;strokeColor=none;shape=mxgraph.bootstrap.rect;';
		const s3 = mxConstants.STYLE_STROKEWIDTH + '=1;shadow=0;dashed=0;align=center;html=1;' + mxConstants.STYLE_SHAPE + "=mxgraph.mockup.";
		const gn = 'mxgraph.charts';
		const dt = 'charts ';
		const sb = this;
		this.setCurrentSearchEntryLibrary('charts');

		const fns = [
			this.addEntry('charts', mxUtils.bind(this, function () {
				const id = generatorChartsId()
				const cell = generatorCell(id, enumConst.CHART_IMG_PLACEHOLDER_SIZE, enumConst.CHART_IMG_PLACEHOLDER_SIZE, graph)
				return this.createVertexTemplateFromCells([ cell ], cell.geometry.width, cell.geometry.height, 'charts');
			})),
		];

		this.addPaletteFunctions('charts', '图表', false, fns);

		this.setCurrentSearchEntryLibrary();
	};

	/**
	 * @description 创建cell
	 * @param id
	 * @param width
	 * @param height
	 * @returns {*}
	 */
	function generatorCell(id, width, height, graph) {
		const cell = new mxCell(createChartsNode(id, width, height), new mxGeometry(0, 0, width, height), 'text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;overflow=hidden;');
		cell.setVertex(true)
		graph.setAttributeForCell(cell, enumConst.CHART_CELL_TYPE, 'charts');
		graph.setAttributeForCell(cell, enumConst.CHART_CELL_ID, id);
		graph.setAttributeForCell(cell, enumConst.CHART_CELL_WIDTH, width)
		graph.setAttributeForCell(cell, enumConst.CHART_CELL_HEIGHT, height)
		return cell
	}

	function generatorChartsId() {
		return `${ enumConst.CHART_CONTAINER_ID_PREFIX }${ Date.now() }`
	}


	function createChartsNode(id, width = 400, height = 400) {
		const chartImg = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAAlUlEQVRIie2UWwqAIBBFD+0hqR21lVpuffRfC7GPJpAYNe1BQRcGxcc9MyrCrwxZiUtUXGX0FMAAbWxR7IiMhDY+yN4uF1ACPTACtTJuZa7KAbgmm1Gdau4DuOUPgb52dFGAlqFWTTRzDRAq372Pw+Z7QEe4fN+LOgyA9V0nm6QATulzX8U7ALO09kQE1QDTnYBfz2oBmQJYp8UoXcoAAAAASUVORK5CYII='
		return `<div class="echarts__instance" style="width: ${ width }px; height: ${ height }px" id="${ id }"><img src="${ chartImg }" alt=""></div>`
	}

	/**
	 * @description 折线图配置
	 * @returns {{yAxis: {type: string}, xAxis: {data: string[], type: string}, series: [{data: number[], type: string}]}}
	 */
	function chartsLineChartsConfig() {
		return {
			xAxis: {
				type: 'category',
				data: [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ],
			},
			yAxis: {
				type: 'value',
			},
			series: [
				{
					data: [ 150, 230, 224, 218, 135, 147, 260 ],
					type: 'line',
				},
			],
		}
	}

	function chartsComponentInit(graph) {
		const chartsInstanceMapping = new Map()

		/**
		 * @description 拓展添加charts 实例方法
		 */
		const addClickHandler = Sidebar.prototype.addClickHandler
		Sidebar.prototype.addClickHandler = function (elt, ds, cells) {
			const cell = cells[0]
			const cellValue = cell.value
			const validate = cellValue && cellValue.nodeName === 'UserObject' && isChartCell(cell)

			const mouseDown = ds.mouseDown
			ds.mouseDown = function (evt) {
				if (validate) {
					const id = generatorChartsId()
					const geo = Object.assign(graph.model.getGeometry(cell), { width: 400, height: 400 })
					cell.setGeometry(geo)
					graph.setAttributeForCell(cell, enumConst.CHART_CELL_ID, id);
					graph.setAttributeForCell(cell, 'label', createChartsNode(id))
				}
				mouseDown.apply(this, arguments)
			};

			const mouseUp = ds.mouseUp
			ds.mouseUp = function () {
				try {
					mouseUp.apply(this, arguments)
				} finally {
					if (validate) {
						const id = getCellId(cell)
						const chartDom = document.getElementById(id);
						const myChart = echarts.init(chartDom);
						const option = chartsLineChartsConfig()
						option && myChart.setOption(option);
						chartsInstanceMapping.set(id, myChart)
					}
				}
			}
			addClickHandler.apply(this, arguments)
		}

		/**
		 * @description charts cell发生resize时改变charts size
		 * @type {mxGraph.cellResized}
		 */
		const cellResized = mxGraph.prototype.cellResized
		mxGraph.prototype.cellResized = function (cell, rect) {
			const { width, height } = rect
			const id = getCellId(cell)
			const chartDom = document.getElementById(id)
			chartDom.style.width = `${ width }px`
			chartDom.style.height = `${ height }px`
			graph.setAttributeForCell(cell, enumConst.CHART_CELL_WIDTH, width)
			graph.setAttributeForCell(cell, enumConst.CHART_CELL_HEIGHT, height)
			const instance = chartsInstanceMapping.get(id)
			instance.resize()
			cellResized.apply(this, arguments)
		}

		/**
		 * @description 删除charts cell 时 删除保存的charts 实例
		 */
		const deleteCells = Graph.prototype.deleteCells
		Graph.prototype.deleteCells = function (cell) {
			const id = getCellId(cell)
			chartsInstanceMapping.delete(id)
			return deleteCells.apply(this, arguments)
		}

		/**
		 * @description 获取charts cell 的id
		 * @param cell
		 * @returns {*}
		 */
		function getCellId(cell) {
			return graph.getAttributeForCell(cell, enumConst.CHART_CELL_ID)
		}

		function generatorEChartInstance(id, width, height) {
			const chartDom = document.getElementById(id);
			chartDom.style.width = `${ width }px`
			chartDom.style.height = `${ height }px`
			const myChart = echarts.init(chartDom);
			const option = chartsLineChartsConfig()
			option && myChart.setOption(option);
			chartsInstanceMapping.set(id, myChart)
		}

		// 初始化图表
		const openFileHandle = EditorUi.prototype.openFileHandle
		EditorUi.prototype.openFileHandle = function () {
			try {
				openFileHandle.apply(this, arguments)
			} finally {
				const allCell = this.editor.graph.getDefaultParent().children
				const domIdMapping = new Map()
				for (const cell of allCell) {
					const chartInstanceId = graph.getAttributeForCell(cell, enumConst.CHART_CELL_ID)
					if (isChartCell(cell) && chartInstanceId) {
						const width = graph.getAttributeForCell(cell, enumConst.CHART_CELL_WIDTH)
						const height = graph.getAttributeForCell(cell, enumConst.CHART_CELL_HEIGHT)
						domIdMapping.set(chartInstanceId, { width, height })
					}
				}
				const chartsDomList = document.querySelectorAll(`.${ enumConst.CHART_CONTAINER_CLS }`)
				for (const chartDom of chartsDomList) {
					const id = chartDom.getAttribute('id')
					const { width, height } = domIdMapping.get(id)
					generatorEChartInstance(id, width, height)
				}
			}
		}

		/**
		 * @description 是否是图表cell
		 * @param cell
		 * @returns {boolean}
		 */
		function isChartCell(cell) {
			const componentsType = graph.getAttributeForCell(cell, enumConst.CHART_CELL_TYPE)
			return !!(componentsType && componentsType === enumConst.IS_CHART_COMP)
		}

		const createTooltip = Sidebar.prototype.createTooltip
		Sidebar.prototype.createTooltip = function (elt, cells) {
			const id = generatorChartsId()
			const validateFlag = isChartCell(cells[0])
			try {
				if (validateFlag) {
					const cell = generatorCell(id, enumConst.CHART_CELL_DEFAULT_WIDTH, enumConst.CHART_CELL_DEFAULT_HEIGHT, graph)
					const _arguments = Array.prototype.slice.call(arguments, 0)
					_arguments.splice(1, 1, [ cell ])
					createTooltip.apply(this, _arguments)
				} else {
					createTooltip.apply(this, arguments)
				}
			} finally {
				if (validateFlag) generatorEChartInstance(id, enumConst.CHART_CELL_DEFAULT_WIDTH, enumConst.CHART_CELL_DEFAULT_HEIGHT)
			}
		}
	}
})();