代码之家  ›  专栏  ›  技术社区  ›  mleroy

我无法让连续的画布矩形在js中具有重复的线性渐变。有人知道怎么做吗?

  •  1
  • mleroy  · 技术社区  · 6 年前

    我画了一幅画布,上面有连续的矩形,每个矩形都有自己的线性渐变,但除了第一个矩形外,我无法在矩形上显示线性渐变。每个矩形的大小都相同,并且每个矩形都应该具有相同的线性渐变。我只能使第一个矩形具有正确的渐变,但其他矩形都没有。其余的是黑色的。我在网上到处找,找不到答案。我哪里出错了?谢谢

    这是一支笔,上面写着我的代码: https://codepen.io/monamoves/pen/RQvzOe

    又来了。

    HTML:

    <canvas id="fabric" width="1020" height="300">
    </canvas>
    

    CSS:

    canvas {
      border: thin red solid;
    }
    

    JavaScript:

    window.onload = draw;
    
    function draw() {
    var cvs = document.getElementById("fabric");
    var ctx = cvs.getContext("2d");
    
    var xcoordinate = 0;
    var grd = ctx.createLinearGradient(xcoordinate, 0, xcoordinate + 20, 0);
    
    for (var i = 0; i < 50; i++) {
      ctx.beginPath();
      ctx.strokeStyle="#ccc";
      ctx.moveTo(xcoordinate, 0);
      ctx.rect(xcoordinate, 0, 20, 300);
      ctx.stroke();
      ctx.fillStyle = grd;
      grd.addColorStop(0, "black");
      grd.addColorStop(0.5, "white");
      grd.addColorStop(1, "black");
      ctx.fill();
      xcoordinate = xcoordinate + 20;  
    }
    }
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   Kaiido    6 年前

    您只需在第一个矩形上定义一次渐变。渐变不会跟随你的形状,如果你告诉它在坐标0,0处宽20px,那么在这些坐标之外绘制的每个形状都将是你设置的两种极端颜色之一。

    您可以在for循环中的每次迭代中创建一个新的渐变,实际上,如果您想更改其色块,就必须这样做。

    但在你的情况下,最好的解决方案(单梯度)是只声明一次你的梯度,只设置一次它的色停止,并简单地修改你的上下文的变换矩阵;坡度也会受到影响。

    var ctx = cvs.getContext("2d");
    
    var xcoordinate = 0;
    // set all this only once if it doesn't change
    var grd = ctx.createLinearGradient(0, 0, 20, 0);
    ctx.fillStyle = grd;
    grd.addColorStop(0, "black");
    grd.addColorStop(0.5, "white");
    grd.addColorStop(1, "black");
    ctx.strokeStyle="#ccc";
    
    for (var i = 0; i < 50; i++) {
      ctx.beginPath();
      // we move the transform matrix
      ctx.setTransform(1,0,0,1,xcoordinate,0);
      // and draw always at same coords
      ctx.moveTo(0, 0);
      ctx.rect(0, 0, 20, 300);
      ctx.stroke();
      ctx.fill();
      xcoordinate = xcoordinate + 20;  
    }
    <canvas id=cvs></canvas>
        2
  •  0
  •   Community Egal    4 年前

    路径和渲染变换

    创建路径时,它使用调用路径函数时当前的变换,使用填充或笔划时,可以设置另一个变换。

    这允许您使用单独的坐标系,一个用于形状,一个用于填充,一个用于笔划。

    如果对填充和笔划使用单独的样式,这将非常有用。

    将渐变拟合到路径的示例

    该示例显示了缩放和转换的两个渐变,以适合在其自己的坐标系中创建的3个形状的填充和笔划。

    中风有一个警告。 lineWidth 是一种样式,在以下情况下由当前变换进行变换: stroke 被调用。这将限制您仅使用统一比例,并且必须反转 线宽 大小请参见如何在代码中执行。

    const ctx = canvas.getContext("2d");
    
    const grad1 = [[0, "green"], [0.45, "gold"], [0.55, "gold"], [1, "green"]];
    const grad2 = [[0, "red"], [0.25, "black"], [0.75, "black"], [1, "red"]];
    const addColStops = (g,s) => s.forEach(s => g.addColorStop(...s));
    const style = {lineWidth: 5};
    
    //==============================================================
    // fill gradient
    style.fillStyle = ctx.createLinearGradient(0, 0, 20, 0);
    // to simplify I attach the coords to the gradient so that it can be scaled to
    // fit the rendered content
    style.fillStyle.coords = { w: 20, h: 0 };
    addColStops(style.fillStyle, grad1);
    
    //==============================================================
    // stroke gradient
    style.strokeStyle = ctx.createLinearGradient(0, 0, 0, 20);
    style.strokeStyle.coords = { w: 0, h: 20 };
    addColStops(style.strokeStyle, grad2);
    
    //==============================================================
    // 3 example boxes
    drawBox(10, 10, 60, 130, style);
    style.lineWidth += 4;
    drawBox(90, 10, 80, 130, style);
    style.lineWidth += 8;
    drawBox(200, 10, 140, 130, style);
    
    //==============================================================
    // draw box
    function drawBox(x, y, width, height, style) {
    
      // shape drawn in default coordinates 
      ctx.setTransform(1, 0, 0, 1, 0, 0); // default transform
      Object.assign(ctx, style); // set the style
    
      //============================================================
      // create the shape
      ctx.beginPath();
      ctx.rect(x, y, width, height);
    
      //============================================================
      // Make the gradient fit the stroke
      const s = style.strokeStyle.coords;
    
      // uniform scale for strokes only and correct for line width
      var scale = (width + ctx.lineWidth) / (s.w ? s.w : 1);
      if (s.w === 0) { scale = (height + ctx.lineWidth) / (s.h ? s.h : 1) }
      ctx.setTransform(
        scale, 0, 0, scale,
        x - ctx.lineWidth / 2, // correct for line width
        y - ctx.lineWidth / 2
      );
      // invert the lineWidth to correct its scale
      ctx.lineWidth /= scale;
      ctx.stroke();
    
      //============================================================
      // Make the fill gradient fit the rect
      const f = style.fillStyle.coords;
      ctx.setTransform(
        width / (f.w ? f.w : 1), // scale grad width if needed
        0, 0,
        height / (f.h ? f.h : 1), // scale grad heigh if needed
        x, y
      );
      ctx.fill();
    }
    <canvas id=canvas width="400"></canvas>