HTML / JS Canvas Donut Chart Как создать круглые штрихи с овлерапом? - PullRequest
1 голос
/ 23 марта 2020

У меня проблема с тем, что моя кольцевая диаграмма не работает так, как я хочу. Я хочу создать Кольцевую Диаграмму, подобную этой:

Example Donut Chart

Но моя Кольцевая Диаграмма выглядит сейчас так:

enter image description here

Как видите, штрихи не перекрываются в правильном направлении. Я думаю, что это может быть, потому что я начинаю рисовать штрихи справа налево. Вместо этого следует рисовать их слева направо, чтобы был виден левый «закругленный конец», а не правый закругленный конец.

Это то, что я пробовал до сих пор:

//function to draw the donut chart, ctx = context, cx - cy = position, radius and arcwith
dmbChart(ctx, cx, cy, radius, arcwidth) {
   var tot = 0;
   var accum = 0;
   var PI = Math.PI;
   var PI2 = PI * 2;
   var offset = -PI/2;

   for(var i = 0; i < this.canvasValues.length; i++) {
     tot += this.canvasValues[i];
   }  

   //Donut Sectors Color: Draw each stroke based on the value (canvasValues) and Color (canvasColors)
   for(var i = 0; i < this.canvasValues.length; i++) {
    ctx.lineWidth = arcwidth;
    ctx.beginPath();
    ctx.lineCap = "round";
    ctx.arc(cx, cy, radius, offset + PI2 * (accum/tot), offset + PI2 * ((accum + this.canvasValues[i]) / tot));
    ctx.strokeStyle = this.canvasColors[i];
    ctx.stroke(); 

    accum += this.canvasValues[i];
   }
 }

Как вы можете видеть, я получаю значения, представляющие собой проценты, как долго должен быть каждый штрих и цвет. Начиная сверху я рисую каждый сверху -> справа -> снизу -> слева, и это результат. Но как я могу изменить его, чтобы получить результат сверху?

Редактировать: С помощью @Helder Sepulveda я создал его вот так сейчас. Я изменил многие расчеты, исправил некоторые ошибки, которые пришли с изменениями. Единственная проблема сейчас в том, что она не начинает рисовать сверху. Как видите, зеленый штрих должен начинаться сверху:

function dmbChart(ctx, cx, cy, radius, arcwidth) { 
  var canvasValues =  [30, 5, 15, 10, 10, 10, 10, 10];
  var canvasColors = ["#10dc60", "#DDDDDD", "#0cd1e8", "#ffce00", "#7044ff", "#f04141", "#ffea00", "#ee82ee"];
  ctx.lineWidth = arcwidth;
  ctx.lineCap = "round";
 
  
  var accum = canvasValues.reduce((a,b) => a + b, 0);  

  for (var i = canvasValues.length-1; i >= 0; i--) {
  	var radians = canvasValues[i] / 100 * 360 * Math.PI / 180

    ctx.beginPath();
    ctx.arc(cx, cy, radius, accum, accum - radians, true);
    ctx.strokeStyle = canvasColors[i];
    ctx.stroke();    
    accum -= radians;
  }
  
  ctx.beginPath();
  ctx.arc(cx, cy, radius, accum, accum - (0.1 / 100 * 360 * Math.PI / 180), true);  
  ctx.strokeStyle = canvasColors[canvasColors.length - 1];
  ctx.stroke();
}

const canvas = document.getElementById("c");
canvas.width = canvas.height = 140;
const ctx = canvas.getContext("2d");

dmbChart(ctx, 70, 70, 50, 30)
<canvas id="c"></canvas>

1 Ответ

1 голос
/ 23 марта 2020

Я делаю некоторые предположения на canvasValues и canvasColors, чтобы показать, что что-то работает:

function dmbChart(ctx, cx, cy, radius, arcwidth) {
  var accum = 0;
  var PI = Math.PI;
  var PI2 = PI * 2;
  var offset = -PI / 2;
  var canvasValues = [10, 10, 10]
  var canvasColors = ["red", "green", "blue"]
  var tot = canvasValues.reduce((a, b) => a + b, 0)

  ctx.lineWidth = arcwidth;
  ctx.lineCap = "round";

  for (var i = 0; i < canvasValues.length; i++) {
    ctx.beginPath();
    ctx.arc(cx, cy, radius, offset + PI2 * (accum / tot), offset + PI2 * ((accum + canvasValues[i]) / tot));
    ctx.strokeStyle = canvasColors[i];
    ctx.stroke();
    accum += canvasValues[i];
  }

  ctx.beginPath();
  ctx.arc(cx, cy, radius, offset, offset);
  ctx.strokeStyle = canvasColors[0];
  ctx.stroke();
}

const canvas = document.getElementById("c");
canvas.width = canvas.height = 140;
const ctx = canvas.getContext("2d");

dmbChart(ctx, 70, 70, 50, 30)
<canvas id="c"></canvas>

Идея состоит в том, чтобы нарисовать один последний «короткий» ar c с первым значением (и цветом) в конце l oop

Я также переместил пару строк из l oop:

  ctx.lineWidth = arcwidth;
  ctx.lineCap = "round";

, которые можно установить только один раз перед l oop


И вот что мы говорили в комментариях, инвертирующих направление

function dmbChart(ctx, cx, cy, radius, arcwidth) {
  var PI = Math.PI;
  var PI2 = PI * 2;
  var offset = -PI / 2;
  var canvasValues = [10, 10, 10]
  var canvasColors = ["red", "green", "blue"]
  var tot = canvasValues.reduce((a,b) => a + b, 0)
  var accum = tot;
  
  ctx.lineWidth = arcwidth;
  ctx.lineCap = "round";

  for (var i = canvasValues.length-1; i >= 0; i--) {
    ctx.beginPath();
    ctx.arc(cx, cy, radius, offset + PI2 * (accum / tot), offset + PI2 * ((accum + canvasValues[i]) / tot));
    ctx.strokeStyle = canvasColors[i];
    ctx.stroke();    
    accum -= canvasValues[i];    
  }

  ctx.beginPath();
  p = offset + PI2 * ((tot + canvasValues[canvasValues.length-1]) / tot)
  ctx.arc(cx, cy, radius, p, p);  
  ctx.strokeStyle = canvasColors[canvasColors.length-1];
  ctx.stroke();
}

const canvas = document.getElementById("c");
canvas.width = canvas.height = 140;
const ctx = canvas.getContext("2d");

dmbChart(ctx, 70, 70, 50, 30)
<canvas id="c"></canvas>
...