Анимация ReactCSSTransition не гладкая для изображения

Я попытался реализовать анимацию постепенного появления / исчезновения в React с использованием ReactCSSTransitionGroup. Я следовал этому решению в предыдущих SO ответах. У меня есть компонент, который содержит изображение и текст. Анимация плавная для текста, но не для изображения. Похоже, изображение мерцает во время анимации.

jsfiddle

JS

var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;

var items = [
    {id: 1, text: "item1", img: "https://mirrors.creativecommons.org/presskit/icons/cc.large.png"},
  {id: 2, text: "item2", img: "https://mirrors.creativecommons.org/presskit/icons/by.large.png"},
  {id: 3, text: "item3", img: "https://mirrors.creativecommons.org/presskit/icons/nc.large.png"},
  {id: 4, text: "item4", img: "https://mirrors.creativecommons.org/presskit/icons/nc-eu.large.png"},
]

function findObjectByKey(array, key, value) {
    for (var i = 0; i < array.length; i++) {
        if (array[i][key] === value) {
            return array[i];
        }
    }
    return null;
}

var SwitchContent = React.createClass({
    render: function() {
        var obj = findObjectByKey(items, 'id', this.props.id);
        console.log(obj);

        return (
            <div>
        <style
            dangerouslySetInnerHTML={{
              __html: [
                '.backgroundImg {',
                '  background: url('+obj.img+');',
                '  background-size: auto 100px;',
                '}',
              ].join('\n'),
            }}
          />
         <div className="backgroundImg" />
         <div className="textContent">{obj.text}</div>
      </div> 
        );

    }
});

var Switch = React.createClass({
    getInitialState: function() {
        return {
            id: 1,
        };
    },
    toggle: function(e) {
        this.setState({ id: this.state.id === 4 ? 1 : this.state.id + 1 });
    },
    render: function() {
        var key = this.state.id;

        return (
            <div>
              <button onClick={this.toggle}>Toggle</button>
              <ReactCSSTransitionGroup
              transitionAppear
        transitionAppearTimeout={500}
        transitionLeaveTimeout={500}
        transitionEnterTimeout={500}
              className="container"
              transitionName="example">
                <div key={key} className="item_container">
                  <SwitchContent id={key} />
                </div>
              </ReactCSSTransitionGroup>
            </div>
        );

    }
});

React.render(<Switch/>, document.getElementById("switch"));

CSS

.backgroundImg {
  background-repeat: no-repeat;
  background-position: center center;
  background-color: black;
  width: 100px;
  height: 100px;
}

.container {
    position: relative;
}
.container > div {
    position: absolute;
}
.button {
    display: block;
    height: 100px;
    width: 100px;
    border: 1px solid #aaa;
    border-radius: 25px;
    font: bold 20px Helvetica, Arial, sans-serif;
    text-align: center;
    line-height: 100px;
    cursor: pointer;
    color: #fff;
    background-color: #000;
    /* Define transition on the "opacity" property. */    
    transition: opacity 0.5s ease-in;
}
.example-enter {
  opacity: 0.01;
}

.example-enter.example-enter-active {
  opacity: 1;
  transition: opacity 500ms ease-in;
}

.example-leave {
  opacity: 1;
}

.example-leave.example-leave-active {
  opacity: 0.01;
  transition: opacity 500ms ease-in;
}

2 ответа

Решение

Попробуйте установить transition-delay значение для .example-enter.example-enter-active Класс CSS и ease-in-out как transition-timing-function:

.example-enter.example-enter-active {
    opacity: 1;
    transition: opacity 500ms ease-in-out 500ms;
}

.example-leave.example-leave-active {
   opacity: 0.01;
   transition: opacity 500ms ease-in-out;
 }

Выглядит так гладко. Разветвленный JSFiddle

Не уверен, что именно происходит в вашей скрипке, и почему выглядит, как будто следующее изображение не ослабевает.

Я, однако, переписал ваш пример в последней реакции и с использованием генераторов, и все, кажется, работает нормально.

Вы пропустили классы с примерами, но я думаю, что это еще не все. Вы можете посмотреть мою песочницу здесь: https://codesandbox.io/s/zw0xv4vy3x

Если, основываясь на этом рабочем примере, вы сможете выяснить, что не так с вашим, то отлично! Если нет, просто скопируйте и вставьте, и вы должны быть хорошими.

JS

import React, { Component } from "react";
import ReactCSSTransitionGroup from "react-addons-css-transition-group";
import { render } from "react-dom";
import "./main.css";

function* continuosArrayIterator(arr) {
  let idx = 0;
  while (idx < arr.length) {
    let ret = arr[idx];
    idx++;
    if (idx === arr.length) {
      idx = 0;
    }
    yield ret;
  }
}

class App extends Component {
  constructor() {
    super();
    this.clickHandler = this.clickHandler.bind(this);
    this.items = [
      {
        id: 1,
        text: "item1",
        img: "https://mirrors.creativecommons.org/presskit/icons/cc.large.png"
      },
      {
        id: 2,
        text: "item2",
        img: "https://mirrors.creativecommons.org/presskit/icons/by.large.png"
      },
      {
        id: 3,
        text: "item3",
        img: "https://mirrors.creativecommons.org/presskit/icons/nc.large.png"
      },
      {
        id: 4,
        text: "item4",
        img:
          "https://mirrors.creativecommons.org/presskit/icons/nc-eu.large.png"
      }
    ];
    this.imageIterator = continuosArrayIterator(this.items);
    this.state = {
      image: this.imageIterator.next().value
    };
  }

  clickHandler(event) {
    return this.setState({
      image: this.imageIterator.next().value
    });
  }

  render() {
    return (
      <div>
        <button onClick={this.clickHandler}>Next Image</button>
        <ReactCSSTransitionGroup
          transitionAppear={true}
          transitionLeaveTimeout={500}
          transitionEnterTimeout={500}
          className="container"
          transitionName="example"
        >
          <div
            key={this.state.image.id}
            style={{
              position: "absolute",
              backgroundImage: `url(${this.state.image.img}`,
              backgroundSize: "auto 100px",
              height: "100px",
              width: "100px"
            }}
          />
        </ReactCSSTransitionGroup>
      </div>
    );
  }
}

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

CSS

.container {
  position: absolute;
}

.example-enter {
  opacity: 0.01;
}

.example-enter.example-enter-active {
  opacity: 1;
  transition: opacity 500ms ease-in;
}

.example-leave {
  opacity: 1;
}

.example-leave.example-leave-active {
  opacity: 0.01;
  transition: opacity 500ms ease-in;
}

.example-appear {
  opacity: 0.01;
}

.example-appear.example-appear-active {
  opacity: 1;
  transition: opacity 0.5s ease-in;
}
Другие вопросы по тегам