首页 > 解决方案 > Konva-React 文本填充图像或渐变不起作用

问题描述

我正在尝试用除颜色以外的任何内容填充 Konvajs (konva-react) 中的文本。即使我在尝试填充渐变时将填充优先级设置为“线性渐变”,它也会默认为一种颜色。我尝试将颜色填充设置为透明。它仍然没有显示图像或渐变。这是尝试填充图像的代码。

import React, { Component } from 'react'
import Konva from "konva"
import {
  Stage,
  Layer,
  Image,
  Text
} from "react-konva"
import './App.css'


class Text2 extends React.Component {
  state = {
    text: "Happy New Year!",
    image: new window.Image(),
    ready: true
  }

  componentDidMount() {
    console.log("text path componentDidMount")
    console.log(this.state.image.src === null)
    this.state.image.src = 'http://localhost:3004/silver-metal-background-01.jpg'

    this.state.image.onload = e => {
      console.log('silver image loaded')
      this.state.ready = true
      console.log(this.TextNode)
    }

  }

  render = () => {
    var text =
      this.state.ready === false
      ? <React.Fragment></React.Fragment>
      :  <Text
          ref={node => {
            this.TextNode = node
          }}
          name="happyNewYear"
          x={32}
          y={175}
          text={this.state.text}
          fontFamily='Sigmar One'
          fontSize={36}
          fontWeight='bold'
          draggable={true}
          fill={this.state.image}
          stroke='red'
          strokeWidth={2}
          scaleX={1}
          scaleY={1}
          opacity={1}
        />

    return (
      <React.Fragment>
        { text }
      </React.Fragment>
    );
  }
}

class App extends Component {
render = () => {

  return (
    <React.Fragment>
      <Stage
        ref={node => {
          this.stage = node
        }}
        x={0}
        y={0}
        width={window.innerWidth} 
        height={window.innerHeight}            
      >
        <Layer
          ref={node => {
            this.layer = node
          }}
        >
          <Text2 />
        </Layer>
      </Stage>
    </React.Fragment>
  )
}

export default App

这是尝试填充渐变的代码。

import React, { Component } from 'react'
import Konva from "konva"
import {
  Stage,
  Layer,
  Image,
  Text
} from "react-konva"
import './App.css'


class Text2 extends React.Component {
  state = {
    text: "Happy New Year!"
  }

  componentDidMount() {
    console.log("text path componentDidMount")

  }

  render = () => {
    var text =
      this.state.ready === false
      ? <React.Fragment></React.Fragment>
      :  <Text
          ref={node => {
            this.TextNode = node
          }}
          name="happyNewYear"
          x={32}
          y={175}
          text={this.state.text}
          fontFamily='Sigmar One'
          fontSize={36}
          fontWeight='bold'
          draggable={true}
          fillLinearGradientStartPoint={ {x : 0, y : 0} }
          fillLinearGradientEndPoint={ {x : 100, y : 100} }
          fillLinearGradientColorStops={[0, 'rgba(0,0,0,0.7)', 1, 'rgba(255,255,255,0.5)']}
          fillEnabled={true}
          fillPriority='linear-gradient'
          stroke='red'
          strokeWidth={2}
          scaleX={1}
          scaleY={1}
          opacity={1}
        />

    return (
      <React.Fragment>
        { text }
      </React.Fragment>
    );
  }
}

class App extends Component {
render = () => {

  return (
    <React.Fragment>
      <Stage
        ref={node => {
          this.stage = node
        }}
        x={0}
        y={0}
        width={window.innerWidth} 
        height={window.innerHeight}            
      >
        <Layer
          ref={node => {
            this.layer = node
          }}
        >
          <Text2 />
        </Layer>
      </Stage>
    </React.Fragment>
  )
}

export default App

标签: imagetextgradientfillkonvajs

解决方案


线性渐变在您的代码中应该可以正常工作。演示:https ://codesandbox.io/s/ykpmjmynvj

但我发现 Konva 代码中有一个关于图案和径向渐变的错误。它应该在下一个版本中修复。在发布之前,您可以使用此解决方法:

您可以使用外部画布通过 globalCompositeOperation 绘制填充文本。然后将此画布用作Konva.Image.

如何用图像填充画布中的文本?

import React, { Component } from "react";
import { render } from "react-dom";
import { Stage, Layer, Image } from "react-konva";

class Text2 extends React.Component {
  state = {
    text: "Happy New Year!",
    canvas: null
  };

  componentDidMount() {
    var image = new window.Image();
    image.onload = () => {
      const canvas = document.createElement("canvas");
      const ctx = canvas.getContext("2d");

      ctx.save();
      ctx.beginPath();

      // put text on canvas
      ctx.font = "20px Verdana";
      ctx.fillText(this.state.text, 10, 20);
      ctx.fill();

      // use compositing to draw the background image
      // only where the text has been drawn
      ctx.beginPath();
      ctx.globalCompositeOperation = "source-in";
      ctx.drawImage(image, 0, 0);
      ctx.restore();

      this.setState({
        canvas: canvas
      });
    };
    image.src =
      "https://uploads.codesandbox.io/uploads/user/9fa343fe-4c37-4683-bd9c-39d985ca18bb/SHmg-gold-metal-background-02.jpg";
  }

  render = () => {
    return <Image image={this.state.canvas} draggable={true} />;
  };
}

class App extends Component {
  render = () => {
    return (
      <React.Fragment>
        <Stage
          ref={node => {
            this.stage = node;
          }}
          x={0}
          y={0}
          width={window.innerWidth}
          height={window.innerHeight}
        >
          <Layer
            ref={node => {
              this.layer = node;
            }}
          >
            <Text2 />
          </Layer>
        </Stage>
      </React.Fragment>
    );
  };
}

render(<App />, document.getElementById("root"));

https://codesandbox.io/s/xojz9q1k3p


推荐阅读