如何在React中访问画布上下文

coc*_*coa 11 javascript html5 canvas reactjs

我用React和Canvas 制作了一个颜色选择器.目前,组件在React中呈现,canvas使用vanilla javascript完成.我想两个网格更多,所以我希望用React处理点击事件.

例如,这个

colorStrip.addEventListener("click", click, false);

function click(e) {
  x = e.offsetX;
  y = e.offsetY;
  var imageData = context.getImageData(x, y, 1, 1).data;
  rgbaColor = 'rgba(' + imageData[0] + ',' + imageData[1] + ',' + imageData[2] + ',1)';
  fillGradient();
}
Run Code Online (Sandbox Code Playgroud)

我希望能够转化为此

var ColorPicker = React.createClass({
  colorStripClick: function() {
    //handle click events here
  },
  render: function() {
    var styles = {
      opacity: this.props.isVisible ? '1' : '0'
    };
    return(
      <div id="color-picker" style={styles}>
        <canvas id="color-block" height="150" width="150"></canvas>
        <canvas id="color-strip" height="150" width="30" onClick={this.colorStripClick}></canvas>
      </div>
    );
  }
});
Run Code Online (Sandbox Code Playgroud)

但这不起作用,因为我不知道如何访问context.如何使用React访问画布属性?有没有办法在点击之前访问它?

UPDATE

我用大卫的答案,但我是通过将一个函数在收到错误信息ref,所以我做ref="canvasBlock"ref="canvasStrip"代替,然后分配在上下文componentDidMount

Fer*_*ojo 18

这是反应钩子的答案:

import { useEffect, useRef } from 'react'

export function Canvas() {
  const ref = useRef()

  useEffect(() => {
    if (ref.current) {
      const canvas = ref.current.getContext('2d')
      // do something here with the canvas
    }
  }, [])

  return <canvas ref={ref} />
}
Run Code Online (Sandbox Code Playgroud)

打字稿

如果您使用 TypeScript:

import { useEffect, useRef } from 'react'

export function Canvas() {
  const ref = useRef<HTMLCanvasElement>(null)

  useEffect(() => {
    if (ref.current) {
      const canvas = ref.current.getContext('2d')
      // do something here with the canvas
    }
  }, [])

  return <canvas ref={ref} />
}
Run Code Online (Sandbox Code Playgroud)

在山上

如果您只想对画布实例执行一次操作(当组件“安装”时),您最好使用useCallback. 这样,您的效果就不会在 React Strict 模式下运行两次。

import { useEffect, useCallback } from 'react'

export function Canvas() {
  const refCallback = useCallback((canvas: HTMLCanvasElement) => {
    // do something here with the canvas
  }, [])
  return <canvas ref={refCallback} />
}
Run Code Online (Sandbox Code Playgroud)


Dav*_*ing 12

您可以refcanvas元素上添加函数属性:

<canvas id="color-strip" ref={(c) => this.context = c.getContext('2d')} height="...
Run Code Online (Sandbox Code Playgroud)

然后您将通过this.context以下方式访问上下文:

colorStripClick: function() {
    var imageData = this.context.getImageData(x, y, 1, 1).data
}
Run Code Online (Sandbox Code Playgroud)

您也可以使用事件对象来访问已经指出的DOM节点,但这样您就可以从任何地方访问,而不仅仅是事件处理程序.


小智 12

按照React16你可以使用 React.createRef()

class ColorPicker extends React.Component {
constructor(props) {
   super(props);

   this.colorPickerRef = React.createRef();
}

componentDidMount() {
   this.context = this.colorPickerRef.current.getContext('2d');
}

render() {
   return (
      <canvas ref={this.colorPickerRef} />
   )
}
}
Run Code Online (Sandbox Code Playgroud)