在React中实现HTML5画布渐变

问题描述 投票:0回答:1

我正在尝试创建一个应用程序,让您使用两种不同的颜色创建背景渐变,我正在使用React。渐变的第一种颜色看起来应该如此,但渐变的第二种颜色更多是纯色,带有锯齿状边框。下面是一张图片来证明:enter image description here

我的目标是获得更接近这一点的东西:enter image description here

颜色混合的地方。

我指的是MDN文档,并且已经弄乱了半径和x,y属性。我正在根据父组件的prop更改来更改画布,这是我的代码:

import React, { Component } from "react";

class Canvas extends Component {
  componentDidMount() {
    const { gradientOne, gradientTwo } = this.props.canvasState.backgroundColor;
    this.ctx = this.canvas.getContext("2d");
    this.radialGradient = this.ctx.createRadialGradient(
      0,
      0,
      300,
      260,
      160,
      100
    );

    this.ctx.fillStyle = this.radialGradient;
    this.ctx.rect(0, 0, this.canvas.width, this.canvas.height);
    this.radialGradient.addColorStop(0, gradientOne);
    this.radialGradient.addColorStop(1, gradientTwo);
    this.ctx.fill();
  }

  componentDidUpdate(prevProps, prevState) {
    const { gradientOne, gradientTwo } = this.props.canvasState.backgroundColor;
    if (prevProps.canvasState.backgroundColor.gradientOne !== gradientOne) {
      this.ctx.fillStyle = this.radialGradient;
      this.radialGradient.addColorStop(0, gradientOne);
      this.ctx.fill();
    } else if (
      prevProps.canvasState.backgroundColor.gradientTwo !== gradientTwo
    ) {
      this.ctx.fillStyle = this.radialGradient;
      this.radialGradient.addColorStop(1, gradientTwo);
      this.ctx.fill();
    }
  }
  render() {
    return (
      <main className="canvasContainer">
        <canvas ref={ref => (this.canvas = ref)} id="canvas">
          YOUR BROWSER DOESN'T SUPPORT THIS FEATURE :(
        </canvas>
      </main>
    );
  }
}

export default Canvas;

谢谢你的帮助!

javascript reactjs html5 canvas html5-canvas
1个回答
1
投票

CanvasGradient的颜色停止(无论是线性还是径向)都不能修改或删除。 当您添加新的色标时,在与前一个色索相同的索引处,它会被放置在前一个色卡之后。因此,不是只有两个颜色停止,而是四个。

这意味着如果你有这样的原始渐变

 <-red -------------------------------------------- green->

并且你在位置blueyellow添加两个新颜色停止01,你会有类似的东西

 <-red[blue -------------------------------- green]yellow->

也就是说,红色和蓝色之间,黄色和绿色之间没有渐变:

const ctx = canvas.getContext('2d');
ctx.strokeStyle = 'white';
// an horizontal gradient
// 0 is at pixel 50, and 1 at pixel 250 on the x axis
const grad = ctx.createLinearGradient(50,0,250,0);
grad.addColorStop(0, 'red');
grad.addColorStop(1, 'green');
ctx.fillStyle = grad;
// top is two color stops version
ctx.fillRect(0,0,300,70);

// bottom is four color stops version
grad.addColorStop(0, 'blue');
grad.addColorStop(1, 'yellow');
ctx.fillStyle = grad;
ctx.fillRect(0,80,300,70);

//  mark color stops
ctx.moveTo(49.5,0);
ctx.lineTo(49.5,150);
ctx.moveTo(249.5,0);
ctx.lineTo(249.5,150);
ctx.stroke();
canvas { border: 1px solid };
<canvas id="canvas"></canvas>

这就是你在代码中所做的事情,因为你在componentDidMount中添加两个颜色停止,然后在componentDidUpdate中添加更多颜色。

要避免这种情况,只需在gradient中覆盖componentDidUpdate属性,以便每次都使用新渐变开始。

const ctx = canvas.getContext('2d');
let radialGradient;
function didMount() {
  radialGradient = ctx.createRadialGradient(
    0,0,300,
    260,160,100
   );
  radialGradient.addColorStop(0, c1.value);
  radialGradient.addColorStop(1, c2.value);
  ctx.fillStyle = radialGradient;
  ctx.fillRect(0,0,canvas.width,canvas.height);
}
function didUpdate() {
  // reset radialGradient to a new one
  radialGradient = ctx.createRadialGradient(
    0,0,300,
    260,160,100
   );
  radialGradient.addColorStop(0, c1.value);
  radialGradient.addColorStop(1, c2.value);
  ctx.fillStyle = radialGradient;
  ctx.fillRect(0,0,canvas.width,canvas.height);
}

didMount();
c1.oninput = c2.oninput = didUpdate;
canvas { border: 1px solid };
<input id="c1" type="color" value="#22CC22">
<input id="c2" type="color" value="#FF2222">
<canvas id="canvas"></canvas>
© www.soinside.com 2019 - 2024. All rights reserved.