在ReactJS中下载带有文本的图片

时间:2019-05-18 22:34:08

标签: javascript reactjs

我为教程创建了一个React应用,它在上传的图片上书写文字。上载图像后的用户键入Top BoxBottom Box,但是当我尝试在用户键入文本后保存图像时,没有显示文本。任何人都可以帮忙,因为我希望图像与文本一起下载。

文件为Header.js,代码为:

import React, {Component} from 'react';
import logo from './logo.svg';
import './App.css';
import CardMedia from '@material-ui/core/CardMedia';
import { withStyles } from '@material-ui/core/styles';
import CardActionArea from '@material-ui/core/CardActionArea';
import { Card, CardContent } from "@material-ui/core";
import IconButton from '@material-ui/core/IconButton';
import PhotoCamera from '@material-ui/icons/PhotoCamera';

const styles = theme => ({
  media: {
      display: 'flex',
      height: 400,
      objectFit: 'contain',
      alignItems: 'center',
  },
})

class Header extends Component {
  render() {
    const {classes} = this.props;
    return(
      <Card >
        <CardContent >
          <div style={{position:'relative'}}>
            <CardMedia
              component="img"
              image = {this.props.imageIn}
            />
            <div style={{position: 'absolute', color: 'white', top: '5%', left: '50%', transform:'translateX(-50%)'}}>
              {this.props.topText}
            </div>

            <div style={{position: 'absolute', color: 'white', bottom: '5%', left: '50%', transform:'translateX(-50%)'}}>
              {this.props.bottomText}
            </div>
          </div>
        </CardContent>
      </Card>

    );
  }
}

export default withStyles(styles)(Header)

App.js为:

import React, {Component} from 'react';
import logo from './logo.svg';
import './App.css';
import CardMedia from '@material-ui/core/CardMedia';
import { withStyles } from '@material-ui/core/styles';
import CardActionArea from '@material-ui/core/CardActionArea';
import { Card, CardContent } from "@material-ui/core";
import Header from './Header';
import Grid from '@material-ui/core/Grid';
import TextField from '@material-ui/core/TextField';
import IconButton from '@material-ui/core/IconButton';
import PhotoCamera from '@material-ui/icons/PhotoCamera';

const styles = (theme) => ({
  input: {
      display: 'none'
  }
});

class App extends Component{
  state = {
    topText: '',
    bottomText: '',
    randomImg: "http://i.imgflip.com/1bij.jpg",
    allImages: [],
    images: []
  }  

  handleChange = (event) => {
    const {name, value} = event.target
    this.setState({ [name]: value })
  }

  handleCapture = ({ target }) => {
    const fileReader = new FileReader();
    const name = target.accept.includes('image') ? 'images' : 'videos';

    fileReader.readAsDataURL(target.files[0]);
    fileReader.onload = (e) => {
        this.setState((prevState) => ({
            [name]: [...prevState[name], e.target.result]
        }));
    };
};

  render() {
    return(
      <div>
        <input
          accept="image/*"
          style={{display: 'none'}}
          id="icon-button-photo"
          onChange={this.handleCapture}
          type="file"
        />
        <label htmlFor="icon-button-photo">
          <IconButton color="primary" component="span">
              <PhotoCamera />
          </IconButton>
        </label>

        <Grid container justify="left" spacing={8}>
          <Grid item xs={12} sm={6}>
            <TextField
              id="standard-name"
              label="Top Text"
              name = "topText"
              value={this.state.topText}
              onChange={this.handleChange}
              margin="normal"
              variant="filled"
            />
          </Grid>

          <Grid item xs={12} sm={6}>
            <TextField
              id="standard-name"
              label="Bottom Text"
              name = "bottomText"
              value={this.state.bottomText}
              onChange={this.handleChange}
              margin="normal"
              variant="filled"
            />
          </Grid>
          <Header topText = {this.state.topText} bottomText = {this.state.bottomText} imageIn = {this.state.images}/>
        </Grid>
      </div>      
    )
  }
}

export default App

3 个答案:

答案 0 :(得分:4)

在您的代码中,文本是不同的元素(以下代码中div的子代):

            <CardMedia
              component="img"
              image = {this.props.imageIn}
            />
            <div style={{position: 'absolute', color: 'white', top: '5%', left: '50%', transform:'translateX(-50%)'}}>
              {this.props.topText}
            </div>

            <div style={{position: 'absolute', color: 'white', bottom: '5%', left: '50%', transform:'translateX(-50%)'}}>
              {this.props.bottomText}
            </div>
          </div>

相反,您可以尝试将文本合并到图像中,例如:

    const canvas = this.refs.canvas;
    const ctx = canvas.getContext("2d");
    const img = this.refs.image;

    img.onload = () => {
      ctx.drawImage(img, 0, 0);
      ctx.font = "40px Courier";
      ctx.fillText(this.props.text, 210, 75); // THIS IS THE PLACE TEXT IS EMBEDDED INTO THE PICTURE
    };

在此代码沙箱链接https://codesandbox.io/s/blazing-sun-e2bgf中,您可以找到一个名为Canvas的简单类,该类使用上述方法,以便在保存文件时可以看到文本。

这里有个问题,我提供的示例没有实质性的UI。您正在使用CardMedia类来获取图像并显示它。但是在我提供的示例中,该方法是通用的。因此,您可以将图像单独放置在卡中。


信用:https://blog.cloudboost.io/using-html5-canvas-with-react-ff7d93f5dc76

答案 1 :(得分:0)

这是我的新手,但是如果您想在图像上放置文字,则可能需要使用z索引。 Z索引:1;将是后div(照片或图片)Z索引:2;将是将div放在顶部的文本。以及alpha不透明度,可将带有文本的div设置为透明。

使用绝对位置将确保它们都位于彼此的顶部。

答案 2 :(得分:0)

使用诸如React之类的DOM操作库无法实现您的要求。您正在尝试使用用于处理DOM的框架在浏览器中进行一些图像编辑和渲染。

您可以将React用于“预览”,但是当实际渲染图像时,您将需要诸如https://imagemagick.org/index.php之类的工具。您可以在此处找到绑定的节点:https://www.npmjs.com/package/gm