ReactCSSTransition 动画对图像不流畅
ReactCSSTransition animation isn't smooth for image
我尝试使用 ReactCSSTransitionGroup. I followed this 之前的 SO 答案在 React 中实现淡出 in/fade 动画。我有一个包含图像和文本的组件。动画对于文本来说是流畅的,但对于图像来说就不是这样了。看起来在动画过程中图像闪烁。
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;
}
尝试将 .example-enter.example-enter-active
CSS class 和 ease-in-out
的 transition-delay
值设置为 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
不确定您的 fiddle 到底发生了什么,以及为什么下一张图片看起来没有缓和。
不过,我确实在最新的 React 中重写了您的示例并使用生成器,一切似乎都正常。
您错过了示例 类,但我认为还有更多内容。
你可以在这里查看我的沙箱: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;
}
我尝试使用 ReactCSSTransitionGroup. I followed this
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;
}
尝试将 .example-enter.example-enter-active
CSS class 和 ease-in-out
的 transition-delay
值设置为 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
不确定您的 fiddle 到底发生了什么,以及为什么下一张图片看起来没有缓和。
不过,我确实在最新的 React 中重写了您的示例并使用生成器,一切似乎都正常。
您错过了示例 类,但我认为还有更多内容。 你可以在这里查看我的沙箱: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;
}