【问题标题】:How can I use an SVG element created with JSX as an image source in a Canvas?如何使用 JSX 创建的 SVG 元素作为 Canvas 中的图像源?
【发布时间】:2019-07-11 22:25:41
【问题描述】:

我有一个 ReactJS 应用程序。我正在动态生成 SVG 图像作为 JSX 组件。到目前为止,一切都很好——但现在我需要使用 SVG 作为 Canvas 元素中的图像源。这适用于静态 SVG 文件,但如何将动态 SVG 放入画布?

sn-p 中出现了一个简化版本。在 componentDidMount 方法中显示了 drawImage 调用的两种方法:创建一个未挂载的 SvgSource,以及使用一个挂载在页面上的 ref,但它们都失败了。

class App extends React.Component {

	// On mount, paint the SVG in the canvas
	componentDidMount(){
  	let ctx = this.canvasRef.getContext("2d")
    
    // THIS DOES NOT WORK:
  	//ctx.drawImage(new SvgSource({fill: "green"}), 50, 50);
    
    // NOR DOES THIS:
    //ctx.drawImage(this.svgRef, 50, 50);
    
    /* TypeError: Argument 1 of CanvasRenderingContext2D.drawImage could not be converted to any of: HTMLImageElement, SVGImageElement, HTMLCanvasElement, HTMLVideoElement, ImageBitmap. */
  }

  render() {
  return (
  <div>     
    {/* This works, inserting the SvgSource element directly - but that's not what I want. */}
    <SvgSource ref={s => this.svgRef = s} fill="blue" />
    
    {/* I want to use the SVG as an image source in this canvas. */}
  	<canvas 
      ref={
      c => this.canvasRef = c 
      /* NB: using older ref syntax because jsFiddle uses React .14 - use CreateRef with version 16 */
      } 
      width={200} 
      height={200} />
  </div>
  );
  }
}

// Our JSX SVG component that provides the custom image to use in the canvas
class SvgSource extends React.Component {
  render() {
    return (
      <svg width={100} height={100} viewBox="0 0 100 100">
        <circle cx={50} cy={50} r={25} fill={this.props.fill || "red"}/>
      </svg>
    );
  }
}

ReactDOM.render(<App />, document.querySelector("#app"))
body {
  background: #20262E;
  padding: 20px;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  min-height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>

澄清一下:我知道如何将普通的 SVG 图像插入到画布元素中。问题是将 JSX SVG 转换为画布上下文中 drawImage 的有效源,因此这一切都可以在 React 组件中完成。

【问题讨论】:

标签: reactjs svg canvas jsx


【解决方案1】:

这不是一种非常优雅的方式,但这是我最终的结果:

class SvgSource extends React.Component {
    generateSvg() {
        return "data:image/svg+xml;base64," + 
            btoa(`<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><circle cx="50" cy="50" r="25" fill="${this.props.fill}" /></svg>`);
    }

    render() {
        return (<img src={this.generateSvg()} />);
    }
}

我没有将 SVG 设为 JSX 对象,而是将其构造为字符串,编码为 base64 以用作数据 URL。然后我可以从render() 函数返回一个&lt;img&gt; JSX 元素,以直接在页面中使用图像。当我需要在画布中使用它时,我可以直接调用new SvgSource({fill: "green"}).generateSvg(),使用在普通(非JSX)&lt;img&gt; 元素的src 属性中返回的字符串。

我找不到更好的方法来渲染 SVG 标记而不将其实际放在页面上。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-10
    • 2020-08-29
    • 2023-03-04
    • 1970-01-01
    • 2020-07-19
    • 2011-06-20
    • 2019-04-15
    • 2012-06-07
    相关资源
    最近更新 更多