在 html canvas 图表上绘制负值和正值区域
draw on html canvas chart negative and positive areas
我正在根据 HTML canvas 创建个人图表。我想用其他颜色绘制负值和正值,但目前无法实现。
这是我的实际图表:
这是我想要实现的目标:
我可以想到两个解决方案。要么我可以用只下降到零的渐变来绘制它。
或者每个正面和每个负面分别绘制。但是我仍然需要交叉点。
这是我的原始值:
[
{ "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
]
您知道如何实现目标吗?谢谢!
我在使用 canvas 制作基本图表渲染器时获得了一些乐趣。我希望您发现以下代码有用。 (如果有什么不清楚的,请不要犹豫)
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>
我正在根据 HTML canvas 创建个人图表。我想用其他颜色绘制负值和正值,但目前无法实现。
这是我的实际图表:
这是我想要实现的目标:
我可以想到两个解决方案。要么我可以用只下降到零的渐变来绘制它。
或者每个正面和每个负面分别绘制。但是我仍然需要交叉点。
这是我的原始值:
[
{ "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
]
您知道如何实现目标吗?谢谢!
我在使用 canvas 制作基本图表渲染器时获得了一些乐趣。我希望您发现以下代码有用。 (如果有什么不清楚的,请不要犹豫)
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>