自定义Chart.js

时间:2018-11-12 18:48:22

标签: javascript charts chart.js

因此,我一直在尝试了解Chart.js的文档,但对于新人来说,了解如何自定义某些内容实际上并不友好。

我已经安装了该插件,但由于要使用它无法自定义,因此我尝试使用<div class="backdrop" ref={this.divRef}> <div class="highlights"> <mark>This</mark> demo shows how to highlight bits of text within a <mark>textarea</mark>. Alright, that's a lie. You can't actually render markup inside a textarea. However, you can fake it by carefully positioning a div behind the textarea and adding your highlight markup there. JavaScript takes care of syncing the content and scroll position from the textarea to the div, so everything lines up nicely. Hit the toggle button to peek behind the curtain. And feel free to edit this text. All capitalized words will be highlighted. </div> ,但由于它是画布,因此您实际上无法做很多事情。

我正在尝试实现这种设计,并从mysql数据库中添加数据并将其显示在图表上,除了设计图表外,我还能理解如何做其余的事情。

我要实现的目标。

Chart example

2 个答案:

答案 0 :(得分:2)

我认为,使用chart.js和圆角边框可以获得的最接近的答案是:https://stackoverflow.com/a/43281198/10387396

但是对于负值,效果不佳。

Chart.helpers.drawRoundedTopRectangle = function(ctx, x, y, width, height, radius) {
  ctx.beginPath();
  ctx.moveTo(x + radius, y);
  // top right corner
  ctx.lineTo(x + width - radius, y);
  ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
  // bottom right   corner
  ctx.lineTo(x + width, y + height);
  // bottom left corner
  ctx.lineTo(x, y + height);
  // top left   
  ctx.lineTo(x, y + radius);
  ctx.quadraticCurveTo(x, y, x + radius, y);
  ctx.closePath();
};

Chart.elements.RoundedTopRectangle = Chart.elements.Rectangle.extend({
  draw: function() {
    var ctx = this._chart.ctx;
    var vm = this._view;
    var left, right, top, bottom, signX, signY, borderSkipped;
    var borderWidth = vm.borderWidth;

    if (!vm.horizontal) {
      // bar
      left = vm.x - vm.width / 2;
      right = vm.x + vm.width / 2;
      top = vm.y;
      bottom = vm.base;
      signX = 1;
      signY = bottom > top? 1: -1;
      borderSkipped = vm.borderSkipped || 'bottom';
    } else {
      // horizontal bar
      left = vm.base;
      right = vm.x;
      top = vm.y - vm.height / 2;
      bottom = vm.y + vm.height / 2;
      signX = right > left? 1: -1;
      signY = 1;
      borderSkipped = vm.borderSkipped || 'left';
    }

    // Canvas doesn't allow us to stroke inside the width so we can
    // adjust the sizes to fit if we're setting a stroke on the line
    if (borderWidth) {
      // borderWidth shold be less than bar width and bar height.
      var barSize = Math.min(Math.abs(left - right), Math.abs(top - bottom));
      borderWidth = borderWidth > barSize? barSize: borderWidth;
      var halfStroke = borderWidth / 2;
      // Adjust borderWidth when bar top position is near vm.base(zero).
      var borderLeft = left + (borderSkipped !== 'left'? halfStroke * signX: 0);
      var borderRight = right + (borderSkipped !== 'right'? -halfStroke * signX: 0);
      var borderTop = top + (borderSkipped !== 'top'? halfStroke * signY: 0);
      var borderBottom = bottom + (borderSkipped !== 'bottom'? -halfStroke * signY: 0);
      // not become a vertical line?
      if (borderLeft !== borderRight) {
        top = borderTop;
        bottom = borderBottom;
      }
      // not become a horizontal line?
      if (borderTop !== borderBottom) {
        left = borderLeft;
        right = borderRight;
      }
    }

    // calculate the bar width and roundess
    var barWidth = Math.abs(left - right);
    var roundness = this._chart.config.options.barRoundness || 0.5;
    var radius = barWidth * roundness * 0.5;

    // keep track of the original top of the bar
    var prevTop = top;

    // move the top down so there is room to draw the rounded top
    top = prevTop + radius;
    var barRadius = top - prevTop;

    ctx.beginPath();
    ctx.fillStyle = vm.backgroundColor;
    ctx.strokeStyle = vm.borderColor;
    ctx.lineWidth = borderWidth;

    // draw the rounded top rectangle
    Chart.helpers.drawRoundedTopRectangle(ctx, left, (top - barRadius + 1), barWidth, bottom - prevTop, barRadius);

    ctx.fill();
    if (borderWidth) {
      ctx.stroke();
    }

    // restore the original top value so tooltips and scales still work
    top = prevTop;
  },
});

Chart.defaults.roundedBar = Chart.helpers.clone(Chart.defaults.bar);

Chart.controllers.roundedBar = Chart.controllers.bar.extend({
  dataElementType: Chart.elements.RoundedTopRectangle
});

//*********//
const d1=  [65, 59, 80, 81,-40, 56, 55, 40 ];
const setColor = data => data < 0 ? '#ff4433': '#3377ee';

var data = {
    labels: ["January", "February", "March", "April", "May", "June", "July", "August"],
    datasets: [
        {
            label: "My First dataset",
            backgroundColor: d1.map(setColor),
            borderColor: d1.map(setColor),
            data: d1
        },
    ],
};

var options = {
    scaleBeginAtZero: false,
    responsive: true,
    barRoundness: 1,
    scales: {
      yAxes: [{
        ticks: {
          suggestedMin: -70,
          suggestedMax: 100
        }
      }]
    }
};

const ctx = "myChart";
const chart = new Chart(ctx, { type: 'roundedBar', data, options });
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script>
<canvas id="myChart" width="250" height="100"></canvas>

使用Echarts可以更轻松地做到这一点。

const chart = echarts.init(document.getElementById('main'));
const d1 =  [65, 59, 80, 81,-40, 56, 55, 40 ];

// specify chart configuration item and data
const option = {

  tooltip: {},
  legend: {
    data:['Sales']
  },
  xAxis: {
    data: ["January", "February", "March", "April", "May", "June", "July", "August"]
  },
  yAxis: {},
  series: [{
    name: 'Sales',
    type: 'bar',
    barWidth: 20,
    data: d1.map(item => {
      return {
        value: item,
        itemStyle: {
          color: item > 0 ? '#2196F3' : '#F44336',
          barBorderRadius: item > 0 ? [100, 100, 0 ,0] 
                                    : [0 ,0 ,100, 100]
        }
      }
    }),
  }]
};

// use configuration item and data specified to show chart
chart.setOption(option);
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/4.1.0/echarts.min.js"></script>
<div id="main" style="width: 100vw;height:400px;"></div>

如果您不关心圆角边框,而​​只是设置负值样式,则可以映射数据以根据其值创建颜色数组:

const chartData = [65, 59, 80, 81,-40, 56, 55, 40 ];
const data = {
  labels: ["January", "February", "March", "April", "May", "June", "July", "August"],
  datasets: [
    {
        label: "My First dataset",
        backgroundColor: chartData.map(setColor),
        borderColor: chartData.map(setColor),
        data: chartData
    },
  ],
};
// If data < 0 return a red color.
const setColor = data => data < 0 ? '#ff4433': '#3377ee';

结果:

const d1=  [65, 59, 80, 81,-40, 56, 55, 40 ];
const setColor = data => data < 0 ? '#ff4433': '#3377ee';

var data = {
    labels: ["January", "February", "March", "April", "May", "June", "July", "August"],
    datasets: [
        {
            label: "My First dataset",
            backgroundColor: d1.map(setColor),
            borderColor: d1.map(setColor),
            data: d1
        },
    ],
};

var options = {
    scaleBeginAtZero: false,
    responsive: true,
    scales: {
      yAxes: [{
        ticks: {
          suggestedMin: -60,
          suggestedMax: 100
        }
      }]
    }
};

const ctx = "myChart";
const chart = new Chart(ctx, { type: 'bar', data, options });
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script>
<canvas id="myChart" width="250" height="100"></canvas>

答案 1 :(得分:0)

对于圆形边框,您可以使用lib的新版本3,它本机支持。

对于红色条,如果它们为负数,则可以传递具有所有颜色的数组作为背景色,对于数据为负的每个索引,将其更改为红色。应该可以工作

圆角示例:https://www.chartjs.org/samples/master/charts/bar/border-radius.html