/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var echarts = require("../../echarts"); var zrUtil = require("zrender/lib/core/util"); var graphic = require("../../util/graphic"); var MapDraw = require("../../component/helper/MapDraw"); /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var HIGH_DOWN_PROP = '__seriesMapHighDown'; var RECORD_VERSION_PROP = '__seriesMapCallKey'; var _default = echarts.extendChartView({ type: 'map', render: function (mapModel, ecModel, api, payload) { // Not render if it is an toggleSelect action from self if (payload && payload.type === 'mapToggleSelect' && payload.from === this.uid) { return; } var group = this.group; group.removeAll(); if (mapModel.getHostGeoModel()) { return; } // Not update map if it is an roam action from self if (!(payload && payload.type === 'geoRoam' && payload.componentType === 'series' && payload.seriesId === mapModel.id)) { if (mapModel.needsDrawMap) { var mapDraw = this._mapDraw || new MapDraw(api, true); group.add(mapDraw.group); mapDraw.draw(mapModel, ecModel, api, this, payload); this._mapDraw = mapDraw; } else { // Remove drawed map this._mapDraw && this._mapDraw.remove(); this._mapDraw = null; } } else { var mapDraw = this._mapDraw; mapDraw && group.add(mapDraw.group); } mapModel.get('showLegendSymbol') && ecModel.getComponent('legend') && this._renderSymbols(mapModel, ecModel, api); }, remove: function () { this._mapDraw && this._mapDraw.remove(); this._mapDraw = null; this.group.removeAll(); }, dispose: function () { this._mapDraw && this._mapDraw.remove(); this._mapDraw = null; }, _renderSymbols: function (mapModel, ecModel, api) { var originalData = mapModel.originalData; var group = this.group; originalData.each(originalData.mapDimension('value'), function (value, originalDataIndex) { if (isNaN(value)) { return; } var layout = originalData.getItemLayout(originalDataIndex); if (!layout || !layout.point) { // Not exists in map return; } var point = layout.point; var offset = layout.offset; var circle = new graphic.Circle({ style: { // Because the special of map draw. // Which needs statistic of multiple series and draw on one map. // And each series also need a symbol with legend color // // Layout and visual are put one the different data fill: mapModel.getData().getVisual('color') }, shape: { cx: point[0] + offset * 9, cy: point[1], r: 3 }, silent: true, // Do not overlap the first series, on which labels are displayed. z2: 8 + (!offset ? graphic.Z2_EMPHASIS_LIFT + 1 : 0) }); // Only the series that has the first value on the same region is in charge of rendering the label. // But consider the case: // series: [ // {id: 'X', type: 'map', map: 'm', {data: [{name: 'A', value: 11}, {name: 'B', {value: 22}]}, // {id: 'Y', type: 'map', map: 'm', {data: [{name: 'A', value: 21}, {name: 'C', {value: 33}]} // ] // The offset `0` of item `A` is at series `X`, but of item `C` is at series `Y`. // For backward compatibility, we follow the rule that render label `A` by the // settings on series `X` but render label `C` by the settings on series `Y`. if (!offset) { var fullData = mapModel.mainSeries.getData(); var name = originalData.getName(originalDataIndex); var fullIndex = fullData.indexOfName(name); var itemModel = originalData.getItemModel(originalDataIndex); var labelModel = itemModel.getModel('label'); var hoverLabelModel = itemModel.getModel('emphasis.label'); var regionGroup = fullData.getItemGraphicEl(fullIndex); // `getFormattedLabel` needs to use `getData` inside. Here // `mapModel.getData()` is shallow cloned from `mainSeries.getData()`. // FIXME // If this is not the `mainSeries`, the item model (like label formatter) // set on original data item will never get. But it has been working // like that from the begining, and this scenario is rarely encountered. // So it won't be fixed until have to. var normalText = zrUtil.retrieve2(mapModel.getFormattedLabel(fullIndex, 'normal'), name); var emphasisText = zrUtil.retrieve2(mapModel.getFormattedLabel(fullIndex, 'emphasis'), normalText); var highDownRecord = regionGroup[HIGH_DOWN_PROP]; var recordVersion = Math.random(); // Prevent from register listeners duplicatedly when roaming. if (!highDownRecord) { highDownRecord = regionGroup[HIGH_DOWN_PROP] = {}; var onEmphasis = zrUtil.curry(onRegionHighDown, true); var onNormal = zrUtil.curry(onRegionHighDown, false); regionGroup.on('mouseover', onEmphasis).on('mouseout', onNormal).on('emphasis', onEmphasis).on('normal', onNormal); } // Prevent removed regions effect current grapics. regionGroup[RECORD_VERSION_PROP] = recordVersion; zrUtil.extend(highDownRecord, { recordVersion: recordVersion, circle: circle, labelModel: labelModel, hoverLabelModel: hoverLabelModel, emphasisText: emphasisText, normalText: normalText }); // FIXME // Consider set option when emphasis. enterRegionHighDown(highDownRecord, false); } group.add(circle); }); } }); function onRegionHighDown(toHighOrDown) { var highDownRecord = this[HIGH_DOWN_PROP]; if (highDownRecord && highDownRecord.recordVersion === this[RECORD_VERSION_PROP]) { enterRegionHighDown(highDownRecord, toHighOrDown); } } function enterRegionHighDown(highDownRecord, toHighOrDown) { var circle = highDownRecord.circle; var labelModel = highDownRecord.labelModel; var hoverLabelModel = highDownRecord.hoverLabelModel; var emphasisText = highDownRecord.emphasisText; var normalText = highDownRecord.normalText; if (toHighOrDown) { circle.style.extendFrom(graphic.setTextStyle({}, hoverLabelModel, { text: hoverLabelModel.get('show') ? emphasisText : null }, { isRectText: true, useInsideStyle: false }, true)); // Make label upper than others if overlaps. circle.__mapOriginalZ2 = circle.z2; circle.z2 += graphic.Z2_EMPHASIS_LIFT; } else { graphic.setTextStyle(circle.style, labelModel, { text: labelModel.get('show') ? normalText : null, textPosition: labelModel.getShallow('position') || 'bottom' }, { isRectText: true, useInsideStyle: false }); // Trigger normalize style like padding. circle.dirty(false); if (circle.__mapOriginalZ2 != null) { circle.z2 = circle.__mapOriginalZ2; circle.__mapOriginalZ2 = null; } } } module.exports = _default;