chartjs / chartjs/Chart.js

Chart.js 2.9.4 minBarLength issue with multiple chart

Open
#11,254 1 comment 0 reactions 0 assignees View on GitHub
type: enhancement
Dominant language
JavaScript
Stars
67.7k
Forks
11.9k
Avg merge
7h 39m
Merged PRs (30d)
5

Description

### Feature Proposal

Using the Chart.js 2.9.4 version, we are using both bar-type charts and line-type charts.

The problem is that the minimum value of the bar type chart is specified as 74 using the minBarLength option, but the line type chart does not keep up with the minimum value.

In other words, the line type should be drawn above the bar type, but it is not.
![image](https://user-images.githubusercontent.com/127506705/234488675-aa5c661a-4fe6-4f47-b33c-36ae5fbcf1c6.png)

/////////// code
```
chartOptions: function() {
var pricePack = ["5000000", null, "7777000", "10000", "7777000"];

var dataPack = ["2월 2일", "2월 9일", "2월 16일", "2월 23일", "3월 2일"];

var ctx = document.getElementById("chartType-bar");

$mainColor = "#eaf9fa";
$pointColor = "#89e5ee";
$borderColor = "#62d4e2";
$linePointColor = "#1d7f97";

Chart.elements.Rectangle.prototype.draw = function() {
var ctx = this._chart.ctx;
var vm = this._view;
var left, right, top, bottom, signX, signY, borderSkipped, radius;
var borderWidth = vm.borderWidth;

var cornerRadius = this._chart.config.options.cornerRadius;
if (cornerRadius < 0) {
cornerRadius = 0;
}
if (typeof cornerRadius == "undefined") {
cornerRadius = 0;
}

if (!vm.horizontal) {
left = vm.x - vm.width / 2;
right = vm.x + vm.width / 2;
top = vm.y;
bottom = vm.base;
signX = 1;
signY = bottom > top ? 1 : -1;
borderSkipped = vm.borderSkipped || "bottom";
} else {
left = vm.base;
right = vm.x;
top = vm.y - vm.height / 2;
bottom = vm.y + vm.height / 2;
signX = right > left ? 1 : -1;
signY = 1;
borderSkipped = vm.borderSkipped || "left";
}

if (borderWidth) {
var barSize = Math.min(Math.abs(left - right), Math.abs(top - bottom));
borderWidth = borderWidth > barSize ? barSize : borderWidth;
var halfStroke = borderWidth / 2;
var borderLeft =
left + (borderSkipped !== "left" ? halfStroke * signX : 0);
var borderRight =
right + (borderSkipped !== "right" ? -halfStroke * signX : 0);
var borderTop =
top + (borderSkipped !== "top" ? halfStroke * signY : 0);
var borderBottom =
bottom + (borderSkipped !== "bottom" ? -halfStroke * signY : 0);
if (borderLeft !== borderRight) {
top = borderTop;
bottom = borderBottom;
}
if (borderTop !== borderBottom) {
left = borderLeft;
right = borderRight;
}
}

ctx.beginPath();
ctx.fillStyle = vm.backgroundColor;
ctx.strokeStyle = vm.borderColor;
ctx.lineWidth = borderWidth;

var corners = [
[left, bottom],
[left, top],
[right, top],
[right, bottom],
];

var borders = ["bottom", "left", "top", "right"];
var startCorner = borders.indexOf(borderSkipped, 0);
if (startCorner === -1) {
startCorner = 0;
}

function cornerAt(index) {
return corners[(startCorner + index) % 4];
}

var corner = cornerAt(0);
ctx.moveTo(corner[0], corner[1]);

for (var i = 1; i < 4; i++) {
corner = cornerAt(i);
nextCornerId = i + 1;
if (nextCornerId == 4) {
nextCornerId = 0;
}

nextCorner = cornerAt(nextCornerId);

width = corners[2][0] - corners[1][0];
height = corners[0][1] - corners[1][1];
x = corners[1][0];
y = corners[1][1];

var radius = cornerRadius;
if (radius > Math.abs(height) / 2) {
radius = Math.floor(Math.abs(height) / 1);
}
if (radius > Math.abs(width) / 2) {
radius = Math.floor(Math.abs(width) / 2);
}

if (height < 0) {
x_tl = x;
x_tr = x + width;
y_tl = y + height;
y_tr = y + height;

x_bl = x;
x_br = x + width;
y_bl = y;
y_br = y;

ctx.moveTo(x_bl + radius, y_bl);
ctx.lineTo(x_br - radius, y_br);
ctx.quadraticCurveTo(x_br, y_br, x_br, y_br - radius);
ctx.lineTo(x_tr, y_tr + radius);
ctx.quadraticCurveTo(x_tr, y_tr, x_tr - radius, y_tr);
ctx.lineTo(x_tl + radius, y_tl);
ctx.quadraticCurveTo(x_tl, y_tl, x_tl, y_tl + radius);
ctx.lineTo(x_bl, y_bl - radius);
ctx.quadraticCurveTo(x_bl, y_bl, x_bl + radius, y_bl);
} else if (width < 0) {
x_tl = x + width;
x_tr = x;
y_tl = y;
y_tr = y;

x_bl = x + width;
x_br = x;
y_bl = y + height;
y_br = y + height;

ctx.moveTo(x_bl + radius, y_bl);
ctx.lineTo(x_br - radius, y_br);
ctx.quadraticCurveTo(x_br, y_br, x_br, y_br - radius);
ctx.lineTo(x_tr, y_tr + radius);
ctx.quadraticCurveTo(x_tr, y_tr, x_tr - radius, y_tr);
ctx.lineTo(x_tl + radius, y_tl);
ctx.quadraticCurveTo(x_tl, y_tl, x_tl, y_tl + radius);
ctx.lineTo(x_bl, y_bl - radius);
ctx.quadraticCurveTo(x_bl, y_bl, x_bl + radius, y_bl);
} else {
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height);
ctx.quadraticCurveTo(
x + width,
y + height,
x + width - radius,
y + height
);
ctx.lineTo(x, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
}
}

ctx.fill();
if (borderWidth) {
ctx.stroke();
}
};

Chart.defaults.global.defaultFontSize = 11;

var chartWrap = new Chart(ctx, {
type: "bar",
plugins: [{
afterDraw: function(chart) {
var ctx = chart.chart.ctx;
var xAxis = chart.scales["x-axis-0"];
var yAxis = chart.scales["y-axis-0"];
ctx.save();

ctx.textAlign = "center";

chart.data.labels.forEach(function(l, i) {
var value = chart.data.labels[i];
var x = xAxis.getPixelForValue(l);
var color = i === 0 ? $linePointColor : (chart.data.datasets[0].data[i] === null ? "#9e9e9e" : "#424242");
ctx.fillStyle = color;
ctx.fillText(value, x, yAxis.bottom + 18);
});

ctx.restore();
},
}, ],
data: {
datasets: [{
data: pricePack,
type: "line",
pointStyle: "circleRot",
pointBorderWidth: 3,
pointRadius: 7,
pointHoverRadius: 7,
pointHoverBackgroundColor: "#fff",
pointBorderColor: [
$linePointColor,
$pointColor,
$pointColor,
$pointColor,
$pointColor,
],
backgroundColor: "#fff",
borderColor: $borderColor,
lineTension: 0,
hoverBorderColor: [
$linePointColor,
$pointColor,
$pointColor,
$pointColor,
$pointColor,
],
hoverBorderWidth: "3",
borderWidth: 1,
spanGaps: true,
datalabels: {
font: function(context) {
if (context.dataIndex === 0) {
return {
weight: 700,
};
} else {
return {
weight: 500,
};
}
},
},
},
{
data: pricePack.map(function(val) {
return val || 0;
}),
type: "bar",
backgroundColor: pricePack.map(function(val, index) {
if (val === null) {
return "#e0e0e0";
} else if (index === 0) {
return $pointColor;
} else {
return $mainColor;
}
}),
borderColor: "#D3687F",
barThickness: 40,
minBarLength: pricePack.map(function(val, index) {
if (val === null) {
return 8;
} else {
return 74;
}
}),
hoverBackgroundColor: [
$pointColor,
$mainColor,
$mainColor,
$mainColor,
$mainColor,
],
},
],
labels: dataPack,
},
options: {
layout: {
padding: {
top: 24,
left: 0,
right: 0,
bottom: 20,
},
},
aspectRatio: 1,
maintainAspectRatio: false,
tooltips: false,
cornerRadius: 8,
legend: {
display: false,
},
plugins: {
datalabels: {
position: 'outside',
display: function(context) {
if (context.dataset.type === 'line' && context.dataset.data[context.dataIndex] !== null) {
return true;
} else if (context.dataset.type === 'bar' && context.dataset.data[context.dataIndex] === 0) {
return true;
} else {
return false;
}
},
color: function(context) {
if (context.dataset.type === 'bar' && context.dataset.data[context.dataIndex] === 0) {
return "#bdbdbd";
} else {
return ["#1d7f97", "#9e9e9e", "#9e9e9e", "#9e9e9e", "#9e9e9e"];
}
},
clamp: true,
clip: false,
anchor: "top",
align: "top",
overlap: 'auto',
offset: function(context) {
if (context.dataset.type === 'bar' && context.dataset.data[context.dataIndex] === 0) {
return 3;
} else {
return 8;
}
},
formatter: function(value, context) {
var result = value
.toString()
.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
if (value === 0) {
this.color = 'red';
return '수집중..';
} else {
return result;
}
}
},
},
scales: {
xAxes: [{
ticks: {
display: false,
beginAtZero: true,
},
gridLines: {
display: false,
},
}, ],
yAxes: [{
gridLines: {
display: false,
},
ticks: {
display: false,
beginAtZero: true,
},
}, ],
},
},
});
}
```

### Possible Implementation

Like the minBarLength of bar type, the minimum height value is added to the line type,
I hope it is added so that the line type can be drawn naturally by finding the offset top value of the bar type.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.