【问题标题】:Reload Live Image without Flickering in React在 React 中重新加载实时图像而不闪烁
【发布时间】:2018-09-26 21:04:34
【问题描述】:

我想在 React 中无限期地重新加载静态 URL 上的图像。通过一些搜索,我得出了以下不太理想的解决方案。它有效,但我想消除图像加载的闪烁。我意识到问题是组件被重新渲染,然后图像加载。我见过几个例子,它们使用两张图片,一张作为占位符,加载一张隐藏,直到它使用onLoadsetState 加载,但它们都假设图像数量有限。我怎样才能使这个显示在CardMedia 中的最后一个图像,直到新的图像被加载然后每五秒更换一次而不闪烁?

import React from 'react';
import ReactDOM from 'react-dom';

import { Card, CardMedia, CardTitle } from 'react-toolbox/lib/card';

const LIVE_IMAGE = 'https://cdn-images-1.medium.com/max/1600/1*oi8WLwC2u0EEI1j9uKmwWg.png';

class LiveImageCard extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      liveImage: null
    };
  }

  componentDidMount() {
    this.interval = setInterval(
      () => this.setState({
        liveImage: `${LIVE_IMAGE}?${new Date().getTime()}`,
      }),
      5000
    );
  }
  componentWillUnmount() {
    clearInterval(this.interval);
  }

  render() {

    return (
      <Card style={{width: '350px'}}>
        <CardTitle title="Live Image" />
        <CardMedia
          aspectRatio="wide"
          image={this.state.liveImage}
        />
      </Card>
    );
  }
}

ReactDOM.render(
  <LiveImageCard />,
  document.getElementById('root'),
);

【问题讨论】:

  • 问题来自这样一个事实,即当图像开始加载(但未完全加载)时,您正在切换 CardMedia 中的图像源。您的 Card Media 组件应该为您处理,否则您将不得不自己编写并在图像开始加载和交换 HTML img 源之间使用中间 1s 超时:stackoverflow.com/questions/5438612/…
  • 感谢您的回复,但您的评论掩盖了问题。我已经尝试了多种方法来执行您的建议,但都没有奏效。例如,按照你的建议,我可以让我的 setInterval 函数类似于 const img = new Image(); img.onload = () =&gt; this.setState({ liveImage: img }); img.src = `${LIVE_IMAGE}?${new Date().getTime()}`; this.setState({ temp: img }); 但 React 或 React-Toolbox 不喜欢在 Image 属性中使用 Image 对象。

标签: javascript reactjs react-toolbox


【解决方案1】:

不确定这是否是最佳解决方案,但我最终解决了这个问题,并且它可以让您看不到闪烁。

import React from 'react';
import ReactDOM from 'react-dom';

import { Card, CardMedia, CardTitle } from 'react-toolbox/lib/card';

const LIVE_IMAGE = 'https://cdn-images-1.medium.com/max/1600/1*oi8WLwC2u0EEI1j9uKmwWg.png';

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

    this.loadImage = () => {
      const component = this;

      const img = new Image();
      img.crossOrigin = "Anonymous";
      img.onload = function () {
        var canvas = document.createElement("canvas");
        canvas.width =this.width;
        canvas.height =this.height;

        var ctx = canvas.getContext("2d");
        ctx.drawImage(this, 0, 0);

        var dataURL = canvas.toDataURL("image/png");
        component.setState({liveImage: dataURL});
      };

      img.src = `${LIVE_IMAGE}?${new Date().getTime()}`;
      this.setState({ loadingImage: img });
    }

    this.state = {
      loadingImage: null,
      liveImage: null
    };
  }


  componentDidMount() {
    this.loadImage();
    this.interval = setInterval(this.loadImage, 5000);
  }
  componentWillUnmount() {
    clearInterval(this.interval);
  }

  render() {

    return (
      <Card style={{width: '350px'}}>
        <CardTitle title="Live Image" />
        <CardMedia
          aspectRatio="wide"
          image={this.state.liveImage}
        />
      </Card>
    );
  }
}

ReactDOM.render(
  <LiveImageCard />,
  document.getElementById('root'),
);

或者作为没有 React-Toolbox 的独立组件

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

    this.loadImage = () => {
      const component = this;

      const img = new Image();
      img.crossOrigin = "Anonymous";
      img.onload = function () {
        var canvas = document.createElement("canvas");
        canvas.width =this.width;
        canvas.height =this.height;

        var ctx = canvas.getContext("2d");
        ctx.drawImage(this, 0, 0);

        var dataURL = canvas.toDataURL("image/png");
        component.setState({liveImage: dataURL});
      };

      img.src = `${this.props.image}?${new Date().getTime()}`;
      this.setState({ loadingImage: img });
    }

    this.state = {
      loadingImage: null,
      liveImage: null
    };
  }

  componentDidMount() {
    this.loadImage();
    this.interval = setInterval(this.loadImage, this.props.interval);
  }
  componentWillUnmount() {
    clearInterval(this.interval);
  }

  render() {
    return (
      <img src={this.state.liveImage} {...this.props} />
    );
  }
}

【讨论】:

  • 您能解释一下它为什么有效吗?我正在尝试在 React-Native 中做同样的事情。提前致谢。
  • @OlivierMATROT 我们可以使用这个组件在安卓设备上解决这个问题。 npmjs.com/package/react-native-no-flicker-image
【解决方案2】:

对我来说,删除 &lt;Image&gt; 道具,resizeMode={"contain"} 解决了 Android 上的闪烁问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-19
    • 1970-01-01
    • 2018-12-14
    相关资源
    最近更新 更多