| /* |
| * 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. |
| */ |
| |
| |
| import SymbolDraw from '../../chart/helper/SymbolDraw'; |
| import * as numberUtil from '../../util/number'; |
| import List from '../../data/List'; |
| import * as markerHelper from './markerHelper'; |
| import MarkerView from './MarkerView'; |
| import { CoordinateSystem } from '../../coord/CoordinateSystem'; |
| import SeriesModel from '../../model/Series'; |
| import MarkPointModel, {MarkPointDataItemOption} from './MarkPointModel'; |
| import GlobalModel from '../../model/Global'; |
| import MarkerModel from './MarkerModel'; |
| import ExtensionAPI from '../../core/ExtensionAPI'; |
| import { HashMap, isFunction, map, defaults, filter, curry } from 'zrender/src/core/util'; |
| import { getECData } from '../../util/innerStore'; |
| import { getVisualFromData } from '../../visual/helper'; |
| import { ZRColor } from '../../util/types'; |
| |
| function updateMarkerLayout( |
| mpData: List<MarkPointModel>, |
| seriesModel: SeriesModel, |
| api: ExtensionAPI |
| ) { |
| const coordSys = seriesModel.coordinateSystem; |
| mpData.each(function (idx: number) { |
| const itemModel = mpData.getItemModel<MarkPointDataItemOption>(idx); |
| let point; |
| const xPx = numberUtil.parsePercent(itemModel.get('x'), api.getWidth()); |
| const yPx = numberUtil.parsePercent(itemModel.get('y'), api.getHeight()); |
| if (!isNaN(xPx) && !isNaN(yPx)) { |
| point = [xPx, yPx]; |
| } |
| // Chart like bar may have there own marker positioning logic |
| else if (seriesModel.getMarkerPosition) { |
| // Use the getMarkerPoisition |
| point = seriesModel.getMarkerPosition( |
| mpData.getValues(mpData.dimensions, idx) |
| ); |
| } |
| else if (coordSys) { |
| const x = mpData.get(coordSys.dimensions[0], idx); |
| const y = mpData.get(coordSys.dimensions[1], idx); |
| point = coordSys.dataToPoint([x, y]); |
| |
| } |
| |
| // Use x, y if has any |
| if (!isNaN(xPx)) { |
| point[0] = xPx; |
| } |
| if (!isNaN(yPx)) { |
| point[1] = yPx; |
| } |
| |
| mpData.setItemLayout(idx, point); |
| }); |
| } |
| |
| class MarkPointView extends MarkerView { |
| |
| static type = 'markPoint'; |
| type = MarkPointView.type; |
| |
| markerGroupMap: HashMap<SymbolDraw>; |
| |
| updateTransform(markPointModel: MarkPointModel, ecModel: GlobalModel, api: ExtensionAPI) { |
| ecModel.eachSeries(function (seriesModel) { |
| const mpModel = MarkerModel.getMarkerModelFromSeries(seriesModel, 'markPoint') as MarkPointModel; |
| if (mpModel) { |
| updateMarkerLayout( |
| mpModel.getData(), |
| seriesModel, api |
| ); |
| this.markerGroupMap.get(seriesModel.id).updateLayout(); |
| } |
| }, this); |
| } |
| |
| renderSeries( |
| seriesModel: SeriesModel, |
| mpModel: MarkPointModel, |
| ecModel: GlobalModel, |
| api: ExtensionAPI |
| ) { |
| const coordSys = seriesModel.coordinateSystem; |
| const seriesId = seriesModel.id; |
| const seriesData = seriesModel.getData(); |
| |
| const symbolDrawMap = this.markerGroupMap; |
| const symbolDraw = symbolDrawMap.get(seriesId) |
| || symbolDrawMap.set(seriesId, new SymbolDraw()); |
| |
| const mpData = createList(coordSys, seriesModel, mpModel); |
| |
| // FIXME |
| mpModel.setData(mpData); |
| |
| updateMarkerLayout(mpModel.getData(), seriesModel, api); |
| |
| mpData.each(function (idx) { |
| const itemModel = mpData.getItemModel<MarkPointDataItemOption>(idx); |
| let symbol = itemModel.getShallow('symbol'); |
| let symbolSize = itemModel.getShallow('symbolSize'); |
| let symbolRotate = itemModel.getShallow('symbolRotate'); |
| let symbolOffset = itemModel.getShallow('symbolOffset'); |
| const symbolKeepAspect = itemModel.getShallow('symbolKeepAspect'); |
| |
| // TODO: refactor needed: single data item should not support callback function |
| if (isFunction(symbol) || isFunction(symbolSize) || isFunction(symbolRotate) || isFunction(symbolOffset)) { |
| const rawIdx = mpModel.getRawValue(idx); |
| const dataParams = mpModel.getDataParams(idx); |
| if (isFunction(symbol)) { |
| symbol = symbol(rawIdx, dataParams); |
| } |
| if (isFunction(symbolSize)) { |
| // FIXME 这里不兼容 ECharts 2.x,2.x 貌似参数是整个数据? |
| symbolSize = symbolSize(rawIdx, dataParams); |
| } |
| if (isFunction(symbolRotate)) { |
| symbolRotate = symbolRotate(rawIdx, dataParams); |
| } |
| if (isFunction(symbolOffset)) { |
| symbolOffset = symbolOffset(rawIdx, dataParams); |
| } |
| } |
| |
| const style = itemModel.getModel('itemStyle').getItemStyle(); |
| const color = getVisualFromData(seriesData, 'color') as ZRColor; |
| if (!style.fill) { |
| style.fill = color; |
| } |
| |
| mpData.setItemVisual(idx, { |
| symbol: symbol, |
| symbolSize: symbolSize, |
| symbolRotate: symbolRotate, |
| symbolOffset: symbolOffset, |
| symbolKeepAspect: symbolKeepAspect, |
| style |
| }); |
| }); |
| |
| // TODO Text are wrong |
| symbolDraw.updateData(mpData); |
| this.group.add(symbolDraw.group); |
| |
| // Set host model for tooltip |
| // FIXME |
| mpData.eachItemGraphicEl(function (el) { |
| el.traverse(function (child) { |
| getECData(child).dataModel = mpModel; |
| }); |
| }); |
| |
| this.markKeep(symbolDraw); |
| |
| symbolDraw.group.silent = mpModel.get('silent') || seriesModel.get('silent'); |
| } |
| } |
| |
| function createList( |
| coordSys: CoordinateSystem, |
| seriesModel: SeriesModel, |
| mpModel: MarkPointModel |
| ) { |
| let coordDimsInfos; |
| if (coordSys) { |
| coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) { |
| const info = seriesModel.getData().getDimensionInfo( |
| seriesModel.getData().mapDimension(coordDim) |
| ) || {}; |
| // In map series data don't have lng and lat dimension. Fallback to same with coordSys |
| return defaults({name: coordDim}, info); |
| }); |
| } |
| else { |
| coordDimsInfos = [{ |
| name: 'value', |
| type: 'float' |
| }]; |
| } |
| |
| const mpData = new List(coordDimsInfos, mpModel); |
| let dataOpt = map(mpModel.get('data'), curry( |
| markerHelper.dataTransform, seriesModel |
| )); |
| if (coordSys) { |
| dataOpt = filter( |
| dataOpt, curry(markerHelper.dataFilter, coordSys) |
| ); |
| } |
| |
| mpData.initData(dataOpt, null, |
| coordSys ? markerHelper.dimValueGetter : function (item: MarkPointDataItemOption) { |
| return item.value; |
| } |
| ); |
| |
| return mpData; |
| } |
| |
| export default MarkPointView; |