score:3
Previous Solution
You can change your dataset a bit to achieve that:
backgroundColor: ["green", "green", "green", "yellow", "yellow", "yellow", "yellow", "red", "red", "red"],
gaugeLimits: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
Since your gagueLimits
are split into a range of 20
currently, so you can't access the limit of 30,
So, what I did here is elaborated the guageLimits
to a split range of 10
and now 30
is accessible, so is 70
,
Now about the colors, each of your guageLimits
require a color in the backgroundColor
array, I set them accordingly, check the above array. Since none of the corresponding colors can be empty, you might need to use the same color until you reach the next color range.
Updated Solution
Your requirements cleared now:
- You want the gauge labels to not be too cozy, which is why a limit of 20.
- And you want to separate the color ranges to 30 and 70 points.
Now, technically if you want to set a color range to a specific point, you need to have that value on the gaugeLimits
array, so your reduced gaugeLimits
array now becomes like this:
gaugeLimits: [0, 20, 30, 40, 60, 70, 80, 100],
Well, no you can set the colors accordingly since you have the points specified in the array. Hence, the backgroundColor
array is:
backgroundColor: ["#0fdc63", "#0fdc63", "#fd9704", "#fd9704", "#fd9704", "#ff7143", "#ff7143"]
Now, the final Trick
You still need to hide the 30, and 70 from the scale, I tried to toggle the showMarkers
in your code, looks like it either enables or disables the visible number scale entirely, I tried to provide an array of strings, but it only accepts boolean
Chartjs-tsgauge Doesn't provide much documentation about available options, so I snuck into the code and found markerFormatFn
What it does is take a function as a parameter and you can provide a function telling what to do with each of your marker items.
So, I came up with an idea to provide a function to only show the numbers which are dividable by 20 without any remainder, otherwise return empty string, here it is:
markerFormatFn: n => n % 20 === 0 ? n.toString() : '',
Check the Snippet:
//Gauge Plugin
(function() {
if (!window.Chart) {
return;
}
function GaugeChartHelper() {}
GaugeChartHelper.prototype.setup = function(chart, config) {
this.chart = chart;
this.ctx = chart.ctx;
this.limits = config.data.datasets[0].gaugeLimits;
this.data = config.data.datasets[0].gaugeData;
var options = chart.options;
this.fontSize = options.defaultFontSize;
this.fontStyle = options.defaultFontFamily;
this.fontColor = options.defaultFontColor;
this.ctx.textBaseline = "alphabetic";
this.arrowAngle = 25 * Math.PI / 180;
this.arrowColor = config.options.indicatorColor || options.arrowColor;
this.showMarkers =
typeof config.options.showMarkers === "undefined" ?
true :
config.options.showMarkers;
if (config.options.markerFormatFn) {
this.markerFormatFn = config.options.markerFormatFn;
} else {
this.markerFormatFn = function(value) {
return value;
};
}
};
GaugeChartHelper.prototype.applyGaugeConfig = function(chartConfig) {
this.calcLimits();
chartConfig.data.datasets[0].data = this.doughnutData;
var ctx = this.ctx;
var labelsWidth = this.limits.map(
function(label) {
var text = this.markerFormatFn(label);
return ctx.measureText(text).width;
}.bind(this)
);
var padding = Math.max.apply(this, labelsWidth) + this.chart.width / 35;
var heightRatio = this.chart.height / 50;
chartConfig.options.layout.padding = {
top: this.fontSize + heightRatio,
left: padding,
right: padding,
bottom: heightRatio * 2
};
};
GaugeChartHelper.prototype.calcLimits = function() {
var limits = this.limits;
var data = [];
var total = 0;
for (var i = 1, ln = limits.length; i < ln; i++) {
var dataValue = Math.abs(limits[i] - limits[i - 1]);
total += dataValue;
data.push(dataValue);
}
this.doughnutData = data;
var minValue = limits[0];
var maxValue = limits[limits.length - 1];
this.isRevers = minValue > maxValue;
this.minValue = this.isRevers ? maxValue : minValue;
this.totalValue = total;
};
GaugeChartHelper.prototype.updateGaugeDimensions = function() {
var chartArea = this.chart.chartArea;
this.gaugeRadius = this.chart.innerRadius;
this.gaugeCenterX = (chartArea.left + chartArea.right) / 2;
this.gaugeCenterY =
(chartArea.top + chartArea.bottom + this.chart.outerRadius) / 2;
this.arrowLength = this.chart.radiusLength * 2;
};
GaugeChartHelper.prototype.getCoordOnCircle = function(r, alpha) {
return {
x: r * Math.cos(alpha),
y: r * Math.sin(alpha)
};
};
GaugeChartHelper.prototype.getAngleOfValue = function(value) {
var result = 0;
var gaugeValue = value - this.minValue;
if (gaugeValue <= 0) {
result = 0;
} else if (gaugeValue >= this.totalValue) {
result = Math.PI;
} else {
result = Math.PI * gaugeValue / this.totalValue;
}
if (this.isRevers) {
return Math.PI - result;
} else {
return result;
}
};
GaugeChartHelper.prototype.renderLimitLabel = function(value) {
var ctx = this.ctx;
var angle = this.getAngleOfValue(value);
var coord = this.getCoordOnCircle(
this.chart.outerRadius + this.chart.radiusLength / 2,
angle
);
var align;
var diff = angle - Math.PI / 2;
if (diff > 0) {
align = "left";
} else if (diff < 0) {
align = "right";
} else {
align = "center";
}
ctx.textAlign = align;
ctx.font = this.fontSize + "px " + this.fontStyle;
ctx.fillStyle = this.fontColor;
var text = this.markerFormatFn(value);
ctx.fillText(
text,
this.gaugeCenterX - coord.x,
this.gaugeCenterY - coord.y
);
};
GaugeChartHelper.prototype.renderLimits = function() {
for (var i = 0, ln = this.limits.length; i < ln; i++) {
this.renderLimitLabel(this.limits[i]);
}
};
GaugeChartHelper.prototype.renderValueLabel = function() {
var label = this.data.value.toString();
var ctx = this.ctx;
ctx.font = "30px " + this.fontStyle;
var stringWidth = ctx.measureText(label).width;
var elementWidth = 0.75 * this.gaugeRadius * 2;
var widthRatio = elementWidth / stringWidth;
var newFontSize = Math.floor(30 * widthRatio);
var fontSizeToUse = Math.min(newFontSize, this.gaugeRadius);
ctx.textAlign = "center";
ctx.font = fontSizeToUse + "px " + this.fontStyle;
ctx.fillStyle = this.data.valueColor || this.fontColor;
ctx.fillText(label, this.gaugeCenterX, this.gaugeCenterY);
};
GaugeChartHelper.prototype.renderValueArrow = function(value) {
var angle = this.getAngleOfValue(
typeof value === "number" ? value : this.data.value
);
this.ctx.globalCompositeOperation = "source-over";
this.renderArrow(
this.gaugeRadius,
angle,
this.arrowLength,
this.arrowAngle,
this.arrowColor
);
};
GaugeChartHelper.prototype.renderSmallValueArrow = function(value) {
var angle = this.getAngleOfValue(value);
this.ctx.globalCompositeOperation = "source-over";
this.renderArrow(
this.gaugeRadius - 1,
angle,
this.arrowLength - 1,
this.arrowAngle,
this.arrowColor
);
};
GaugeChartHelper.prototype.clearValueArrow = function(value) {
var angle = this.getAngleOfValue(value);
this.ctx.lineWidth = 2;
this.ctx.globalCompositeOperation = "destination-out";
this.renderArrow(
this.gaugeRadius - 1,
angle,
this.arrowLength + 1,
this.arrowAngle,
"#FFFFFF"
);
this.ctx.stroke();
};
GaugeChartHelper.prototype.renderArrow = function(
radius,
angle,
arrowLength,
arrowAngle,
arrowColor
) {
var coord = this.getCoordOnCircle(radius, angle);
var arrowPoint = {
x: this.gaugeCenterX - coord.x,
y: this.gaugeCenterY - coord.y
};
var ctx = this.ctx;
ctx.fillStyle = arrowColor;
ctx.beginPath();
ctx.moveTo(arrowPoint.x, arrowPoint.y);
coord = this.getCoordOnCircle(arrowLength, angle + arrowAngle);
ctx.lineTo(arrowPoint.x + coord.x, arrowPoint.y + coord.y);
coord = this.getCoordOnCircle(arrowLength, angle - arrowAngle);
ctx.lineTo(arrowPoint.x + coord.x, arrowPoint.y + coord.y);
ctx.closePath();
ctx.fill();
};
GaugeChartHelper.prototype.animateArrow = function() {
var stepCount = 30;
var animateTimeout = 300;
var gaugeValue = this.data.value - this.minValue;
var step = gaugeValue / stepCount;
var i = 0;
var currentValue = this.minValue;
var interval = setInterval(
function() {
i++;
this.clearValueArrow(currentValue);
if (i > stepCount) {
clearInterval(interval);
this.renderValueArrow();
} else {
currentValue += step;
this.renderSmallValueArrow(currentValue);
}
}.bind(this),
animateTimeout / stepCount
);
};
Chart.defaults.tsgauge = {
animation: {
animateRotate: true,
animateScale: false
},
cutoutPercentage: 95,
rotation: Math.PI,
circumference: Math.PI,
legend: {
display: false
},
scales: {},
arrowColor: "#444"
};
Chart.controllers.tsgauge = Chart.controllers.doughnut.extend({
initialize: function(chart) {
var gaugeHelper = (this.gaugeHelper = new GaugeChartHelper());
gaugeHelper.setup(chart, chart.config);
gaugeHelper.applyGaugeConfig(chart.config);
chart.config.options.animation.onComplete = function(chartElement) {
gaugeHelper.updateGaugeDimensions();
gaugeHelper.animateArrow();
};
Chart.controllers.doughnut.prototype.initialize.apply(this, arguments);
},
draw: function() {
Chart.controllers.doughnut.prototype.draw.apply(this, arguments);
var gaugeHelper = this.gaugeHelper;
gaugeHelper.updateGaugeDimensions();
gaugeHelper.renderValueLabel();
if (gaugeHelper.showMarkers) {
gaugeHelper.renderLimits();
}
gaugeHelper.renderSmallValueArrow(gaugeHelper.minValue);
}
});
})();
//Chart setup
var ctx = document.getElementById("chart3").getContext("2d");
new Chart(ctx, {
type: "tsgauge",
data: {
datasets: [{
backgroundColor: ["#0fdc63", "#0fdc63", "#fd9704", "#fd9704", "#fd9704", "#ff7143", "#ff7143"],
borderWidth: 0,
gaugeData: {
value: 50,
valueColor: "#ff7143"
},
gaugeLimits: [0, 20, 30, 40, 60, 70, 80, 100],
}]
},
options: {
events: [],
showMarkers: true,
markerFormatFn: n => n % 20 === 0 ? n.toString() : '',
}
});
.gauge {
width: 500px;
height: 400px;
}
<link href="https://cdn.jsdelivr.net/npm/chart.js@2.9.2/dist/Chart.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.2/dist/Chart.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<div class="gauge">
<canvas id="chart3"></canvas>
</div>
Source: stackoverflow.com
Related Query
- Custom background limits for Doughnut (Gauge)
- How to add background color for doughnut mid using chart,js
- getting additional value fields from data source for dx.chartjs doughnut chart
- Chartjs Custom Legend for Doughnut Chart Having Labelled Lines Sticking Out of Each Section
- Chart.js Custom Image for Each Point
- chart.js Line chart with different background colors for each section
- Chart.js HTML custom legend issues with doughnut chart
- Chart js different background for y axis
- (Vue, ChartJS) Create gradient background for chart from child component canvas context
- How to set a full length background color for each bar in chartjs bar
- Chart.js Pie Chart: How to set background image for segment
- Using Chart.js - Creating Legend for Doughnut Chart
- Custom data position on the doughnut chart in chart.js
- How can I create custom tooltips for each data point in a graph?
- Create an interactive custom tooltip for chartjs
- Custom labeling/fixed range on x-axis in Chart.js for horizontal bar chart?
- ChartJS v2 custom tooltip for rLabel
- Need help in figuring out config for a custom tooltip (chartjs)
- chartjs custom y axis values, different text for each one
- Setting Common labels and background color common for all the charts in ChartJs
- Chart.js - PieChart defined background color for specific dataset element
- Chart JS pass in custom data for points
- How to create a custom tooltip for chartJS graph with data in JSON array in JavaScript?
- ChartJS doughnut data toggle on custom button click
- Custom empty screen for ng2-charts
- Set background color for individual bars using ChartJS?
- Set custom colours for tooltip squares Chart.js
- How to share same background color for multiple dataset in a chart?
- Chartjs doughnut chart rounded corners for half doghnut
- Chart.JS: How can I only display data labels when the doughnut size is big enough for the text?
More Query from same tag
- Chart.js pie chart not showing in Google Chrome canvas
- Chart.js don't work when I open my app as a stand alone app in Chrome
- How to change NaN values to 0 in Chart.js?
- Pass numeric matrix of rgb color values to chartJSRadar() in R
- ChartJs does not render chart when binding canvas id in Angular
- Range at the end of the line chart
- How to prevent empty bars from taking up width in Chart.js bar chart
- How do I remove the ticks or inner circles of my polar area chart Chart.js
- I want to show the value of label inside the pie graph. (vue-chartjs / pieceLabel)
- I can't add data to chartjs from codeigniter
- ChartJS animate only one dataset
- how to get React chartjs to resize back down with window
- ChartJS with React: Only one value showing on time chart
- lazy loaded modules share same dependencies?
- Show/hide All nested data in ChartJS Pie chart when outer is shown/hidden
- load a graph with chart.js and react
- Switching between Charts with chart.js using Buttons
- ChartJS Bar chart with time scale - Bars overlap with each other
- How to export a chart.js chart to excel?
- Angular Overlapping bars using chart.js
- Comparison between d3.js and chart.js (only for charts)
- how to pass function variable from one file to another in react
- Chart.js multiTooltip Labels in Pie
- ChartJs: x-axes min and max value not working
- Inserting percentage charts.js doughnut
- Minimum value for x Axis doesn't work for horizontal bar chart | ChartJS
- Display chart data based on API call
- Chart.js add label inside bubble chart
- dynamic charts using chart.js
- how do I make chart.js smaller? (html, chart.js)