简体   繁体   中英

Adding responsive text inside chart in Charts Js

I am new to writing JS/jquery and looking to build a doughnut charts.js chart with two lines of text: a larger size percentage on top and a smaller text only 'category' on the bottom as in the image below.

Sample Chart

I have had limited success with the code below taken from a fiddle link found on another similar stackoverflow post https://jsfiddle.net/cmyker/ooxdL2vj/

Struggling to understand how to have two lines of responsive text. Ex. getting the "prepaid" to scale without affecting the size of the percentage text above. Any help is greatly appreciated.

HTML: <canvas id="myChart"> </canvas>

Code:

Chart.pluginService.register({
        beforeDraw: function (chart) {
            if (chart.config.options.elements.center) {
        //Get ctx from string
        var ctx = chart.chart.ctx;

                //Get options from the center object in options
        var centerConfig = chart.config.options.elements.center;
        var fontStyle = centerConfig.fontStyle || 'Arial';
                var txt = centerConfig.text;
                var txtB = centerConfig.textB;
        var color = centerConfig.color || '#000';
        var sidePadding = centerConfig.sidePadding || 20;
        var sidePaddingCalculated = (sidePadding/100) * (chart.innerRadius * 2)

        //Start with a base font of 30px
        ctx.font = "30px " + fontStyle;

                //Get the width of the string and also the width of the element minus 10 to give it 5px side padding
        var stringWidth = ctx.measureText(txt).width;
        var elementWidth = (chart.innerRadius * 2) - sidePaddingCalculated;

        // Find out how much the font can grow in width.
        var widthRatio = elementWidth / stringWidth;
        var newFontSize = Math.floor(30 * widthRatio);
        var elementHeight = (chart.innerRadius * 2);

        // Pick a new font size so it will not be larger than the height of label.
        var fontSizeToUse = Math.min(newFontSize, elementHeight);

                //Set font settings to draw it correctly.
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        var centerX = ((chart.chartArea.left + chart.chartArea.right) / 2);
        var centerY = ((chart.chartArea.top + chart.chartArea.bottom) / 2);
        ctx.font = fontSizeToUse+"px " + fontStyle;
        ctx.fillStyle = color;


        //Draw text in center
        ctx.fillText(txt, centerX, centerY);            
            }
        }
    });

        var config = {
            type: 'doughnut',
            data: {
                labels: [
                  "Red",
                  "Green",
                  "Yellow"
                ],
                datasets: [{
                    data: [300, 50, 100],
                    backgroundColor: [
                      "#FF6384",
                      "#36A2EB",
                      "#FFCE56"
                    ],
                    hoverBackgroundColor: [
                      "#FF6384",
                      "#36A2EB",
                      "#FFCE56"
                    ]
                }]
            },
        options: {
            legend: {
            display: false},
            cutoutPercentage: 70,
            aspectRatio: 1.5,
            elements: {
                center: {
                    text: '80%' ,
          color: 'black', // Default is #000000
          fontStyle: 'Arial', // Default is Arial
          sidePadding: 20 // Defualt is 20 (as a percentage)
                }
            }
        }
    };

        var ctx = document.getElementById("myChart").getContext("2d");
        var myChart = new Chart(ctx, config);

If I use your sample chart as a template, this can be done with the following code.

 Chart.pluginService.register({ beforeDraw: (chart) => { let ctx = chart.chart.ctx; ctx.save(); let fontSize = (chart.chart.height / 75).toFixed(2); ctx.font = fontSize + "em sans-serif"; ctx.textBaseline = "middle"; let text = chart.data.datasets[0].data[0] + '%'; let textX = Math.round((chart.chart.width - ctx.measureText(text).width) / 2); let textY = chart.chart.height / 2.25; ctx.fillText(text, textX, textY); fontSize = (chart.chart.height / 124).toFixed(2); ctx.font = fontSize + "em sans-serif"; ctx.textBaseline = "middle"; text = chart.data.labels[0]; textX = Math.round((chart.chart.width - ctx.measureText(text).width) / 2); textY = chart.chart.height / 1.6; ctx.fillText(text, textX, textY); ctx.restore(); } }); var config = { type: 'doughnut', data: { labels: ["Prepaid", "Others"], datasets: [{ data: [90.8, 9.2], backgroundColor: ["yellow", "white" ] }] }, options: { legend: { display: false }, tooltips: { enabled: false }, cutoutPercentage: 80, aspectRatio: 5, rotation: 70 } }; var ctx = document.getElementById("myChart").getContext("2d"); var myChart = new Chart(ctx, config);
 <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script> <canvas id="myChart"> </canvas>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM