我无法获得连续的画布矩形在js中具有重复的线性渐变。谁知道怎么样?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我无法获得连续的画布矩形在js中具有重复的线性渐变。谁知道怎么样?相关的知识,希望对你有一定的参考价值。

我绘制了一个带有连续矩形的画布,每个画布都有自己的线性渐变,但除了第一个矩形外,我无法在矩形上显示线性渐变。每个矩形的大小相同,每个矩形应具有相同的线性渐变。我只能使第一个矩形具有正确的渐变,但其余的都没有。其余的都是黑色的。一直在寻找互联网,无法找到答案。我哪里做错了?谢谢!

这是我的代码笔: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;  
}
}
答案

您只是将渐变定义为仅在第一个矩形上方。渐变不符合你的形状,如果你告诉它在coords 0的宽度为20px,那么在这些coordsa之外绘制的每个形状都将是你设置的2种极端颜色之一。

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

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

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>
另一答案

Path and render transforms

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

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

如果您对填充和描边使用单独的样式,这将特别有用。

示例适合渐变到路径

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

中风有一个警告。 lineWidth是一种风格,在调用stroke时通过当前变换进行转换。这限制了您仅使用统一比例,并且您必须反转lineWidth大小。看看如何在代码中。

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>

以上是关于我无法获得连续的画布矩形在js中具有重复的线性渐变。谁知道怎么样?的主要内容,如果未能解决你的问题,请参考以下文章

具有线性渐变的CSS过渡[重复]

canvas怎么画一个渐变的圆角边框,填充的也行

画布线性渐变采用另一个输入类型颜色字段的值

有没有办法在 QML 中设置线性渐变 stepwith

Android 绘图基础:Canvas画布——自定义View基础(绘制表盘矩形圆形弧渐变)

Cordova 无法处理的具有线性渐变的 SVG - iOS