| /* |
| * 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 * as zrUtil from 'zrender/src/core/util'; |
| import * as graphic from '../../util/graphic'; |
| import AxisBuilder from './AxisBuilder'; |
| import AxisView from './AxisView'; |
| import { RadiusAxisModel } from '../../coord/polar/AxisModel'; |
| import Polar from '../../coord/polar/Polar'; |
| import RadiusAxis from '../../coord/polar/RadiusAxis'; |
| import GlobalModel from '../../model/Global'; |
| |
| const axisBuilderAttrs = [ |
| 'axisLine', 'axisTickLabel', 'axisName' |
| ] as const; |
| const selfBuilderAttrs = [ |
| 'splitLine', 'splitArea', 'minorSplitLine' |
| ] as const; |
| |
| type TickCoord = ReturnType<RadiusAxis['getTicksCoords']>[number]; |
| |
| class RadiusAxisView extends AxisView { |
| |
| static readonly type = 'radiusAxis'; |
| readonly type = RadiusAxisView.type; |
| |
| axisPointerClass = 'PolarAxisPointer'; |
| |
| private _axisGroup: graphic.Group; |
| |
| render(radiusAxisModel: RadiusAxisModel, ecModel: GlobalModel) { |
| this.group.removeAll(); |
| if (!radiusAxisModel.get('show')) { |
| return; |
| } |
| |
| const oldAxisGroup = this._axisGroup; |
| const newAxisGroup = this._axisGroup = new graphic.Group(); |
| this.group.add(newAxisGroup); |
| |
| const radiusAxis = radiusAxisModel.axis; |
| const polar = radiusAxis.polar; |
| const angleAxis = polar.getAngleAxis(); |
| const ticksCoords = radiusAxis.getTicksCoords(); |
| const minorTicksCoords = radiusAxis.getMinorTicksCoords(); |
| const axisAngle = angleAxis.getExtent()[0]; |
| const radiusExtent = radiusAxis.getExtent(); |
| |
| const layout = layoutAxis(polar, radiusAxisModel, axisAngle); |
| const axisBuilder = new AxisBuilder(radiusAxisModel, layout); |
| zrUtil.each(axisBuilderAttrs, axisBuilder.add, axisBuilder); |
| newAxisGroup.add(axisBuilder.getGroup()); |
| |
| graphic.groupTransition(oldAxisGroup, newAxisGroup, radiusAxisModel); |
| |
| zrUtil.each(selfBuilderAttrs, function (name) { |
| if (radiusAxisModel.get([name, 'show']) && !radiusAxis.scale.isBlank()) { |
| axisElementBuilders[name]( |
| this.group, |
| radiusAxisModel, |
| polar, |
| axisAngle, |
| radiusExtent, |
| ticksCoords, |
| minorTicksCoords |
| ); |
| } |
| }, this); |
| } |
| } |
| |
| interface AxisElementBuilder { |
| ( |
| group: graphic.Group, |
| axisModel: RadiusAxisModel, |
| polar: Polar, |
| axisAngle: number, |
| radiusExtent: number[], |
| ticksCoords: TickCoord[], |
| minorTicksCoords?: TickCoord[][] |
| ): void |
| } |
| |
| const axisElementBuilders: Record<typeof selfBuilderAttrs[number], AxisElementBuilder> = { |
| |
| splitLine(group, radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) { |
| const splitLineModel = radiusAxisModel.getModel('splitLine'); |
| const lineStyleModel = splitLineModel.getModel('lineStyle'); |
| let lineColors = lineStyleModel.get('color'); |
| let lineCount = 0; |
| |
| lineColors = lineColors instanceof Array ? lineColors : [lineColors]; |
| |
| const splitLines: graphic.Circle[][] = []; |
| |
| for (let i = 0; i < ticksCoords.length; i++) { |
| const colorIndex = (lineCount++) % lineColors.length; |
| splitLines[colorIndex] = splitLines[colorIndex] || []; |
| splitLines[colorIndex].push(new graphic.Circle({ |
| shape: { |
| cx: polar.cx, |
| cy: polar.cy, |
| r: ticksCoords[i].coord |
| } |
| })); |
| } |
| |
| // Simple optimization |
| // Batching the lines if color are the same |
| for (let i = 0; i < splitLines.length; i++) { |
| group.add(graphic.mergePath(splitLines[i], { |
| style: zrUtil.defaults({ |
| stroke: lineColors[i % lineColors.length], |
| fill: null |
| }, lineStyleModel.getLineStyle()), |
| silent: true |
| })); |
| } |
| }, |
| |
| minorSplitLine(group, radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords, minorTicksCoords) { |
| if (!minorTicksCoords.length) { |
| return; |
| } |
| |
| const minorSplitLineModel = radiusAxisModel.getModel('minorSplitLine'); |
| const lineStyleModel = minorSplitLineModel.getModel('lineStyle'); |
| |
| const lines: graphic.Circle[] = []; |
| |
| for (let i = 0; i < minorTicksCoords.length; i++) { |
| for (let k = 0; k < minorTicksCoords[i].length; k++) { |
| lines.push(new graphic.Circle({ |
| shape: { |
| cx: polar.cx, |
| cy: polar.cy, |
| r: minorTicksCoords[i][k].coord |
| } |
| })); |
| } |
| } |
| |
| group.add(graphic.mergePath(lines, { |
| style: zrUtil.defaults({ |
| fill: null |
| }, lineStyleModel.getLineStyle()), |
| silent: true |
| })); |
| }, |
| |
| splitArea(group, radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) { |
| if (!ticksCoords.length) { |
| return; |
| } |
| |
| const splitAreaModel = radiusAxisModel.getModel('splitArea'); |
| const areaStyleModel = splitAreaModel.getModel('areaStyle'); |
| let areaColors = areaStyleModel.get('color'); |
| let lineCount = 0; |
| |
| areaColors = areaColors instanceof Array ? areaColors : [areaColors]; |
| |
| const splitAreas: graphic.Sector[][] = []; |
| |
| let prevRadius = ticksCoords[0].coord; |
| for (let i = 1; i < ticksCoords.length; i++) { |
| const colorIndex = (lineCount++) % areaColors.length; |
| splitAreas[colorIndex] = splitAreas[colorIndex] || []; |
| splitAreas[colorIndex].push(new graphic.Sector({ |
| shape: { |
| cx: polar.cx, |
| cy: polar.cy, |
| r0: prevRadius, |
| r: ticksCoords[i].coord, |
| startAngle: 0, |
| endAngle: Math.PI * 2 |
| }, |
| silent: true |
| })); |
| prevRadius = ticksCoords[i].coord; |
| } |
| |
| // Simple optimization |
| // Batching the lines if color are the same |
| for (let i = 0; i < splitAreas.length; i++) { |
| group.add(graphic.mergePath(splitAreas[i], { |
| style: zrUtil.defaults({ |
| fill: areaColors[i % areaColors.length] |
| }, areaStyleModel.getAreaStyle()), |
| silent: true |
| })); |
| } |
| } |
| }; |
| |
| /** |
| * @inner |
| */ |
| function layoutAxis(polar: Polar, radiusAxisModel: RadiusAxisModel, axisAngle: number) { |
| return { |
| position: [polar.cx, polar.cy], |
| rotation: axisAngle / 180 * Math.PI, |
| labelDirection: -1 as const, |
| tickDirection: -1 as const, |
| nameDirection: 1 as const, |
| labelRotate: radiusAxisModel.getModel('axisLabel').get('rotate'), |
| // Over splitLine and splitArea |
| z2: 1 |
| }; |
| } |
| |
| export default RadiusAxisView; |