【问题标题】:Canvas - fill area below or above lines画布 - 填充线条下方或上方的区域
【发布时间】:2015-12-17 16:24:20
【问题描述】:

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

有贴图看案例

所以我有一个红色图表和一个棕色图表以及 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();

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

PS:我需要绘制两种着色填充物,而不仅仅是其中一个。

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

【问题讨论】:

    标签: javascript html canvas charts


    【解决方案1】:

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

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

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

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

    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; }
    &lt;canvas id="canvas" width=800 height=550&gt;&lt;/canvas&gt;

    【讨论】:

    • 这正是我所需要的!非常感谢答案!惊人而干净:)
    【解决方案2】:

    您可以尝试在图表前进行“填充”。

    1. 您创建填充颜色。
    2. 您创建了“面具”(白色)
    3. 您创建图表线

    一个示例,只有一个图表,但可以轻松更改为使用两个图表:https://jsfiddle.net/eLwc96fj/

    var c2 = document.getElementById('test').getContext('2d');
    
    // Create a colored rectangle
    c2.fillStyle = '#0f0';
    c2.rect(80,0, 200,70);
    c2.fill();
    
    // Create the 'mask' - it has the same path than the chart, but then follow the above rectangle.
    c2.beginPath();
    c2.fillStyle = '#fff';
    c2.moveTo(80, 80);
    c2.lineTo(120,50);
    c2.lineTo(180, 90);
    c2.lineTo(250, 40);
    c2.lineTo(280, 120);
    c2.lineTo(280, 0);
    c2.lineTo(80, 0);
    c2.closePath();
    c2.fill();
    
    // Draw the chart itself
    c2.strokeStyle = '#f00';
    c2.beginPath();
    c2.moveTo(80, 80);
    c2.lineTo(120,50);
    c2.lineTo(180, 90);
    c2.lineTo(250, 40);
    c2.lineTo(280, 120);
    c2.stroke();
    

    【讨论】:

      猜你喜欢
      • 2018-09-10
      • 1970-01-01
      • 1970-01-01
      • 2021-06-23
      • 2014-03-11
      • 2015-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多