【问题标题】:Chart js - Draw center of each bubbles of a bubble chartChart js - 绘制气泡图每个气泡的中心
【发布时间】:2017-05-29 15:16:52
【问题描述】:

我有一个带有大气泡的气泡图。我想在每个气泡的中心画一个十字或任何东西,但我找不到任何解决方案。下图显示了上下文:

我在流星上使用 Chart.js 2.5.0。

【问题讨论】:

    标签: javascript meteor charts chart.js


    【解决方案1】:

    您的问题对我来说似乎很有趣,因此,我构建了以下 chartjs 插件,这将有助于满足您的要求。

    Chart.plugins.register({
       afterDraw: c => {
          let datasets = c.data.datasets;
          datasets.forEach((e, i) => {
             let isHidden = e._meta[0].hidden;
             if (!isHidden) {
                let data = c.getDatasetMeta(i).data;
                data.forEach(e => {
                   let ctx = c.chart.ctx;
                   let x = e._model.x;
                   let y = e._model.y;
                   let r = e._model.radius;
    
                   // draw a cross
                   // or you can draw anything using general canvas methods
                   ctx.save();
                   ctx.beginPath();
                   ctx.moveTo(x - r / 4, y - r / 4);
                   ctx.lineTo(x + r / 4, y + r / 4);
                   ctx.moveTo(x + r / 4, y - r / 4);
                   ctx.lineTo(x - r / 4, y + r / 4);
                   ctx.strokeStyle = 'white';
                   ctx.lineWidth = 2;
                   ctx.stroke();
                   ctx.restore();
                });
             }
          });
       }
    });
    

    ᴅᴇᴍᴏ

    Chart.plugins.register({
       afterDraw: c => {
          let datasets = c.data.datasets;
          datasets.forEach((e, i) => {
             let isHidden = e._meta[0].hidden;
             if (!isHidden) {
                let data = c.getDatasetMeta(i).data;
                data.forEach(e => {
                   let ctx = c.chart.ctx;
                   let x = e._model.x;
                   let y = e._model.y;
                   let r = e._model.radius;
                   
                   // draw a cross
                   // or you can draw anything using general canvas methods
                   ctx.save();
                   ctx.beginPath();
                   ctx.moveTo(x - r / 4, y - r / 4);
                   ctx.lineTo(x + r / 4, y + r / 4);
                   ctx.moveTo(x + r / 4, y - r / 4);
                   ctx.lineTo(x - r / 4, y + r / 4);
                   ctx.strokeStyle = 'white';
                   ctx.lineWidth = 2;
                   ctx.stroke();
                   ctx.restore();
                });
             }
          });
       }
    });
    
    let ctx = document.querySelector('#c').getContext('2d');
    let chart = new Chart(ctx, {
       type: 'bubble',
       data: {
          labels: ['Jan', 'Feb', 'Mar'],
          datasets: [{
             label: 'John',
             data: [
                { x: 5, y: 5, r: 10 },
                { x: 10, y: 10, r: 15 },
                { x: 16, y: 15, r: 18 }
             ],
             backgroundColor: '#76d1bf'
          }, {
             label: 'Smith',
             data: [
                { x: 3, y: 10, r: 10 },
                { x: 7, y: 11, r: 15 },
                { x: 12, y: 6, r: 18 }
             ],
             backgroundColor: '#827ada'
          }]
       },
       options: {
          responsive: false,
          scales: {
             xAxes: [{
                ticks: {
                   min: 2,
                   max: 18,
                   stepSize: 4
                }
          	 }],
             yAxes: [{
                ticks: {
                   min: 0,
                   max: 20,
                   stepSize: 4
                }
          	 }]
          }
       }
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
    <canvas id="c" height="200"></canvas>

    【讨论】:

    • 嘿,差不多五年后!你碰巧让它与 Chart JS V3 一起工作吗?我正在使用 V.3.7.0,您的解决方案无法运行。它不喜欢“Chart.plugins.register”。谢谢
    【解决方案2】:

    Chart.js 一直是一个非常简单明了的库。它的优点之一是易于定制。这也是 JavaScript 的优点之一,源代码始终可用于您使用的任何库。

    定制化是有退路的。对库进行更改后,您将不得不使用该特定版本,因为定制不是作者在进行更改时会考虑的事情。

    因此,要使用下面的代码,您应该转到 github page 并下载项目并为您的站点使用该版本的 chart.js。我不会更改原始的,大多数时候每个自定义都是针对特定情况的,并且代码是在客户端自定义的。

    改变很简单。先备份画点的函数

    Chart.canvasHelpers.defaultDrawPoint = Chart.canvasHelpers.drawPoint;
    

    这样做是为了您可以将所有您不感兴趣的调用传递回标准处理程序。

    接下来通过替换刚刚备份的函数来编写拦截代码。

    Chart.canvasHelpers.drawPoint = function(ctx, pointStyle, radius, x, y){
    

    查看原始源代码,您可以了解它是如何绘制圆圈的,并且只是捕获将所有其他参数变体传递给原始源代码的行为。

    如果 pointStyle 未定义或 === "circle" 你自己处理

        // pointStyle undefined is default 
        // pointStyle === "circle" is the default named style
        if(pointStyle === undefined || pointStyle === "circle"){
    
            // next 4 lines copied from the source
            ctx.beginPath();
            ctx.arc(x, y, radius, 0, Math.PI * 2);
            ctx.closePath();
            ctx.fill();   
    

    然后您添加自定义代码以呈现您喜欢的任何内容。保存当前的 2D 上下文很重要,因为您不必担心会进一步破坏某些内容。

            // draw a cross
    
            ctx.save();  // save the state
            ctx.strokeStyle = "white";
            ctx.strokeWidth = 4;
            ctx.beginPath();
            ctx.moveTo(x - radius *0.3, y - radius *0.3);
            ctx.lineTo(x + radius *0.3, y + radius *0.3);
            ctx.moveTo(x + radius *0.3, y - radius *0.3);
            ctx.lineTo(x - radius *0.3, y + radius *0.3);
            ctx.stroke();
    

    然后恢复2D上下文的状态

            ctx.restore(); // restore the state
    

    else 处理你不感兴趣的标准调用

        }else{  // all other styles pass on to default handler
            Chart.canvasHelpers.defaultDrawPoint(ctx, pointStyle, radius, x, y);
        }
    

    对于 Chart.js,这特别有用,因为它还提供了一种自定义和获取动画的方法。

    Chart.canvasHelpers.defaultDrawPoint = Chart.canvasHelpers.drawPoint;
    Chart.canvasHelpers.drawPoint = function(ctx, pointStyle, radius, x, y){
        // PointStyle undefined is default 
        // PointStyle === "circle" is the default named style
        if(pointStyle === undefined || pointStyle === "circle"){
        
            ctx.beginPath();
            ctx.arc(x, y, radius, 0, Math.PI * 2);
            ctx.closePath();
            ctx.fill();   
            
            // custom code here
            ctx.save();  // save the state
            ctx.strokeStyle = "white";
            ctx.strokeWidth = 4;
            ctx.beginPath();
            ctx.moveTo(x - radius *0.3, y - radius *0.3);
            ctx.lineTo(x + radius *0.3, y + radius *0.3);
            ctx.moveTo(x + radius *0.3, y - radius *0.3);
            ctx.lineTo(x - radius *0.3, y + radius *0.3);
            ctx.stroke();
            ctx.restore(); // restor the state
            
        }else{  // all other styles pass on to default handler
            Chart.canvasHelpers.defaultDrawPoint(ctx, pointStyle, radius, x, y);
        }
    }
    
    // some utils to add data
    // returns a random int
    const rand = (min, max = min + (min = 0))=> Math.floor( Math.random() * (max-min) + min);    
    // returns a random data point {x,y,r}
    const randData = ()=>({x : rand(0,50), y: rand(5,50), r: rand(4,20)});
    // create a chart.
    const ctx = canvas.getContext("2d");
    const chart = new Chart(ctx, {
       type: "bubble",
       data: {
          datasets: [{
             label: "Random Data",
             backgroundColor: "#7AF",
             data: (()=>{
                var dat = [];
                for(var i = 0; i < 10; i++){ dat.push(randData()) }
                return dat;
             })(),
          }]
       },
       options: { responsive: false } // this is required to work or it throws
                                      // not sure why by it is not due to the
                                      // changes
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
    <canvas id=canvas height=200 width=400></canvas>

    要回滚更改,只需将函数设置回原来的值。

    Chart.canvasHelpers.drawPoint = Chart.canvasHelpers.defualtDrawPoint;
    

    并删除多余的引用

    Chart.canvasHelpers.defualtDrawPoint = undefined;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-12
      相关资源
      最近更新 更多