javascript - Canvas - 填充线条下方或上方的区域

标签 javascript html canvas charts

好的,我有一个难题要解决。我有一个 HTML5 Canvas ,我在其中绘制了两个图表(线)。我有每个图表的连接点,我有两个 y 值(图片中的 X、Y),我必须在其中画一条线并在图表上方或下方填充。 我似乎真的无法让它工作,因为我尝试为特定图表上方的所有内容着色并用矩形对其进行剪裁,但我有两个图表,所以我必须有两个剪裁区域,这会给出不正确的解决方案。

帖子有附图看案例

enter image description here

所以我有一张红色图表和一张棕色图表以及 X 和 Y 的值(彩色线条)。 X 是浅蓝色 - 我要为下图着色的高度。 Y为浅灰色,为棕色图表上方着色的高度。

如何在不知道图表与 X 或 Y 的交叉点的情况下实现这一点?

我使用的代码是这样的。我为每个图表调用它两次。我省略了绘制图表的代码——它是使用“点”数组绘制的。 不幸的是,我没有颜色区域末端和图表之间的交叉点(红色和浅蓝色的交叉点;棕色和浅灰色)

ctx.rect(clipX, clipY, clipWidth, clipHeight);
		ctx.stroke();
		ctx.clip();

		//fill the area of the chart above or below
		ctx.globalAlpha = 0.4;
		ctx.strokeStyle = color;
		ctx.fillStyle = color;
		ctx.beginPath();
		ctx.moveTo(points[0].x, points[0].y + visibleGraphicSpace);
		for (var i = 1; i < points.length; i++) {
			ctx.lineTo(points[i].x, points[i].y + visibleGraphicSpace);
		}
		ctx.closePath();
		ctx.fill();

首先,我为可见区域绘制矩形,然后使用给定的点数组绘制图表,关闭它并填充上方或下方的所有内容,直到 Canvas 结束。但是这个解决方案只占用第二次填充权,因为它覆盖了第一次。

PS:我需要画两种颜色的填充物,而不是只画一种。

我希望我能把它解释得足够好。如果您有任何问题,请不要介意提问。 提前感谢您的帮助。

最佳答案

您可以创建一个剪辑区域(使用 context.clip)以确保您的蓝色和灰色填充包含在图表创建的路径内。设置裁剪区域后,裁剪区域外将不会显示任何新绘图。

  • 将一些图表点保存在数组中。
  • 在图表点内保存填充的顶部和底部范围
  • 定义图表路径(==绘制点而不绘制点)
  • 根据路径创建裁剪区域(所有新绘制的内容都包含在裁剪区域内,不会出现在区域外)
  • 填充裁剪区域(使用蓝色和灰色填充)
  • 描边路径(用红色和栗色描边)

注意:创建剪切路径时,只能通过将剪切代码包装在 context.savecontext.restore 中来“取消剪切”。

enter image description here

这是带注释的代码和演示:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var pts0=[
  {x:119,y:239},
  {x:279,y:89},
  {x:519,y:249},
  {x:739,y:83},
  {x:795,y:163},
];
  var fill0={top:75,bottom:133};

  var pts1=[
  {x:107,y:342},
  {x:309,y:523},
  {x:439,y:455},
  {x:727,y:537},
  {x:757,y:389}
];
var fill1={top:473,bottom:547};

filledChart(pts0,fill0,'red','skyblue');
filledChart(pts1,fill1,'maroon','lightgray');


function filledChart(pts,fill,strokecolor,fillcolor){
  // define the path
  // This doesn't stroke the path, it just "initializes" it for use
  ctx.beginPath();
  ctx.moveTo(pts[0].x,pts[0].y);
  for(var i=0;i<pts.length;i++){
    var pt=pts[i];
    ctx.lineTo(pt.x,pt.y);
  }

  // save the un-clipped context state
  ctx.save();

  // Create a clipping area from the path
  // All new drawing will be contained inside
  // the clipping area
  ctx.clip();

  // fill some of the clipping area
  ctx.fillStyle=fillcolor;
  ctx.fillRect(0,fill.top,cw,fill.bottom-fill.top);

  // restore the un-clipped context state
  // (the clip is un-done)
  ctx.restore();

  // stroke the path
  ctx.strokeStyle=strokecolor;
  ctx.lineWidth=2;
  ctx.stroke();
}
body{ background-color: ivory; }
#canvas{border:1px solid red; }
<canvas id="canvas" width=800 height=550></canvas>

关于javascript - Canvas - 填充线条下方或上方的区域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34339520/

相关文章:

javascript - 如何将 onclick 事件添加到 Razor View 中的单选按钮

html - 将表格单元格限制为只有一行文本? 'overflow' 和 'white-space' 不工作

java - 在 ListView 元素内绘制到 Canvas

javascript - 图表区域背景颜色chartjs

javascript - 二维 map 数组上的简单 Javascript 碰撞检测

javascript - 如何在用户单击音频标签中的播放按钮时显示消息?

javascript - 将值从 Controller 传递到另一个页面上的另一个 Controller - AngularJS

javascript - 如何将数组中的整数相乘?

javascript - 如何声明一个与 ng-repeat 类似的变量,但对于单个对象?

javascript - 缓存静态页面和内容nodejs