Vue.js ApexCharts 圆角柱状图(带背景)实现详解
2025-03-16 13:40:45
Vue.js 中使用 ApexCharts 实现圆角垂直柱状图(带背景容器)
遇到一个需求,要在 Vue.js 项目中用 ApexCharts 创建一个特殊的垂直柱状图。每个柱子不仅要有圆角,还要有一个浅灰色的背景容器,里边填充蓝色的值条,就像一个胶囊形状。虽然 ApexCharts 提供了圆角选项,但实现这个特定的样式还是有点绕。
目前的代码只能做出基本的圆角柱状图,离目标效果还差得远。
问题出在哪?
主要问题在于 ApexCharts 的 borderRadius
属性只会作用于实际数据对应的柱子(蓝色部分),而不能直接给每个柱子加一个背景容器。 而且单纯通过修改 plotOptions.bar
下的相关设置也做不出想要的两层结构。
解决思路和具体实现
经过一番尝试和研究,整理出下面几种实现方案,一步步来解决这个问题。
方案一:利用 dataLabels
自定义样式 (推荐)
这种方案利用 dataLabels
的 formatter
方法对每个数据点单独渲染, 生成特定结构来实现背景容器。
原理:
dataLabels
本来是用来显示数据标签的。通过自定义其内容和样式,可以“借用”这个位置来渲染我们的背景和填充条。formatter
函数能够提供对每个数据点的自定义控制,对实现复杂样式帮助极大。
实现步骤:
-
修改
chartOptions
:const chartOptions = ref({ chart: { type: "bar", toolbar: { show: false } }, plotOptions: { bar: { borderRadius: 20, // 用于内部蓝色填充条 columnWidth: '25%' }, }, grid: { show: false }, xaxis: { labels: { show: false }, axisBorder: { show: false, }, axisTicks: { show: false } }, yaxis: { show: false }, dataLabels: { enabled: true, style: { colors: ['#333'] // 不会实际用到,占位 }, formatter: function(val, opts) { const maxValue = 100; // 根据你的实际最大值修改 const percent = ((val / maxValue) * 100).toFixed(0); // 计算百分比 return `<div style="height: 145px; width: 16px; border-radius: 20px; background-color: #E9EDF7; position: relative; overflow: hidden;"> <div style="position: absolute; bottom: 0; left: 0; width: 100%; height: ${percent}%; background-color: #1A75FF; border-radius: 20px;"></div> </div>` } } });
- 重点在
dataLabels.formatter
: 在这个函数里,直接返回了一个包含两层结构的 HTML 字符串: - 外层
div
:设置了高度、宽度、圆角和浅灰色背景(#E9EDF7
)。position: relative;
和overflow: hidden;
用于控制内层填充条的显示。 - 内层
div
:通过height: ${percent}%;
动态设置高度来表示数据值。设置了蓝色背景(#1A75FF
)和圆角。 dataLabels.style.colors
仅仅是一个占位, 由于我们自定义了formatter
返回HTML,因此原本的颜色设置不会生效。
- 重点在
进阶使用技巧:
可以根据具体的数据极值进行计算,让每一个柱形图都可以顶到最上方。修改formatter, 在其中通过opts.series[opts.seriesIndex][opts.dataPointIndex]
获取当前点的值,Math.max(...opts.series[opts.seriesIndex])
获取当前series的最大值,替换上方代码写死的maxValue
.
方案二:使用自定义 Annotation(Custom Annotations)
这种方式通过 ApexCharts 的 custom annotations 功能来实现容器效果,更为灵活,但配置相对复杂一些。
原理:
ApexCharts 的 annotations 允许你在图表上添加自定义元素,例如矩形、文本等。 用矩形来模拟背景容器。
实现步骤:
-
修改
chartOptions
:
先计算每个数据点所对应的的 annotationconst annotations = ref({ rect: [] }); onMounted(() => { series.value[0].data.forEach((value, index) => { annotations.value.rect.push( createAnnotation(index,value) ); }) })
再在chartOptions进行应用.
```javascript
const chartOptions = ref({
// ... 其他配置 ...
annotations: annotations.value, //增加配置
// ... 其他配置 ...
});
```
```javascript
function createAnnotation(index, value)
{
const maxValue = 100; // 最大值
//根据需要, 计算xy坐标和尺寸
let x1 = 25 * (index+1)
let x2 = x1+ 15
let y1 = maxValue-value
let y2 = maxValue
return {
x: x1,
x2:x2,
y:y1,
y2: y2,
borderColor: 'transparent',
fillColor: '#E9EDF7',
borderRadius:20,
}
}
```
* 计算位置时,可能需要考虑边距和间隔, 上述只是一个范例。
* 添加多个 `rect` annotation 对象到 `annotations.rect` 数组中。每个对象代表一个柱子的背景容器:
* `x`、`x2`、`y`、`y2`: 通过计算得到每个矩形的准确位置和尺寸。需要仔细调整这些值来匹配你的图表。
* `borderColor`: 设为 `'transparent'`。
* `fillColor`: 设为 `#E9EDF7`(浅灰色)。
-
修改 Series 部分
同时, 为了数据柱也能有圆角效果,不要忘记调整Series 部分,增加:plotOptions: { bar: { borderRadius: 20, columnWidth: "25%" //按需进行调整 } },
额外建议:
- 由于涉及较多的手动计算, 为了更准确,建议开启xaxis, yaxis的显示用于位置调试,调整好以后再将其关闭.
- 要进行数值调整使之更契合真实图标需求。
方案三:利用SVG自定义绘制(不推荐,仅作思路参考)
ApexCharts 底层使用 SVG 渲染,所以可以直接操作生成的 SVG 元素来实现一些高级定制,但比较 hacky,并且要小心潜在的版本兼容性问题。
原理:
通过对 图标的SVG元素进行自定义,手动增加或者修改容器的图形。
这种方式不推荐,因为涉及到非常规的SVG操作,步骤也相对烦琐,容易导致不可预期的问题。不作展开,只作思路参考。
总结
实现这个带有背景容器的圆角柱状图效果,第一种使用dataLabels
是最方便的,第二种方案比较通用,但实现更复杂一些. 第三种方案虽然灵活但实现成本非常高,不推荐.