目录
Vue3 + hook + Apexcharts实现可视化图表渲染的封装 - 第一节 - 基础封装
Vue3 + hook + Apexcharts实现可视化图表渲染的封装 - 第二节 - 图表的全屏功能
Apexcharts实现BoxPlot中绘制散点 - 第三节
Apexcharts实现双/多Line图 - 每条线的点数不同 - 第四节(当前所在)
摘要
Apexcharts中的Line图必须设置 x轴中
catgories
,如果不设置默认应该是index + 1
作为x轴的坐标。但是categories
是固定的,这时候如果有两条曲线点数不同,绘制上去之后就会出现问题。
实现效果
思路
Apexcharts中的Line 图并不支持画这种多曲线图,因为
catgories
是固定的x轴也就是固定的了。这种图一般是用来对比线与线之间的趋势,但是每条曲线的坐标个数不同。
换句话来说我们就是要先画坐标点,坐标点个数不同也能画那就是Apexcharts中的scatter
图,也就是说先画散点图在通过操作svg
元素将这些点进行连线,同样是和上一节一样进行在updated
事件中进行DOM
操作的方式。
代码实现
// 用坐标点画线
const paintLine = (el, points, i) => {
const colors = ['#8b509d', '#106aa7']
const svg = el.querySelector('.apexcharts-inner')
const polyline = document.createElementNS('http://www.w3.org/2000/svg', 'polyline')
const pointsStr = points.map(point => `${point.x},${point.y}`).join(' ')
polyline.setAttribute('points', pointsStr)
polyline.setAttribute('fill', 'none')
polyline.setAttribute('stroke', colors[i])
polyline.setAttribute('stroke-width', '2')
svg.appendChild(polyline)
}
// 画点数不同的line图表;先画散点图,再通过操作DOM的形式连线
export const paintLineChart = (el) => {
Array.from(el.querySelectorAll('.apexcharts-series')).forEach((item, i) => {
const pointsArr = Array.from(item.querySelectorAll('circle'))
// 获取每个点的坐标
const points = pointsArr.map(point => {
const x = point.getAttribute('cx')
const y = point.getAttribute('cy')
return { x, y }
})
paintLine(el, points, i)
})
}
附上一个完整案例的html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ApexCharts - Mixed Chart with Heatmap and Bar</title>
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
</head>
<body>
<!-- <svg xmlns="http://www.w3.org/2000/svg">
<polyline points="50,50 100,200 150,150 200,250 250,100" fill="none" stroke="black" />
</svg> -->
<div id="chart" style="width: 50vw;"></div>
<script>
const colors = ['#8b509d', '#106aa7']
var options = {
series: [{
name: "SAMPLE A",
// 随机生成20个坐标点
data: [
[1.3, 14], [2.7, 18], [4.3, 20], [5.7, 26], [7.3, 38], [8.7, 44], [10.3, 56], [11.7, 64], [13.3, 66], [14.7, 68], [16.3, 70], [17.7, 72], [19.3, 74], [20.7, 76], [22.3, 78], [23.7, 80], [25.3, 82], [26.7, 84], [28.3, 86], [29.7, 88]]
},{
name: "SAMPLE B",
// 随机生成10个坐标点, x轴不能和上面一样
data: [
[1, 14], [2, 18], [4, 20], [6, 26], [8, 38], [10, 44], [12, 56], [14, 64], [16, 66], [18, 68], [29.7, 90]]
}],
chart: {
height: 500,
type: 'scatter',
zoom: {
enabled: false,
}
},
xaxis: {
tickAmount: 10,
labels: {
formatter: function(val) {
return parseFloat(val).toFixed(1)
}
}
},
yaxis: {
tickAmount: 7
},
markers: {
size: 1,
},
colors: colors,
};
var chart = new ApexCharts(document.querySelector("#chart"), options);
chart.render();
Array.from(document.querySelectorAll('.apexcharts-series')).forEach((el, i) => {
const pointsArr = Array.from(el.querySelectorAll('circle'))
// 获取每个点的坐标
const points = pointsArr.map(point => {
const x = point.getAttribute('cx')
const y = point.getAttribute('cy')
return { x, y }
})
console.log(points)
paintLine(points, i)
})
// 用坐标点画线
function paintLine(points, i) {
const svg = document.querySelector('.apexcharts-inner')
const polyline = document.createElementNS('http://www.w3.org/2000/svg', 'polyline')
const pointsStr = points.map(point => `${point.x},${point.y}`).join(' ')
polyline.setAttribute('points', pointsStr)
polyline.setAttribute('fill', 'none')
polyline.setAttribute('stroke', colors[i])
polyline.setAttribute('stroke-width', '2')
svg.appendChild(polyline)
}
</script>
</body>
</html>