如何在关键帧之间进行平滑插值?
How do I get a smooth interpolation between keyframes?
我正在尝试为我的 three.js 项目制作一个动画系统。我有一个 json 文件来获取信息。我能够播放动画。但是,在他们需要在某个地方的那一刻,他们移动到那个位置,而不是随着时间的推移慢慢移动到那个位置。 json 文件告诉程序特定对象需要在某个位置。例如:
Json 文件:
{
"right": {
"position": {
"0.0": [0, 0, 0],
"0.25": [0, 1, 0],
"0.5": [1, 1, 0]
}
}
Json 文件告诉你位置,在什么时候,然后是位置。
代码:
for (const [key, value] of Object.entries(json.position.right))
if(seconds === json.position.right[key]) {
obj.position.x = json.right.position[key][0];
obj.position.y = json.right.position[key][1];
obj.position.z = json.right.position[key][2];
}
}
在代码中,我循环遍历 json 文件的右立方体位置(它告诉位置何时发生变化)。如果秒匹配,它会移动到那个位置。
我怎样才能在对象的关键帧之间移动?
示例如下:https://mixed-polyester-a.glitch.me/
这是全部代码:https://glitch.com/edit/#!/mixed-polyester-a
我使用 Blockbench 将模型导出为 .OBJ 文件,将材质导出为 .MTL 文件,将动画导出为 .JSON 文件。
抱歉,如果这听起来令人困惑,我真的不知道如何解释。任何帮助将不胜感激。
Three.js 有 a method called MathUtils.lerp() 取起始位置、结束位置和 [0, 1]
之间的插值。您可以使用它在每一帧上将对象的当前位置补间到其目标位置,如下例所示:
const container = document.getElementById("container");
const ball = document.getElementById("ball");
// Set current positions
let ballPosX = 0;
let ballPosY = 0;
// Set target positions
let ballTargetX = 0;
let ballTargetY = 0;
// Update target positions on click
function onClick(event) {
ballTargetX = event.layerX;
ballTargetY = event.layerY;
//console.log(event);
}
function update() {
// Interpolate current position towards targets
ballPosX = THREE.MathUtils.lerp(ballPosX, ballTargetX, 0.1);
ballPosY = THREE.MathUtils.lerp(ballPosY, ballTargetY, 0.1);
// Apply current position to our object
ball.style.left = ballPosX + "px";
ball.style.top = ballPosY + "px";
requestAnimationFrame(update);
}
container.addEventListener("click", onClick);
update();
#container {
width: 300px;
height: 300px;
background: #ddd;
}
#ball {
width: 10px;
height: 10px;
position: absolute;
top: 0;
left: 0;
background: #f90;
border-radius: 10px;
margin-top: -5px;
margin-left: -5px;
}
<div id="container">
<div id="ball"></div>
</div>
<script src="https://threejs.org/build/three.js"></script>
更新:
为了创建带有关键帧的线性时间轴,我使用 gsap.to()
和关键帧参数将所有位置提供给时间轴。 See here and look up "keyframes" 了解更多详情。您可以在下面的代码演示中看到它的运行情况,不过您需要遍历 JSON 以自行将该数据提供给 GSAP。祝你好运!
// Set position vector
const ballPos = {x: 0, y: 0};
const positions = {
"0.0": [0, 0],
"0.25": [0, 100],
"0.5": [100, 100],
"0.75": [100, 0],
"1.0": [0, 0],
}
const timeline = gsap.to(ballPos, {keyframes: [
{x: positions["0.0"][0], y: positions["0.0"][1], duration: 0.0},
{x: positions["0.25"][0], y: positions["0.25"][1], duration: 0.25},
{x: positions["0.5"][0], y: positions["0.5"][1], duration: 0.25},
{x: positions["0.75"][0], y: positions["0.75"][1], duration: 0.25},
{x: positions["1.0"][0], y: positions["1.0"][1], duration: 0.25},
]});
const container = document.getElementById("container");
const ball = document.getElementById("ball");
let timelineTime = 0;
function update() {
timelineTime += 0.001;
timelineTime %= 1;
timeline.seek(timelineTime);
// Apply current position to our object
ball.style.left = ballPos.x + "px";
ball.style.top = ballPos.y + "px";
requestAnimationFrame(update);
}
update();
#container {
width: 300px;
height: 300px;
background: #ddd;
}
#ball {
width: 10px;
height: 10px;
position: absolute;
top: 0;
left: 0;
background: #f90;
border-radius: 10px;
margin-top: -5px;
margin-left: -5px;
}
<div id="container">
<div id="ball"></div>
</div>
<script src="https://threejs.org/build/three.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.7.1/gsap.min.js"></script>
我正在尝试为我的 three.js 项目制作一个动画系统。我有一个 json 文件来获取信息。我能够播放动画。但是,在他们需要在某个地方的那一刻,他们移动到那个位置,而不是随着时间的推移慢慢移动到那个位置。 json 文件告诉程序特定对象需要在某个位置。例如:
Json 文件:
{
"right": {
"position": {
"0.0": [0, 0, 0],
"0.25": [0, 1, 0],
"0.5": [1, 1, 0]
}
}
Json 文件告诉你位置,在什么时候,然后是位置。
代码:
for (const [key, value] of Object.entries(json.position.right))
if(seconds === json.position.right[key]) {
obj.position.x = json.right.position[key][0];
obj.position.y = json.right.position[key][1];
obj.position.z = json.right.position[key][2];
}
}
在代码中,我循环遍历 json 文件的右立方体位置(它告诉位置何时发生变化)。如果秒匹配,它会移动到那个位置。
我怎样才能在对象的关键帧之间移动?
示例如下:https://mixed-polyester-a.glitch.me/
这是全部代码:https://glitch.com/edit/#!/mixed-polyester-a
我使用 Blockbench 将模型导出为 .OBJ 文件,将材质导出为 .MTL 文件,将动画导出为 .JSON 文件。
抱歉,如果这听起来令人困惑,我真的不知道如何解释。任何帮助将不胜感激。
Three.js 有 a method called MathUtils.lerp() 取起始位置、结束位置和 [0, 1]
之间的插值。您可以使用它在每一帧上将对象的当前位置补间到其目标位置,如下例所示:
const container = document.getElementById("container");
const ball = document.getElementById("ball");
// Set current positions
let ballPosX = 0;
let ballPosY = 0;
// Set target positions
let ballTargetX = 0;
let ballTargetY = 0;
// Update target positions on click
function onClick(event) {
ballTargetX = event.layerX;
ballTargetY = event.layerY;
//console.log(event);
}
function update() {
// Interpolate current position towards targets
ballPosX = THREE.MathUtils.lerp(ballPosX, ballTargetX, 0.1);
ballPosY = THREE.MathUtils.lerp(ballPosY, ballTargetY, 0.1);
// Apply current position to our object
ball.style.left = ballPosX + "px";
ball.style.top = ballPosY + "px";
requestAnimationFrame(update);
}
container.addEventListener("click", onClick);
update();
#container {
width: 300px;
height: 300px;
background: #ddd;
}
#ball {
width: 10px;
height: 10px;
position: absolute;
top: 0;
left: 0;
background: #f90;
border-radius: 10px;
margin-top: -5px;
margin-left: -5px;
}
<div id="container">
<div id="ball"></div>
</div>
<script src="https://threejs.org/build/three.js"></script>
更新:
为了创建带有关键帧的线性时间轴,我使用 gsap.to()
和关键帧参数将所有位置提供给时间轴。 See here and look up "keyframes" 了解更多详情。您可以在下面的代码演示中看到它的运行情况,不过您需要遍历 JSON 以自行将该数据提供给 GSAP。祝你好运!
// Set position vector
const ballPos = {x: 0, y: 0};
const positions = {
"0.0": [0, 0],
"0.25": [0, 100],
"0.5": [100, 100],
"0.75": [100, 0],
"1.0": [0, 0],
}
const timeline = gsap.to(ballPos, {keyframes: [
{x: positions["0.0"][0], y: positions["0.0"][1], duration: 0.0},
{x: positions["0.25"][0], y: positions["0.25"][1], duration: 0.25},
{x: positions["0.5"][0], y: positions["0.5"][1], duration: 0.25},
{x: positions["0.75"][0], y: positions["0.75"][1], duration: 0.25},
{x: positions["1.0"][0], y: positions["1.0"][1], duration: 0.25},
]});
const container = document.getElementById("container");
const ball = document.getElementById("ball");
let timelineTime = 0;
function update() {
timelineTime += 0.001;
timelineTime %= 1;
timeline.seek(timelineTime);
// Apply current position to our object
ball.style.left = ballPos.x + "px";
ball.style.top = ballPos.y + "px";
requestAnimationFrame(update);
}
update();
#container {
width: 300px;
height: 300px;
background: #ddd;
}
#ball {
width: 10px;
height: 10px;
position: absolute;
top: 0;
left: 0;
background: #f90;
border-radius: 10px;
margin-top: -5px;
margin-left: -5px;
}
<div id="container">
<div id="ball"></div>
</div>
<script src="https://threejs.org/build/three.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.7.1/gsap.min.js"></script>