@jiaminghi/charts
Version:
Lightweight charting
247 lines (167 loc) • 5.45 kB
JavaScript
import { extendNewGraph } from '@jiaminghi/c-render'
import { text } from '@jiaminghi/c-render/lib/config/graphs'
import { getCircleRadianPoint, checkPointIsInRect } from '@jiaminghi/c-render/lib/plugin/util'
import { getColorFromRgbValue } from '@jiaminghi/color'
import { getLinearGradientColor } from '../util/index'
const pie = {
shape: {
rx: 0,
ry: 0,
ir: 0,
or: 0,
startAngle: 0,
endAngle: 0,
clockWise: true
},
validator ({ shape }) {
const keys = ['rx', 'ry', 'ir', 'or', 'startAngle', 'endAngle']
if (keys.find(key => typeof shape[key] !== 'number')) {
console.error('Pie shape configuration is abnormal!')
return false
}
return true
},
draw ({ ctx }, { shape }) {
ctx.beginPath()
let { rx, ry, ir, or, startAngle, endAngle, clockWise } = shape
rx = parseInt(rx) + 0.5
ry = parseInt(ry) + 0.5
ctx.arc(rx, ry, ir > 0 ? ir : 0, startAngle, endAngle, !clockWise)
const connectPoint1 = getCircleRadianPoint(rx, ry, or, endAngle).map(p => parseInt(p) + 0.5)
const connectPoint2 = getCircleRadianPoint(rx, ry, ir, startAngle).map(p => parseInt(p) + 0.5)
ctx.lineTo(...connectPoint1)
ctx.arc(rx, ry, or > 0 ? or : 0, endAngle, startAngle, clockWise)
ctx.lineTo(...connectPoint2)
ctx.closePath()
ctx.stroke()
ctx.fill()
}
}
const agArc = {
shape: {
rx: 0,
ry: 0,
r: 0,
startAngle: 0,
endAngle: 0,
gradientStartAngle: null,
gradientEndAngle: null
},
validator ({ shape }) {
const keys = ['rx', 'ry', 'r', 'startAngle', 'endAngle']
if (keys.find(key => typeof shape[key] !== 'number')) {
console.error('AgArc shape configuration is abnormal!')
return false
}
return true
},
draw ({ ctx }, { shape, style }) {
let { gradient } = style
gradient = gradient.map(cv => getColorFromRgbValue(cv))
if (gradient.length === 1) {
gradient = [gradient[0], gradient[0]]
}
const gradientArcNum = gradient.length - 1
let { gradientStartAngle, gradientEndAngle, startAngle, endAngle, r, rx, ry } = shape
if (gradientStartAngle === null) gradientStartAngle = startAngle
if (gradientEndAngle === null) gradientEndAngle = endAngle
let angleGap = (gradientEndAngle - gradientStartAngle) / gradientArcNum
if (angleGap === Math.PI * 2) angleGap = Math.PI * 2 - 0.001
for (let i = 0; i < gradientArcNum; i++) {
ctx.beginPath()
const startPoint = getCircleRadianPoint(rx, ry, r, startAngle + angleGap * i)
const endPoint = getCircleRadianPoint(rx, ry, r, startAngle + angleGap * (i + 1))
const color = getLinearGradientColor(ctx, startPoint, endPoint, [gradient[i], gradient[i + 1]])
const arcStartAngle = startAngle + angleGap * i
let arcEndAngle = startAngle + angleGap * (i + 1)
let doBreak = false
if (arcEndAngle > endAngle) {
arcEndAngle = endAngle
doBreak = true
}
ctx.arc(rx, ry, r, arcStartAngle, arcEndAngle)
ctx.strokeStyle = color
ctx.stroke()
if (doBreak) break
}
}
}
const numberText = {
shape: {
number: [],
content: '',
position: [0, 0],
toFixed: 0,
rowGap: 0,
formatter: null
},
validator ({ shape }) {
const { number, content, position } = shape
if (!(number instanceof Array) || typeof content !== 'string' || !(position instanceof Array)) {
console.error('NumberText shape configuration is abnormal!')
return false
}
return true
},
draw ({ ctx }, { shape }) {
const { number, content, toFixed, rowGap, formatter } = shape
const textSegments = content.split('{nt}')
let textString = ''
textSegments.forEach((t, i) => {
let currentNumber = number[i]
if (typeof currentNumber !== 'number') currentNumber = ''
if (typeof currentNumber === 'number') {
currentNumber = currentNumber.toFixed(toFixed)
if (typeof formatter === 'function') currentNumber = formatter(currentNumber)
}
textString += t + (currentNumber || '')
})
text.draw({ ctx }, { shape: { ...shape, content: textString, rowGap } })
}
}
const lineIcon = {
shape: {
x: 0,
y: 0,
w: 0,
h: 0
},
validator ({ shape }) {
const { x, y, w, h } = shape
if (typeof x !== 'number' || typeof y !== 'number' || typeof w !== 'number' || typeof h !== 'number') {
console.error('lineIcon shape configuration is abnormal!')
return false
}
return true
},
draw ({ ctx }, { shape }) {
ctx.beginPath()
let { x, y, w, h } = shape
const halfH = h / 2
ctx.strokeStyle = ctx.fillStyle
ctx.moveTo(x, y + halfH)
ctx.lineTo(x + w, y + halfH)
ctx.lineWidth = 1
ctx.stroke()
ctx.beginPath()
let radius = halfH - 5 * 2
if (radius <= 0) radius = 3
ctx.arc(x + w / 2, y + halfH, radius, 0, Math.PI * 2)
ctx.lineWidth = 5
ctx.stroke()
ctx.fillStyle = '#fff'
ctx.fill()
},
hoverCheck (position, { shape }) {
let { x, y, w, h } = shape
return checkPointIsInRect(position, x, y, w, h)
},
setGraphCenter (e, { shape, style }) {
const { x, y, w, h } = shape
style.graphCenter = [x + w / 2, y + h / 2]
},
}
extendNewGraph('pie', pie)
extendNewGraph('agArc', agArc)
extendNewGraph('numberText', numberText)
extendNewGraph('lineIcon', lineIcon)