import { BaseToken } from '../../theme/index'; import Axis from './axis'; import { AxisOptions, AxisData } from '../../models'; import { AxisName } from './config'; export default class XAixs extends Axis { constructor(chart, axisdata: AxisData, options: AxisOptions, axisIndex: number) { super(chart, AxisName.XAxis, axisdata, options, axisIndex); } render() { const { axisLine, axisTick, splitLine } = this.options; axisLine?.show && this.drawLine(); axisTick?.show && this.drawTick(); splitLine?.show && this.drawSplitLine(); this.drawLabel(); } /** * 画坐标轴线 */ drawLine() { const { size } = this.canvas; this.painter.draw('Line', { x1: 0, y1: 0, x2: size.width, y2: 0, lineWidth: 1, strokeStyle: BaseToken?.COLOR?.GRAY_5 ?? '#ddd', }); } /** * 画坐标轴刻度 */ drawTick() { const { canvas, options, layoutData } = this; if (!layoutData) return; const { size } = canvas; const { axisTick, boundaryGap } = options; const { length: axisTickLength } = axisTick; const tickGap = size.width / (boundaryGap ? layoutData.length : layoutData.length - 1); for (let i = 0; i <= layoutData.length; i++) { if (layoutData[i]?.isSampled === false) continue; this.painter.draw('Line', { x1: i * tickGap, y1: 0, x2: i * tickGap, y2: -axisTickLength, lineWidth: 1, strokeStyle: BaseToken?.COLOR?.GRAY_5 ?? '#333', }); } } /** * 画坐标轴文本 */ drawLabel() { const { canvas: { ctx, size }, layoutData, options, } = this; if (!layoutData) return; const { axisLabel: { rotate = 0, margin = 0 }, boundaryGap, type, } = options; const isValueAxis = type === 'value'; const computeTextCenter = (index, text, tickGap) => { ctx.font = 'normal 12px PingFang SC'; const { width: textWidth } = ctx.measureText(text); const centerX = index * tickGap + (!isValueAxis && boundaryGap ? tickGap / 2 : 0); const centerY = -margin - (rotate ? Math.sin(Math.abs(rotate)) * (textWidth / 2) : 0); return { centerX, centerY, }; }; const tickGap = size.width / ((!isValueAxis && boundaryGap) ? layoutData.length : layoutData.length - 1); for (let i = 0; i < layoutData.length; i++) { if (layoutData[i]?.isSampled === false) continue; const { text } = layoutData[i]; const { centerX, centerY } = computeTextCenter(i, text, tickGap); this.painter.draw('Text', { text, x: centerX, y: centerY, textBaseline: 'middle', fontStyle: '#777777', rotate, textAlign: 'center', }); } } /** * 画坐标轴分隔线 */ drawSplitLine() { const { splitLine, boundaryGap } = this.options; if (!splitLine?.show) return; const { canvas, layoutData } = this; const { size } = canvas; if (!layoutData) return; const tickGap = size.width / (boundaryGap ? layoutData.length : layoutData.length - 1); for (let i = 0; i < layoutData.length; i++) { if (i === 0) continue; if (layoutData[i]?.isSampled === false) continue; this.painter.draw('Line', { x1: i * tickGap, y1: 0, x2: i * tickGap, y2: size.height, lineWidth: 1, strokeStyle: BaseToken?.COLOR?.GRAY_3 ?? '#ddd', }); } } }