You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ChartJS自定义左侧和底部坐标轴为虚线、顶部为实线边框的实现问题

ChartJS自定义多边框样式实现

需求说明

我有一个ChartJS图表,需要将左侧和底部坐标轴边框设置为虚线,顶部边框设置为单实线,预期效果如下:
效果示例

初始实现与问题

我最初通过自定义chartAreaBorder插件实现,代码如下:

const chartAreaBorder = {
        id: 'chartAreaBorder',
        beforeDraw(chart, args, options) {
            const { ctx, chartArea: { left, top, width, height } } = chart
            ctx.save()
            ctx.strokeStyle = options.borderColor
            ctx.lineWidth = options.borderWidth
            ctx.borderStyle = options.borderDash
            ctx.borderTopWidth = options.borderTopWidth
            ctx.setLineDash(options.borderDash || [])
            ctx.lineDashOffset = options.borderDashOffset
            ctx.strokeRect(left, top, width, height)
            ctx.restore()
        }
    }
    const config = {
        type: 'line',
        data: data,
        plugins: [ chartAreaBorder ],
        options: {
            plugins: {
                chartAreaBorder: {
                    borderColor: '#b1b1b1',
                    borderWidth: 10,
                    /*borderWidth: {
                        top:0,
                        right:0,
                        left:10,
                        bottom:10
                    },*/
                    borderDash: [ 1, 5 ],
                    borderDashOffset: 2,
                },
            }
        }
    }

当前得到的效果如下:
当前实现效果
遇到的问题是边框被应用到了图表的四个边,找不到隐藏顶部/右侧边框、或是为不同边框单独设置宽度的配置方法,无法实现四个边框分别设置不同样式的需求。

优化后解决方案

感谢@LeeLenalee的帮助,调整后的ChartAreaBorder插件支持为四个边框单独配置宽度、颜色、虚线样式等属性,实现代码如下:

const chartAreaBorder = {
    id: 'chartAreaBorder',
    afterDraw: (chart, args, opts) => {
        const {
            chartArea: {
                top,
                left,
                width,
                height
            },
            ctx
        } = chart
        const {
            borders: {
                tLtR, // 顶部边框(左上到右上)
                tLbL, // 左侧边框(左上到左下)
                tRbR, // 右侧边框(右上到右下)
                bLbR // 底部边框(左下到右下)
            }
        } = opts
        
        ctx.save()
        
        if ( tLtR && tLtR.borderWidth !== 0 ) {
            ctx.beginPath()
            ctx.strokeStyle = tLtR.borderColor || Chart.defaults.color
            ctx.lineWidth = tLtR.borderWidth || 0
            ctx.borderStyle = tLtR.borderDash || []
            ctx.setLineDash(tLtR.borderDash || [])
            ctx.lineDashOffset = tLtR.borderDashOffset || 0
            ctx.moveTo(left, top + 0.5)
            ctx.lineTo(left + width, top)
            ctx.stroke()
        }
        
        if ( tLbL && tLbL.borderWidth !== 0 ) {
            ctx.beginPath()
            ctx.strokeStyle = tLbL.borderColor || Chart.defaults.color
            ctx.lineWidth = tLbL.borderWidth || 0
            ctx.borderStyle = tLbL.borderDash || []
            ctx.setLineDash(tLbL.borderDash || [])
            ctx.lineDashOffset = tLbL.borderDashOffset || 0
            ctx.moveTo(left, top)
            ctx.lineTo(left, top + height - 5)
            ctx.stroke()
        }
        
        if ( tRbR && tRbR.borderWidth !== 0 ) {
            ctx.beginPath()
            ctx.strokeStyle = tRbR.borderColor || Chart.defaults.color
            ctx.lineWidth = tRbR.borderWidth || 0
            ctx.borderStyle = tRbR.borderDash || []
            ctx.setLineDash(tLbL.borderDash || [])
            ctx.lineDashOffset = tRbR.borderDashOffset || 0
            ctx.moveTo(left + width, top)
            ctx.lineTo(left + width, top + height)
            ctx.stroke()
        }
        
        if ( bLbR && bLbR.borderWidth !== 0 ) {
            ctx.beginPath()
            ctx.strokeStyle = bLbR.borderColor || Chart.defaults.color
            ctx.lineWidth = bLbR.borderWidth || 0
            ctx.borderStyle = bLbR.borderDash || []
            ctx.setLineDash(bLbR.borderDash || [])
            ctx.lineDashOffset = bLbR.borderDashOffset || 0
            ctx.moveTo(left, top + height)
            ctx.lineTo(left + width, top + height)
            ctx.stroke()
        }
        
        ctx.restore()
    }
}

// 插件配置示例
plugins: {
    chartAreaBorder: {
        borders: {
            tLtR: { // 顶部边框:实线
                borderWidth: 1,
                borderColor: '#b1b1b1'
            },
            tLbL: { // 左侧边框:虚线
                borderDash: [ 1, 5 ],
                borderWidth: 10,
                borderColor: '#b1b1b1'
            },
            tRbR: { // 右侧边框:隐藏
                borderWidth: 0
            },
            bLbR: { // 底部边框:虚线
                borderDash: [ 1, 5 ],
                borderWidth: 10,
                borderColor: '#b1b1b1'
            },
        }
    }
}

内容的提问来源于stack exchange,提问作者soDub

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 17:15:02