Анимация ReactCSSTransition не гладкая для изображения
Я попытался реализовать анимацию постепенного появления / исчезновения в React с использованием ReactCSSTransitionGroup. Я следовал этому решению в предыдущих SO ответах. У меня есть компонент, который содержит изображение и текст. Анимация плавная для текста, но не для изображения. Похоже, изображение мерцает во время анимации.
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;
}