Solution précédente
Vous pouvez modifier un peu votre jeu de données pour y parvenir:
backgroundColor: ["green", "green", "green", "yellow", "yellow", "yellow", "yellow", "red", "red", "red"],
gaugeLimits: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
Étant donné que vous gagueLimits
êtes actuellement divisé en plusieurs catégories 20
, vous ne pouvez donc pas accéder à la limite de 30,
Donc, ce que j'ai fait ici est élaboré guageLimits
sur une plage fractionnée de 10
et 30
est maintenant accessible, tout comme 70
,
Maintenant, à propos des couleurs, chacune de vos guageLimits
nécessite une couleur dans le backgroundColor
tableau, je les ai définies en conséquence, vérifiez le tableau ci-dessus. Puisqu'aucune des couleurs correspondantes ne peut être vide, vous devrez peut-être utiliser la même couleur jusqu'à ce que vous atteigniez la gamme de couleurs suivante.
Solution mise à jour
Vos exigences sont maintenant remplies:
- Vous voulez que les étiquettes de jauge ne soient pas trop confortables, c'est pourquoi une limite de 20.
- Et vous souhaitez séparer les plages de couleurs à 30 et 70 points.
Maintenant, techniquement, si vous souhaitez définir une plage de couleurs à un point spécifique, vous devez avoir cette valeur sur le gaugeLimits
tableau, de sorte que votre gaugeLimits
tableau réduit devient maintenant comme ceci:
gaugeLimits: [0, 20, 30, 40, 60, 70, 80, 100],
Eh bien, non, vous pouvez définir les couleurs en conséquence puisque vous avez les points spécifiés dans le tableau. Par conséquent, le backgroundColor
tableau est:
backgroundColor: ["#0fdc63", "#0fdc63", "#fd9704", "#fd9704", "#fd9704", "#ff7143", "#ff7143"]
Maintenant, le dernier tour
Vous devez toujours masquer les 30 et 70 de l'échelle, j'ai essayé de basculer le showMarkers
dans votre code, on dirait qu'il active ou désactive entièrement l'échelle des nombres visibles, j'ai essayé de fournir un tableau de chaînes, mais il n'accepte queboolean
Chartjs-tsgauge Ne fournit pas beaucoup de documentation sur les options disponibles, donc je me suis glissé dans le code et j'ai trouvémarkerFormatFn
Ce qu'il fait, c'est prendre une fonction comme paramètre et vous pouvez fournir une fonction indiquant quoi faire avec chacun de vos éléments marqueurs.
Donc, j'ai eu l'idée de fournir une fonction pour n'afficher que les nombres qui sont divisibles par 20 sans aucun reste, sinon retournez une chaîne vide, la voici:
markerFormatFn: n => n % 20 === 0 ? n.toString() : '',
Vérifiez l'extrait:
//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>