我正在使用React/Redux并将动画数据存储在JSON中并尝试将其显示在React页面上.
我正在使用setTimeout
(暂停)和setInterval
(用于动画运动).但是,我似乎无法理解如何正确实现动画,并认为我的事情完全是错误的.
JSON数据:
"objects": [
{
"title": "puppy",
"image_set": [
{
"image": "images/puppy_sitting.png",
"startx": 520,
"starty": 28,
"pause": 1000
},
{
"image": "images/puppy_walking.png",
"startx": 520,
"starty": 28,
"endx": 1,
"endy": 1,
"time": 1000
},
{
"image": "images/puppy_crouching.png",
"startx": 1,
"starty": 1,
"endx": 500,
"endy": 400,
"time": 2000
}
]
},
{
"title": "scorpion",
"image_set": [
{
"image": "images/scorping_sleeping.png",
"startx": 100,
"starty": 400,
"pause": 5000
},
{
"image": "images/scorpion_walking.png",
"startx": 100,
"starty": 400,
"endx": 500,
"endy": 400,
"time": 7000
},
{
"image": "images/scorpion_walking.png",
"startx": 500,
"starty": 400,
"endx": 100,
"endy": 400,
"time": 2000
},
{
"image": "images/scorpion_walking.png",
"startx": 100,
"starty": 400,
"endx": 200,
"endy": 400,
"time": 7000
},
{
"image": "images/scorpion_walking.png",
"startx": 200,
"starty": 400,
"endx": 100,
"endy": 400,
"time": 1000
}
]
}
]
每个对象可以有几个与它们相关的图像.动画将继续不间断地重复.每个对象应与其他每个对象同时移动,以便我可以创建各种动物和物体在其周围移动的场景.
动画代码:
我很确定我在这里咆哮错误的树,但我的代码看起来像这样:
// image_set is the list of images for a specific object
// object_num is the array index corresponding to the JSON objects array
// selected is the array index corresponding to which image in the image_set will be displayed
runAnimation(image_set, object_num, selected){
// Uses prevState so that we keep state immutable
this.setState(prevState => {
let images = [...prevState.images];
if (!images[object_num]){
images.push({image: null, x: 0, y: 0})
}
images[object_num].image = image_set[selected].image;
images[object_num].x = this.getFactoredX(image_set[selected].startx);
images[object_num].y = this.getFactoredY(image_set[selected].starty);
return {images: images};
})
if (image_set[selected].endx && image_set[selected].endy && image_set[selected].time){
let x = this.getFactoredX(image_set[selected].startx)
let y = this.getFactoredY(image_set[selected].starty)
let startx = x
let starty = y
let endx = this.getFactoredX(image_set[selected].endx)
let endy = this.getFactoredY(image_set[selected].endy)
let time = image_set[selected].time
let x_increment = (endx - x) / (time / 50)
let y_increment = (endy - y) / (time / 50)
let int = setInterval(function(){
x += x_increment
y += y_increment
if (x > endx || y > endy){
clearInterval(int)
}
this.setState(prevState => {
let images = [...prevState.images]
if (images[object_num]){
images[object_num].x = x
images[object_num].y = y
}
return {images: images};
})
}.bind(this),
50
)
}
if (image_set[selected].pause && image_set[selected].pause > 0){
selected++
if (selected == image_set.length){
selected = 0
}
setTimeout(function() {
this.runAnimation(image_set, object_num, selected)
}.bind(this),
image_set[selected].pause
)
}
else {
selected++
if (selected == image_set.length){
selected = 0
}
setTimeout(function() {
this.runAnimation(image_set, object_num, selected)
}.bind(this),
50
)
}
}
Redux和this.props.data
Redux将数据作为道具引入.所以,我有一个从我的componentDidMount和componentWillReceiveProps函数调用的函数,它将原始图像集传递给loadAnimationFunction.
我的渲染()
在我的render()
功能中,我有这样的事情:
if (this.state.images.length > 1){
animated = this.state.images.map((image, i) => {
let x_coord = image.x
let y_coord = image.y
return (
)
})
}
x_factor/y_factor
在我的代码中,还提到了x和y因子.这是因为动画出现的背景可以缩小或缩小.因此,我还缩放每个动画的起始和结束x/y坐标的位置,以及缩放动画图像本身.
时间和暂停时间
时间表示动画应采用的以ms为单位的时间.暂停时间表示在移动到下一个动画之前要暂停多长时间.
问题
代码不能平滑地移动动画,它们似乎偶尔会跳动.
此外,当我在页面上的任何位置单击鼠标时,它会导致动画跳转到另一个位置.为什么单击鼠标会影响动画?
我注意到的一件事是,如果我打开控制台进行调试,这确实会减慢动画的速度.
我可以对代码执行哪些操作,以便动画按预期工作?
1> Balthazar..:
您尝试使用到动画的元素setInterval
做一个setState
坐标,并用一个absolute
位置.所有这些都无法实现卓越的性能.
首先,setInterval
永远不应该用于动画,你应该更喜欢requestAnimationFrame,因为它将允许60fps动画,因为动画将在下次重新绘制浏览器之前运行.
其次,做一个setState
会重新渲染你的整个组件,这可能会对渲染时间产生影响,因为我认为你的组件不会只渲染你的图像.您应该尽量避免重新渲染未更改的内容,因此请尝试隔离动画中的图像.
最后,当您使用和属性定位元素时,您应该坚持使用,定位,而不是动画,因为浏览器将逐像素地执行动画,并且无法创建良好的性能.相反,你应该使用CSS ,因为它可以进行子像素计算,而不是在GPU上工作,允许你实现60fps的动画.Paul Irish 有一篇很好的文章.left
top
translate()
话虽这么说,你应该使用react-motion来让你获得流畅的动画:
import { Motion, spring } from 'react-motion'
{({ x, y }) => (
)}
还有React Transition Group,Transition可以使用translate
如上所述的动画移动元素.你还应该看看这里的反应动画文档.
值得一试的是React Pose,它非常易于使用,并且在使用干净的API时性能也很好.这是React的入门页面.
这是一个快速演示,使用您的概念与坐/走/跑步循环.请注意,如果没有对转换的持续时间进行硬编码,反应运动是唯一一个处理帧之间转换的方法,这将违背流畅的UI,状态只处理通过不同的步骤.
引用反应动作自述文件:
对于95%的动画组件用例,我们不必使用硬编码的缓动曲线和持续时间.为你的UI元素设置刚度和阻尼,让物理的魔力照顾其余部分.这样,您就不必担心动画行为中断等小情况.它还极大地简化了API.
如果您对默认弹簧不满意,可以更改dampling
和stiffness
参数.有一个应用程序可以帮助您获得最满足您的那个.
Source