【问题标题】:html5 canvas triangle filled color by percentagehtml5画布三角形按百分比填充颜色
【发布时间】:2016-06-26 06:22:58
【问题描述】:

我在画布上有一个三角形,我想用颜色填充它.. 可能不止一种颜色.. 我该怎么做?

我的三角形在这里:

function draw() {

        var width = 360;  // Triangle Width
        var height = 400; // Triangle Height
        var padding = 90;

        // Draw a path
        ctx.beginPath();
        ctx.moveTo(padding + width/2, padding+height);        // Top Corner
        ctx.lineTo(padding + width,  padding); // TOP Right
        ctx.lineTo(padding,  padding);         // TOP Left
        ctx.closePath();

        ctx.strokeStyle = "#e8ecef";
        ctx.lineWidth = 25;
        ctx.stroke();



        ctx.restore();
}

当前结果与此图像中的结果类似:

我想要这样的结果:

请帮忙?我该怎么做?或者是否有任何插件可以帮助我更快地做到这一点?

【问题讨论】:

    标签: html css canvas html5-canvas


    【解决方案1】:

    构图模式

    这个问题可以简单地通过使用几种合成模式和很少的数学来解决(只计算正确的位置)。

    收据是:

    • 绘制一个代表整个三角形背景的蒙版(颜色无关紧要,只要它不透明)
    • 创建带有硬过渡的渐变以定义不同的颜色部分。
    • 在顶部合成一个矩形,使用source-in 模式将其裁剪为背景形状。
    • 使用普通的source-over模式描边

    所有这些步骤都可以重复使用单个路径。渐变将允许您在一处定义所有彩色部分。只需确保每个部分以相同的颜色开始和结束,并且下一个部分将从上一个停止的位置开始。这将在各个部分之间形成硬边。

    由于渐变颜色停止采用标准化值,因此只需定义渐变线相对于三角形位置和大小的起点和终点,即可轻松匹配任意大小。 p>

    根据需要进行调整。

    修改代码示例

    我在您的基本代码中插入了代码以显示需要修改的位置。

    var ctx = c.getContext("2d"),
        width = 360, height = 400, padding = 90, split = 0.33;
    
    // Draw a path that will be reused below
    ctx.beginPath();
    ctx.moveTo(padding + width/2, padding+height); // Top Corner
    ctx.lineTo(padding + width,  padding);         // TOP Right
    ctx.lineTo(padding,  padding);                 // TOP Left
    ctx.closePath();
    
    // fill for a mask (color doesn't matter as long as it's opaque)
    ctx.fill();
    
    // define gradient
    var gr = ctx.createLinearGradient(0, padding, 0, padding+height); // line
    gr.addColorStop(0    , "rgb(187, 19, 221)");
    gr.addColorStop(split, "rgb(187, 19, 221)");
    gr.addColorStop(split, "rgb(38, 199, 222)");
    gr.addColorStop(1    , "rgb(38, 199, 222)");
    
    // fill the colored sections (adjust positions as needed)
    ctx.globalCompositeOperation = "source-in";
    ctx.fillStyle = gr;
    ctx.fillRect(0, 0, c.width, c.height);
    
    // stroke outline
    ctx.globalCompositeOperation = "source-over";
    ctx.strokeStyle = "#e8ecef";
    ctx.lineWidth = 25;
    ctx.stroke();
    <canvas id=c width=500 height=550></canvas>

    【讨论】:

      【解决方案2】:

      有效地,一个很好的方法是画一个底三角形,然后在上面画一个梯形,然后在这些上面做笔划。

      function draw(percent) {
      
          var width = 360;  // Triangle Width
          var height = 400; // Triangle Height
          var padding = 90;
      
          // Draw the purple triangle underneath
          ctx.beginPath();
          ctx.moveTo(padding + width/2, padding+height);        // Top Corner
          ctx.lineTo(padding + width,  padding); // TOP Right
          ctx.lineTo(padding,  padding);         // TOP Left
      
          ctx.fillStyle = "#990099";
          ctx.fill();
      
          // Draw second triangle/trapezium over the top
          ctx.beginPath();
          ctx.moveTo(padding + width*percent/2, padding+height*percent);          //Bottom left
          ctx.lineTo(padding + width - width*percent/2, padding+height*percent);  //Bottom right
          ctx.lineTo(padding + width,  padding); // TOP Right
          ctx.lineTo(padding,  padding);         // TOP Left
      
          ctx.fillStyle = "#00ccff";
          ctx.fill();
      
          // Draw the grey line around the triangles
          ctx.beginPath();
          ctx.moveTo(padding + width/2, padding+height);        // Top Corner
          ctx.lineTo(padding + width,  padding); // TOP Right
          ctx.lineTo(padding,  padding);         // TOP Left
          ctx.closePath();
      
          ctx.strokeStyle = "#e8ecef";
          ctx.lineWidth = 25;
          ctx.stroke();
      
          ctx.restore();
      }
      
      draw(0.1);
      

      draw 函数适用于 0 到 1 之间的任何值,其中 0 是 0% 蓝色,1 是 100% 蓝色。由于这是一个三角形,如果为 50%,填充的区域将看起来不相等,但百分比将介于顶部坐标和底部坐标之间。

      希望对你有帮助

      【讨论】:

        【解决方案3】:

        三角形和面积

        求解分数 (p) (0-1) 以给出三角形 (w) 宽度和 (h) 高度的新高度 (h1)

        三角形的面积是

        • w * h * 0.5

        切割三角形会得到一个三角形和一个梯形。

        我们将求解使得分数面积是梯形的面积。

        以三角形 w、h 和 h1 表示的梯形面积(尖端的另一端),其中 h1 是梯形的未知高度。

        • a1 = w * h1 - (w / 2 * h) * h1 * h1

        h1 * h1 表示此解是二次解,因此请制定一个等于 0 的公式。我们知道梯形的面积是三角形面积乘以分数,因此使用 (w * h * 0.5 * p)并用 h1 减去上述面积解,得到

        • 0 = w * h * 0.5 * p - w * h1 - (w / 2 * h) * h12

        这给出了一个二次方程,一般形式是 ax2 + bx + c = 0(在这种情况下,未知值 x 是 h1 梯形的高度)可以用 (-b (+/-) sqrt(b2 - 4ac) ) / 2a。由于解决方案中的 (+/-) 有两个答案,现阶段不知道哪个答案是正确的。

        因此我们需要 a,b,c 来解决

        • a = w/(2*h)
        • b = - w
        • c = w * h * 0.5 * p

        所以作为一个函数

        // return the height of the trapezoid made from a triangle of width height that 
        // has an area equal to the area of the triangle * fraction
        function getFractionHeightOfTriangle(width,height,fraction){
              var a = width / (2 * height);
              var b = -width;
              var c = width * height * 0.5 * fraction;
        
              // find the two solutions
              var h1_a = (-b + Math.sqrt(b * b - 4 * a * c)) / (2 * a);
              var h1_b = (-b - Math.sqrt(b * b - 4 * a * c)) / (2 * a);
        
              // from experiment the solution is the second one
              // or you can check which is positive and return that
              return h1_b;  
          }
        

        以顶部为原点绘制三角形

        // x,y is the top (pointy end) w is width h is height
        // col is stroke colour, col1 is fillColour
        // lineW is line width.
        var drawTriangle = function(x,y,w,h,col,col1,lineW){
            ctx.beginPath();
            ctx.strokeStyle = col;
            ctx.fillStyle = col1;
            ctx.lineWidth = lineW;
            ctx.moveTo(x,y );
            ctx.lineTo(x + w / 2 ,y + h);
            ctx.lineTo(x - w / 2 ,y + h);
            ctx.closePath();
            ctx.fill();
            ctx.stroke();
        }
        

        绘制三角形的一部分

        // See above function for x,y,w,h,col,col1,lineW
        // which is == "top" for pointy end and != "top" for trapezoid
        // amount is the height of the top
        var drawPartTriangle = function(x,y,w,h,which,amount,col,col1,lineW){
            ctx.beginPath();
            ctx.strokeStyle = col;
            ctx.fillStyle = col1;
            ctx.lineWidth = lineW;
            if(which === "top"){
                ctx.moveTo(x,y);
                ctx.lineTo(x + w / 2 * (amount / h),y + amount);
                ctx.lineTo(x - w / 2 * (amount / h),y + amount);
            }else{
                ctx.moveTo(x + w / 2 * (amount / h),y + amount);
                ctx.lineTo(x + w / 2 ,y + h);
                ctx.lineTo(x - w / 2 ,y + h);
                ctx.lineTo(x - w / 2 * (amount / h),y + amount);   
            }
            ctx.closePath();
            ctx.fill();
            ctx.stroke();
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-02-14
          • 2019-10-07
          • 2016-03-13
          • 2021-09-19
          • 1970-01-01
          • 2017-01-23
          • 1970-01-01
          • 2017-12-04
          相关资源
          最近更新 更多