0👍
You can create something similar using chart.js; almost anything can be charted with it, as it is an open system with strong support for customization. Still, how much effort it would take to implement a type of chart that is not natively supported may vary.
For the type of chart you describe in your image, I’d go with the following:
- a mixed chart: lines with stacking and fill to draw quadrants
- a bubble plot for … the bubbles
- chartjs-plugin-annotation for the texts in the corners
- chartjs-plugin-datalabels for the labels of the bubbles
Here’s an example that can get you started, containing all those ingredients as a proof of concept – there’s still a lot to do to achieve something useful in production. In particular, the tooltip is just the standard version, so you’ll need to configure it using the extensive set of options available in the library (see the docs).
Chart.register(ChartDataLabels)
const xMin = 90, xMax = 110;
const yMin = 90, yMax = 110;
const xHalf = (xMin+xMax)/2, xHalfPlus = xHalf + 1e-6,
yHalf = (yMin + yMax)/2, yHalfDist = (yMax - yMin)/2;
new Chart(document.getElementById('chart'), {
type: "line",
data: {
datasets: [{
data: [
{x: xMin, y: yHalf},
{x: xHalf, y:yHalf},
{x: xHalfPlus, y: null},
{x: xMax, y: null}
],
fill: true,
backgroundColor: "rgba(255, 160, 0, 0.5)",
pointRadius: 0,
showLine: false,
stacked: true,
order: 1
}, {
data: [
{x: xMin, y: yHalfDist},
{x: xHalf, y:yHalfDist},
{x: xHalfPlus, y: null},
{x: xMax, y: null}
],
fill: "-1",
backgroundColor: "rgba(0, 255, 255, 0.5)",
pointRadius: 0,
showLine: false,
stacked: true,
order: 2
},
{
data: [
{x: xMin, y: null},
{x: xHalf, y: null},
{x: xHalfPlus, y: yHalf},
{x: xMax, y:yHalf}
],
fill: true,
backgroundColor: "rgba(255, 255, 0, 0.5)",
pointRadius: 0,
showLine: false,
order: 1
},
{
data: [
{x: xMin, y: null},
{x: xHalf, y: null},
{x: xHalfPlus, y: yHalfDist},
{x: xMax, y:yHalfDist}
],
fill: "-1",
backgroundColor: "rgba(0, 192, 160, 0.5)",
pointRadius: 0,
showLine: false,
order: 2
},
{
type: "bubble",
data: [
{x: 101, y: 97.2, r: 18, label: "ABCD"},
{x: 102, y: 103.4, r: 11, label: "WEDW"},
{x: 103, y: 102.2, r: 11, label: "CESA"},
{x: 98, y: 101.4, r: 11, label: "QWEX"}
],
backgroundColor: 'rgba(64, 64, 128, 0.7)',
order: 0,
label: "my data"
}
]},
options: {
scales: {
x: {
type: "linear",
min: xMin,
max: xMax,
},
y: {
min: yMin,
max: yMax,
stacked: true,
}
},
plugins:{
legend:{
labels:{
filter(ctx){
// no legend for the four quadrants
if(ctx.datasetIndex < 4) return false;
return true;
}
}
},
datalabels:{
anchor:'center',
align: 'center',
color: '#000',
clamp: true,
font: {
weight: 'bold'
},
formatter: function(value) {
//console.log(value)
return value.label || ''
},
},
annotation: {
annotations: {
label1: {
type: 'label',
content: 'Lagging',
xValue: xMin,
yValue: yMin,
position:{x: "start", y: "end"},
color: 'rgba(0,0,0,0.6)',
},
label2: {
type: 'label',
content: 'Weakening',
xValue: xMax,
yValue: yMin,
position:{x: "end", y: "end"},
color: 'rgba(0,0,0,0.6)'
},
label3: {
type: 'label',
content: 'Improving',
xValue: xMin,
yValue: yMax,
position:{x: "start", y: "start"},
color: 'rgba(0,0,0,0.6)'
},
label4: {
type: 'label',
content: 'Leading',
xValue: xMax,
yValue: yMax,
position:{x: "end", y: "start"},
color: 'rgba(0,0,0,0.6)'
}
},
font: {
size: 22
}
}
}
}
});
<div style="width:900px; height: 700px">
<canvas id="chart"></canvas>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.3.0/chart.umd.js" integrity="sha512-CMF3tQtjOoOJoOKlsS7/2loJlkyctwzSoDK/S40iAB+MqWSaf50uObGQSk5Ny/gfRhRCjNLvoxuCvdnERU4WGg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.2.0/chartjs-plugin-datalabels.min.js" integrity="sha512-JPcRR8yFa8mmCsfrw4TNte1ZvF1e3+1SdGMslZvmrzDYxS69J7J49vkFL8u6u8PlPJK+H3voElBtUCzaXj+6ig==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-annotation/2.2.1/chartjs-plugin-annotation.min.js" integrity="sha512-qF3T5CaMgSRNrxzu69V3ZrYGnrbRMIqrkE+OrE01DDsYDNo8R1VrtYL8pk+fqhKxUBXQ2z+yV/irk+AbbHtBAg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
- Chartjs-Two line datasets with different size (different labels) in chart.js
- Chartjs-Chart.js 4 linear gradient based on the lowest values
Source:stackexchange.com