gpt4 book ai didi

javascript - donut (仪表)的自定义背景限制

转载 作者:行者123 更新时间:2023-12-04 04:28:05 27 4
gpt4 key购买 nike

我正在使用基于 (Chartjs-tsgauge) 的仪表图表。
我想为图表设置与仪表限制分开的背景颜色。如何的问题图表.JS 渲染背景,因为我使用的插件没有关于背景的代码。
例如,我有一个有限制的仪表 [0, 20, 40, 60, 80, 100] .我要设置[0-30]到绿色,[30-70]变成黄色和 [70-100]变红。
当前代码:CodePEN

这是我目前的选择。

var ctx = document.getElementById("canvas").getContext("2d");
new Chart(ctx, {
type: "tsgauge",
data: {
datasets: [{
backgroundColor: ["#0fdc63", "#fd9704", "#ff7143"],
borderWidth: 0,
gaugeData: {
value: 7777,
valueColor: "#ff7143"
},
gaugeLimits: [0, 3000, 7000, 10000]
}]
},
options: {
events: [],
showMarkers: true
}
});

这是我设置背景颜色的方法。
new Chart(ctx, {
type: "tsgauge",
data: {
datasets: [{
backgroundColor: ["#0fdc63", "#fd9704", "#ff7143"],
borderWidth: 0,
gaugeData: {
value: 50,
valueColor: "#ff7143"
},
gaugeLimits: [0, 20, 40, 60, 80, 100],
gaugeColors: [{
min: 0,
max: 30,
color: ""
}, {
min: 30,
max: 70,
color: ""
},{
min:70,
max:100,
color: ""
}]
}]
},
options: {
events: [],
showMarkers: true
}
});

目前 Chart.JS匹配颜色 0i有限制 0i .
我还想绘制另一个具有所需颜色的虚拟图表并将其设置在真实图表的顶部,但这样做似乎很狡猾。

最佳答案

以前的解决方案
您可以稍微更改数据集以实现此目的:

backgroundColor: ["green", "green", "green", "yellow", "yellow", "yellow", "yellow", "red", "red", "red"],
gaugeLimits: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
由于您的 gagueLimits被分成 20 的范围目前,因此您无法访问 30 的限制,
所以,我在这里所做的是详细说明 guageLimits10 的分割范围现在 30可以访问, 70 也可以访问,
现在关于颜色,您的每个 guageLimits需要 backgroundColor 中的颜色数组,我相应地设置它们,检查上面的数组。由于对应的颜色都不能为空,因此您可能需要使用相同的颜色,直到达到下一个颜色范围。
更新的解决方案
您的要求现已清除:
  • 您希望仪表标签不要太舒适,这就是为什么限制为 20。
  • 并且您想将颜色范围分为 30 点和 70 点。

  • 现在,从技术上讲,如果您想将颜色范围设置为特定点,您需要在 gaugeLimits 上设置该值。数组,所以你减少了 gaugeLimits数组现在变成了这样:
    gaugeLimits: [0, 20, 30, 40, 60, 70, 80, 100],
    好吧,不,您可以相应地设置颜色,因为您在数组中指定了点。因此, backgroundColor数组是:
    backgroundColor: ["#0fdc63", "#0fdc63", "#fd9704", "#fd9704", "#fd9704", "#ff7143", "#ff7143"]
    现在,最后一招
    您仍然需要从比例中隐藏 30 和 70,我尝试切换 showMarkers在您的代码中,看起来它要么完全启用或禁用可见数字比例,我试图提供一个字符串数组,但它只接受 boolean
    Chartjs-tsgauge没有提供太多关于可用选项的文档,所以我潜入代码并找到 markerFormatFn它的作用是将函数作为参数,您可以提供一个函数来告诉您如何处理每个标记项。
    所以,我想出了一个想法,提供一个函数来只显示可被 20 整除的数字而没有任何余数,否则返回空字符串,这里是:
    markerFormatFn: n => n % 20 === 0 ? n.toString() : '',
    检查片段:

    //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>

    关于javascript - donut (仪表)的自定义背景限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58856535/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com