您如何在条形图的顶部和底部创建圆角,而2部分之间仍然像图像一样绘制?

发布于 2025-01-24 06:43:55 字数 3295 浏览 2 评论 0原文

我目前正在尝试使用React-Chartjs-2将此图表栩栩如生。 设计: 在此处输入图像描述 在网上进行了数小时的搜索后,我只能为每个条的顶部和底部创建圆角。

这是我到目前为止的照片: 在此处输入映像

我将自定义的JS文件导入我的React组件,以使上面的图像在上方。

这是我使用的自定义JS:

Chart.elements.Rectangle.prototype.draw = function () {
var ctx = this._chart.ctx;
var vm = this._view;
var left, right, top, bottom, signX, signY, borderSkipped, radius;
var borderWidth = vm.borderWidth;
var cornerRadius = 20;

if (!vm.horizontal) {
    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 {
    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';
}

if (borderWidth) {
    var barSize = Math.min(Math.abs(left - right), Math.abs(top - bottom));
    borderWidth = borderWidth > barSize ? barSize : borderWidth;
    var halfStroke = borderWidth / 2;
    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);
    if (borderLeft !== borderRight) {
        top = borderTop;
        bottom = borderBottom;
    }
    if (borderTop !== borderBottom) {
        left = borderLeft;
        right = borderRight;
    }
}

ctx.beginPath();
ctx.fillStyle = vm.backgroundColor;
ctx.strokeStyle = vm.borderColor;
ctx.lineWidth = borderWidth;
var corners = [
    [left, bottom],
    [left, top],
    [right, top],
    [right, bottom]
];

var borders = ['bottom', 'left', 'top', 'right'];
var startCorner = borders.indexOf(borderSkipped, 0);
if (startCorner === -1) {
    startCorner = 0;
}

function cornerAt(index) {
    return corners[(startCorner + index) % 4];
}

var corner = cornerAt(0);
ctx.moveTo(corner[0], corner[1]);

for (var i = 1; i < 4; i++) {
    corner = cornerAt(i);
    nextCornerId = i + 1;
    if (nextCornerId == 4) {
        nextCornerId = 0
    }

    nextCorner = cornerAt(nextCornerId);

    width = corners[2][0] - corners[1][0];
    height = corners[0][1] - corners[1][1];
    x = corners[1][0];
    y = corners[1][1];

    var radius = cornerRadius;

    if (radius > height / 2) {
        radius = height / 2;
    } if (radius > width / 2) {
        radius = width / 2;
    }

    ctx.moveTo(x + radius, y);
    ctx.lineTo(x + width - radius, y);
    ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
    ctx.lineTo(x + width, y + height - radius);
    ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
    ctx.lineTo(x + radius, y + height);
    ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
    ctx.lineTo(x, y + radius);
    ctx.quadraticCurveTo(x, y, x + radius, y);
}

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

};

I am currently attempting to use react-chartjs-2 to bring this chart to life.
design:
enter image description here
After hours of searching online, I have only been able to create rounded corners for the top and bottom of each bar.

Here is a picture of what I have so far:
enter image description here

I am importing a custom JS file into my react component to make the image above.

Here is the custom JS I am using:

Chart.elements.Rectangle.prototype.draw = function () {
var ctx = this._chart.ctx;
var vm = this._view;
var left, right, top, bottom, signX, signY, borderSkipped, radius;
var borderWidth = vm.borderWidth;
var cornerRadius = 20;

if (!vm.horizontal) {
    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 {
    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';
}

if (borderWidth) {
    var barSize = Math.min(Math.abs(left - right), Math.abs(top - bottom));
    borderWidth = borderWidth > barSize ? barSize : borderWidth;
    var halfStroke = borderWidth / 2;
    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);
    if (borderLeft !== borderRight) {
        top = borderTop;
        bottom = borderBottom;
    }
    if (borderTop !== borderBottom) {
        left = borderLeft;
        right = borderRight;
    }
}

ctx.beginPath();
ctx.fillStyle = vm.backgroundColor;
ctx.strokeStyle = vm.borderColor;
ctx.lineWidth = borderWidth;
var corners = [
    [left, bottom],
    [left, top],
    [right, top],
    [right, bottom]
];

var borders = ['bottom', 'left', 'top', 'right'];
var startCorner = borders.indexOf(borderSkipped, 0);
if (startCorner === -1) {
    startCorner = 0;
}

function cornerAt(index) {
    return corners[(startCorner + index) % 4];
}

var corner = cornerAt(0);
ctx.moveTo(corner[0], corner[1]);

for (var i = 1; i < 4; i++) {
    corner = cornerAt(i);
    nextCornerId = i + 1;
    if (nextCornerId == 4) {
        nextCornerId = 0
    }

    nextCorner = cornerAt(nextCornerId);

    width = corners[2][0] - corners[1][0];
    height = corners[0][1] - corners[1][1];
    x = corners[1][0];
    y = corners[1][1];

    var radius = cornerRadius;

    if (radius > height / 2) {
        radius = height / 2;
    } if (radius > width / 2) {
        radius = width / 2;
    }

    ctx.moveTo(x + radius, y);
    ctx.lineTo(x + width - radius, y);
    ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
    ctx.lineTo(x + width, y + height - radius);
    ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
    ctx.lineTo(x + radius, y + height);
    ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
    ctx.lineTo(x, y + radius);
    ctx.quadraticCurveTo(x, y, x + radius, y);
}

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

};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

情未る 2025-01-31 06:43:55

您只需使用 /a>具有堆叠x轴的属性:

const options = {
  type: 'bar',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
        label: '# of Votes',
        data: [3, 5, 3, 5, 2, 3],
        backgroundColor: 'orange',
        borderSkipped: false,
        borderRadius: 20,
      },
      {
        label: '# of Points',
        data: [7, 11, 5, 8, 3, 7],
        backgroundColor: 'pink',
        borderSkipped: false,
        borderRadius: 20,
      }
    ]
  },
  options: {
    scales: {
      x: {
        stacked: true
      }
    }
  }
}

const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
  <canvas id="chartJSContainer" width="600" height="400"></canvas>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.js"></script>
</body>

You can just use the borderRadius property with a stacked x axes like so:

const options = {
  type: 'bar',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
        label: '# of Votes',
        data: [3, 5, 3, 5, 2, 3],
        backgroundColor: 'orange',
        borderSkipped: false,
        borderRadius: 20,
      },
      {
        label: '# of Points',
        data: [7, 11, 5, 8, 3, 7],
        backgroundColor: 'pink',
        borderSkipped: false,
        borderRadius: 20,
      }
    ]
  },
  options: {
    scales: {
      x: {
        stacked: true
      }
    }
  }
}

const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
  <canvas id="chartJSContainer" width="600" height="400"></canvas>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.js"></script>
</body>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文