在带圆角的圆环图中转义重叠

问题描述 投票:0回答:1

我创建了一个圆环图。

我试过做一个圆角的圆弧,但是由于我的数学不好没能成功。所以我在每个圆弧的 startAngle 和 endAngle 上添加了圆圈。添加了 lineWidth 来模拟间距。

问题是重叠——每个角末端的圆与下一个弧重叠。 如何避免与此设计剩余的重叠?

代码如下:

"use strict";

const canvas = document.getElementById("myCanvas");
canvas.width = 400;
canvas.height = 400;

const ctx = canvas.getContext("2d");
const PI = Math.PI;
const TAU = PI * 2;

function drawSlice(
  ctx,
  x,
  y,
  radius,
  startAngle,
  endAngle,
  fillColor,
  strokeColor,
  cutout,
  lineWidth
) {
  ctx.fillStyle = fillColor;
  ctx.strokeStyle = strokeColor;

  ctx.save();
  ctx.translate(x, y);
  ctx.beginPath();
  ctx.arc(
    ((radius + (radius * cutout) / 100) / 2) * Math.cos(endAngle),
    ((radius + (radius * cutout) / 100) / 2) * Math.sin(endAngle),
    (radius - (radius * cutout) / 100) / 2 + lineWidth / 2,
    0,
    TAU
  );

  ctx.closePath();
  ctx.fill();
  ctx.lineWidth = lineWidth;
  ctx.stroke();
  ctx.beginPath();
  ctx.arc(
    ((radius + (radius * cutout) / 100) / 2) * Math.cos(startAngle),
    ((radius + (radius * cutout) / 100) / 2) * Math.sin(startAngle),
    (radius - (radius * cutout) / 100) / 2 + lineWidth / 2,
    TAU,
    0
  );
  ctx.fill();
  ctx.stroke();
  ctx.restore();

  ctx.save();
  ctx.beginPath();
  ctx.arc(x, y, radius, startAngle, endAngle);
  ctx.arc(x, y, (radius * cutout) / 100, endAngle, startAngle, true);
  ctx.closePath();
  ctx.fill();
  ctx.stroke(); // enables to see overlap
  ctx.restore();
}

class Doughnut {
  constructor(options) {
    this.options = options;
    this.canvas = options.canvas;
    this.ctx = ctx;
    this.x = this.canvas.width / 2;
    this.y = this.canvas.height / 2;
    this.colors = options.colors;
    this.totalValue = [...Object.values(this.options.data)].reduce(
      (a, b) => a + b,
      0
    );
    this.radius = Math.min(this.x, this.y) - options.padding;
  }

  draw() {
    let colorIndex = 0;
    let startAngle = -PI / 2;

    for (const i in this.options.data) {
      const value = this.options.data[i];
      const sliceAngle = (TAU * value) / this.totalValue;
      const endAngle = startAngle + sliceAngle - this.options.spacing / 100;

      drawSlice(
        this.ctx,
        this.x,
        this.y,
        this.radius,
        startAngle,
        endAngle,
        this.colors[colorIndex % this.colors.length],
        "#FFF",
        70,
        10
      );

      startAngle += sliceAngle;
      colorIndex++;
    }
  }
}

let CustomDoughnut = new Doughnut({
  canvas,
  padding: 20,
  spacing: 0,
  data: {
    TV: 5,
    Desktop: 5,
    Phone: 5,
    Laptop: 5,
  },
  colors: ["#80DEEE", "#FFE0E2", "#FFABE1", "#CE93DE"],
});

CustomDoughnut.draw();
<canvas id="myCanvas"></canvas>

javascript html5-canvas
1个回答
0
投票

简单的东西怎么样,比如用笔画画...
请参阅下面的示例代码:

const canvas = document.getElementById("myCanvas");
canvas.width = 200;
canvas.height = 200;

const ctx = canvas.getContext("2d");
ctx.lineCap = "round"
const PI = Math.PI;
const TAU = PI * 2;

function drawSlice(x, y, radius, startAngle, endAngle, color, lineWidth) {
  ctx.beginPath();
  ctx.strokeStyle = color;
  ctx.lineWidth = lineWidth
  ctx.arc(x, y, 80, startAngle, endAngle);
  ctx.stroke();
}

class Doughnut {
  constructor(options) {
    this.options = options;
    this.x = canvas.width / 2;
    this.y = canvas.height / 2;
    this.colors = options.colors;
    this.totalValue = [...Object.values(this.options.data)].reduce( (a, b) => a + b, 0);
    this.radius = Math.min(this.x, this.y) - options.padding;
  }

  draw() {
    let colorIndex = 0;
    let startAngle = -PI / 2;

    for (const i in this.options.data) {
      const value = this.options.data[i];
      const sliceAngle = (TAU * value) / this.totalValue;
      const endAngle = startAngle + sliceAngle - this.options.spacing / 100;

      drawSlice(this.x,this.y, this.radius, startAngle, endAngle, this.colors[colorIndex % this.colors.length],40);

      startAngle += sliceAngle;
      colorIndex++;
    }
    drawSlice(this.x, this.y, this.radius, -PI / 2, -PI / 2+0.01, this.colors[0], 40);
  }
}

let CustomDoughnut = new Doughnut({
  padding: 20,
  spacing: 0,
  data: {
    TV: 5,
    Desktop: 5,
    Phone: 3,
    Laptop: 7,
  },
  colors: ["red", "blue", "cyan", "pink"],
});

CustomDoughnut.draw();
<canvas id="myCanvas"></canvas>

你可以看到我已经重构了你的

function drawSlice
不再保存,恢复或翻译,我们只调用一次圆弧,我确实将半径硬编码为80你可以稍后更改。

© www.soinside.com 2019 - 2024. All rights reserved.