首页 > 解决方案 > 在 html 画布图表上绘制负面和正面区域

问题描述

我正在基于 HTML 画布创建一个单独的图表。我想用其他颜色绘制负值和正值,但到目前为止无法实现。

这是我的实际图表:

在此处输入图像描述

这是我想要实现的目标:

在此处输入图像描述

我可以想到两种解决方案。要么我可以用只下降到零的渐变来绘制它。

或者每个正面和每个负面分别绘制。但是我仍然需要十字路口。

这是我的原始值:

[
  { "x": 0, "y": 750 },
  { "x": 1, "y": -200 },
  { "x": 2, "y": 60 },
  { "x": 3, "y": 60 },
  { "x": 4, "y": 120 },
  { "x": 5, "y": 505 }
]

这是我转换后的像素值:

[
  { "x": 0, "y": 236}, // to draw the area
  { "x": 0, "y": 0},
  { "x": 173, "y": 300}, 
  { "x": 346, "y": 217}, 
  { "x": 519, "y": 217}, 
  { "x": 692, "y": 198}, 
  { "x": 865, "y": 77}, 
  { "x": 865, "y": 236} // to draw the area
]

你知道如何实现目标吗?谢谢!

标签: javascripthtmlcanvaschartsarea

解决方案


我在使用画布制作基本图表渲染器时获得了一些乐趣。我希望您发现以下代码很有用。(如果有不清楚的地方,请随时询问)

const c = document.getElementById("mycanvas");
const cc = c.getContext("2d");

const points = [
  750, -200, 60, 60, 120, 505
];

const maxY = Math.max(...points);
const minY = Math.min(...points);

//used to scale and fit the graph into the canvas
const xaxis = (maxY / (maxY - minY)) * c.height;
const yscale = -c.height / (maxY - minY);
const xscale = c.width / (points.length - 1);

const poscolor = "cornflowerblue";
const negcolor = "crimson";
cc.fillStyle = points[0] >= 0 ? poscolor : negcolor;

//start at (0, 0) and line to first point
cc.beginPath();
cc.moveTo(0, xaxis);
cc.lineTo(0, points[0] * yscale + xaxis);
for (let i = 1; i < points.length; i++) {
  const a = {
    x: i - 1,
    y: points[i - 1]
  };
  const b = {
    x: i,
    y: points[i]
  };
  //if a.y and b.y have different sign, the line will intersect the x-axis
  if (a.y * b.y < 0) {
    //calculate intersection (point on x-axis)
    const intersection = -a.y / (b.y - a.y);
    const intersectionPoint = (a.x + intersection) * xscale;
    //complete the current shape
    cc.lineTo(intersectionPoint, xaxis);
    cc.fill();
    //start a new shape for the other side of the x-axis
    cc.fillStyle = b.y >= 0 ? poscolor : negcolor;
    cc.beginPath();
    cc.moveTo(intersectionPoint, xaxis);
  }
  //continue the shape to point b
  cc.lineTo(b.x * xscale, b.y * yscale + xaxis);
}
//draw a line back to the x-axis and finish the shape
cc.lineTo((points.length - 1) * xscale, xaxis);
cc.fill();
canvas {
  background-color: ivory;
  border: 2px solid darkgray;
}
<!DOCTYPE html>
<html>

<body>
  <canvas id="mycanvas" width=500 height=200></canvas>
</body>

</html>


推荐阅读