javascript - 在 React 中实现 HTML5 Canvas 渐变

标签 javascript reactjs html canvas html5-canvas

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

我的目标是得到与此更接近的东西: enter image description here

颜色混合的地方。

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

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;

感谢您的帮助!

最佳答案

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

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

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

并且您在位置 01 处添加两个新色标 blueyellow,您将有类似的东西

 <-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 中添加了更多颜色停止点。

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

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>

关于javascript - 在 React 中实现 HTML5 Canvas 渐变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55006679/

相关文章:

html - 删除箭头旋转木马 Bootstrap 附近的可点击区域

iphone - 移动 safari 中忽略的溢出 x 值

javascript - 为什么此复选框缺少 "checked"属性?

javascript - 如何获取小数点后的任意位数以及我必须存储的数据类型

reactjs - react 从类到功能组件的调用。错误: Invalid hook call. Hooks只能在函数组件的主体内部调用

reactjs - 如何修改 Material UI datagrid 复选框图标?

reactjs - Deck.GL 与 CARTO 和 React

html - 'datePublished' 属性和 HTML 'lang' 属性

javascript - 如何为数组中的所有对象更新键

javascript - 使用 if 语句和 document.write 隐藏/显示 li 列表