ChartJS 自定义左下轴边框
ChartJS customize left and bottom axe border
我有一个图表,需要在左侧和底部的 ax 上使用虚线边框,在顶部使用单线边框,如下面的屏幕截图所示。
这是我到目前为止取得的成就:
我使用 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,
},
}
}
}
}
这是我得到的:
所以我的问题是,边框应用于每个站点。我找不到任何选项来隐藏 top/right 边框或将 top/right borderWidth 设置为 0
有没有办法为图表的每个站点设置不同的边框?
编辑:
这是我的 ChartAreaBorder 使用优化代码的解决方案。感谢@LeeLenalee :)
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'
},
}
}
}
您可以不一次绘制矩形,而是分别绘制每条线:
const plugin = {
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.borderTopWidth = tLtR.borderTopWidth || 0;
ctx.setLineDash(tLtR.borderDash || []);
ctx.lineDashOffset = tLtR.borderDashOffset || 0;
ctx.moveTo(left, top);
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.borderTopWidth = tLbL.borderTopWidth || 0;
ctx.setLineDash(tLbL.borderDash || []);
ctx.lineDashOffset = tLbL.borderDashOffset || 0;
ctx.moveTo(left, top);
ctx.lineTo(left, top + height)
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.borderTopWidth = tRbR.borderTopWidth || 0;
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.borderTopWidth = bLbR.borderTopWidth || 0;
ctx.setLineDash(bLbR.borderDash || []);
ctx.lineDashOffset = bLbR.borderDashOffset || 0;
ctx.moveTo(left, top + height);
ctx.lineTo(left + width, top + height)
ctx.stroke();
}
ctx.restore();
}
}
const options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderWidth: 1
}
]
},
options: {
plugins: {
chartAreaBorder: {
borders: {
tLtR: {
borderWidth: 0,
},
tLbL: {},
tRbR: {
borderTopWidth: 2,
borderColor: 'red',
lineDashOffset: 5,
borderDash: [2, 2]
},
bLbR: {
borderDash: [2, 2]
},
}
}
}
},
plugins: [plugin]
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.js"></script>
</body>
我有一个图表,需要在左侧和底部的 ax 上使用虚线边框,在顶部使用单线边框,如下面的屏幕截图所示。
这是我到目前为止取得的成就: 我使用 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,
},
}
}
}
}
这是我得到的:
有没有办法为图表的每个站点设置不同的边框?
编辑: 这是我的 ChartAreaBorder 使用优化代码的解决方案。感谢@LeeLenalee :)
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'
},
}
}
}
您可以不一次绘制矩形,而是分别绘制每条线:
const plugin = {
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.borderTopWidth = tLtR.borderTopWidth || 0;
ctx.setLineDash(tLtR.borderDash || []);
ctx.lineDashOffset = tLtR.borderDashOffset || 0;
ctx.moveTo(left, top);
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.borderTopWidth = tLbL.borderTopWidth || 0;
ctx.setLineDash(tLbL.borderDash || []);
ctx.lineDashOffset = tLbL.borderDashOffset || 0;
ctx.moveTo(left, top);
ctx.lineTo(left, top + height)
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.borderTopWidth = tRbR.borderTopWidth || 0;
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.borderTopWidth = bLbR.borderTopWidth || 0;
ctx.setLineDash(bLbR.borderDash || []);
ctx.lineDashOffset = bLbR.borderDashOffset || 0;
ctx.moveTo(left, top + height);
ctx.lineTo(left + width, top + height)
ctx.stroke();
}
ctx.restore();
}
}
const options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderWidth: 1
}
]
},
options: {
plugins: {
chartAreaBorder: {
borders: {
tLtR: {
borderWidth: 0,
},
tLbL: {},
tRbR: {
borderTopWidth: 2,
borderColor: 'red',
lineDashOffset: 5,
borderDash: [2, 2]
},
bLbR: {
borderDash: [2, 2]
},
}
}
}
},
plugins: [plugin]
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.js"></script>
</body>