import * as echarts from 'echarts/lib/echarts'; import ZRTextureAtlasSurface from '../../util/ZRTextureAtlasSurface'; import LabelsMesh from '../../util/mesh/LabelsMesh'; import retrieve from '../../util/retrieve'; import { getItemVisualColor, getItemVisualOpacity } from '../../util/visual'; import { createTextStyle } from 'echarts/lib/label/labelStyle'; var LABEL_NORMAL_SHOW_BIT = 1; var LABEL_EMPHASIS_SHOW_BIT = 2; function LabelsBuilder(width, height, api) { this._labelsMesh = new LabelsMesh(); this._labelTextureSurface = new ZRTextureAtlasSurface({ width: 512, height: 512, devicePixelRatio: api.getDevicePixelRatio(), onupdate: function () { api.getZr().refresh(); } }); this._api = api; this._labelsMesh.material.set('textureAtlas', this._labelTextureSurface.getTexture()); } LabelsBuilder.prototype.getLabelPosition = function (dataIndex, positionDesc, distance) { return [0, 0, 0]; }; LabelsBuilder.prototype.getLabelDistance = function (dataIndex, positionDesc, distance) { return 0; }; LabelsBuilder.prototype.getMesh = function () { return this._labelsMesh; }; LabelsBuilder.prototype.updateData = function (data, start, end) { if (start == null) { start = 0; } if (end == null) { end = data.count(); } if (!this._labelsVisibilitiesBits || this._labelsVisibilitiesBits.length !== end - start) { this._labelsVisibilitiesBits = new Uint8Array(end - start); } var normalLabelVisibilityQuery = ['label', 'show']; var emphasisLabelVisibilityQuery = ['emphasis', 'label', 'show']; for (var idx = start; idx < end; idx++) { var itemModel = data.getItemModel(idx); var normalVisibility = itemModel.get(normalLabelVisibilityQuery); var emphasisVisibility = itemModel.get(emphasisLabelVisibilityQuery); if (emphasisVisibility == null) { emphasisVisibility = normalVisibility; } var bit = (normalVisibility ? LABEL_NORMAL_SHOW_BIT : 0) | (emphasisVisibility ? LABEL_EMPHASIS_SHOW_BIT : 0); this._labelsVisibilitiesBits[idx - start] = bit; } this._start = start; this._end = end; this._data = data; }; LabelsBuilder.prototype.updateLabels = function (highlightDataIndices) { if (!this._data) { return; } highlightDataIndices = highlightDataIndices || []; var hasHighlightData = highlightDataIndices.length > 0; var highlightDataIndicesMap = {}; for (var i = 0; i < highlightDataIndices.length; i++) { highlightDataIndicesMap[highlightDataIndices[i]] = true; } this._labelsMesh.geometry.convertToDynamicArray(true); this._labelTextureSurface.clear(); var normalLabelQuery = ['label']; var emphasisLabelQuery = ['emphasis', 'label']; var seriesModel = this._data.hostModel; var data = this._data; var seriesLabelModel = seriesModel.getModel(normalLabelQuery); var seriesLabelEmphasisModel = seriesModel.getModel(emphasisLabelQuery, seriesLabelModel); var textAlignMap = { left: 'right', right: 'left', top: 'center', bottom: 'center' }; var textVerticalAlignMap = { left: 'middle', right: 'middle', top: 'bottom', bottom: 'top' }; for (var dataIndex = this._start; dataIndex < this._end; dataIndex++) { var isEmphasis = false; if (hasHighlightData && highlightDataIndicesMap[dataIndex]) { isEmphasis = true; } var ifShow = this._labelsVisibilitiesBits[dataIndex - this._start] & (isEmphasis ? LABEL_EMPHASIS_SHOW_BIT : LABEL_NORMAL_SHOW_BIT); if (!ifShow) { continue; } var itemModel = data.getItemModel(dataIndex); var labelModel = itemModel.getModel(isEmphasis ? emphasisLabelQuery : normalLabelQuery, isEmphasis ? seriesLabelEmphasisModel : seriesLabelModel); var distance = labelModel.get('distance') || 0; var position = labelModel.get('position'); var dpr = this._api.getDevicePixelRatio(); var text = seriesModel.getFormattedLabel(dataIndex, isEmphasis ? 'emphasis' : 'normal'); if (text == null || text === '') { return; } // TODO Background. var textEl = new echarts.graphic.Text({ style: createTextStyle(labelModel, { text: text, fill: labelModel.get('color') || getItemVisualColor(data, dataIndex) || '#000', align: 'left', verticalAlign: 'top', opacity: retrieve.firstNotNull(labelModel.get('opacity'), getItemVisualOpacity(data, dataIndex), 1) }) }); var rect = textEl.getBoundingRect(); var lineHeight = 1.2; rect.height *= lineHeight; var coords = this._labelTextureSurface.add(textEl); var textAlign = textAlignMap[position] || 'center'; var textVerticalAlign = textVerticalAlignMap[position] || 'bottom'; this._labelsMesh.geometry.addSprite(this.getLabelPosition(dataIndex, position, distance), [rect.width * dpr, rect.height * dpr], coords, textAlign, textVerticalAlign, this.getLabelDistance(dataIndex, position, distance) * dpr); } this._labelsMesh.material.set('uvScale', this._labelTextureSurface.getCoordsScale()); // var canvas = this._labelTextureSurface.getTexture().image; // document.body.appendChild(canvas); // canvas.style.cssText = 'position:absolute;z-index: 1000'; // Update image. this._labelTextureSurface.getZr().refreshImmediately(); this._labelsMesh.geometry.convertToTypedArray(); this._labelsMesh.geometry.dirty(); }; LabelsBuilder.prototype.dispose = function () { this._labelTextureSurface.dispose(); }; export default LabelsBuilder;