三.js时间线精简版动画不起作用



我正在尝试对文本几何进行动画处理,以形成一个盒子{delay}球体{delay}的形状,然后是一个圆锥体。此外,在过渡时更改颜色。我尝试了以下代码来尝试将初始状态动画化为一个框:

var pointsInsideShape = shapes[0].points.attributes.position.array;
for (i = 0; i < MAX_PARTICLES; i++) {
var tl = new TimelineLite();
tl.from(particleGroup.children[i].position, 2, {
x: pointsInsideShape[ index ++ ],
y: pointsInsideShape[ index ++ ],
z: pointsInsideShape[ index ++ ]
})
}

控制台抛出以下错误:

particleGroup.children[i] is undefined

我检查了particleGroup有对象,但是我收到此错误。我不确定为什么这不起作用。

目前所有的粒子都在中心,我正在尝试将它们动画化以形成球体的形状,然后在下一个形状动画之前延迟,依此类推。最后重复循环。如果有人能指出我正确的方向,将不胜感激。谢谢!

下面是代码:

var renderer, camera, scene, light, shapes, triggers, particleCount, particleGroup,
defaultAnimationSpeed, morphAnimationSpeed, colorToStartWith, textGeometries, loader, typeface,
animationVars;
const MAX_PARTICLES = 100,
PARTICLE_SIZE = .65;
var sts = {
config: function() {
shapes = [{
"geoCode": new THREE.BoxBufferGeometry(13, 13, 13),
"textMat": new THREE.MeshPhongMaterial({
color: 0x029894
}),
"color": 0x029894,
"size": [50, 50, 50]
},
{
"geoCode": new THREE.SphereBufferGeometry(25, 33, 33),
"textMat": new THREE.MeshPhongMaterial({
color: 0x8F3985
}),
"color": 0x8F3985,
"size": [25, 33, 33]
},
{
"geoCode": new THREE.ConeBufferGeometry(25, 50, 30),
"textMat": new THREE.MeshPhongMaterial({
color: 0x11659C
}),
"color": 0x11659C,
"size": [25, 50, 30]
}
];
triggers = document.getElementsByTagName('span');
particleGroup = new THREE.Group();
defaultAnimationSpeed = 1;
morphAnimationSpeed = 18;
normalSpeed = (defaultAnimationSpeed / 100)
fullSpeed = (morphAnimationSpeed / 100)
colorToStartWith = '#8F3985';
textGeometries = new Array();
},
initScene: function() {
//Renderer
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setClearColor(0xffffff, 1);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Scene
scene = new THREE.Scene();
// Camera and position
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.y = -25;
camera.position.z = 45;
camera.rotation.x = -.45;
// Lighting
light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(1, 1, 1).normalize();
scene.add(light);
var light2 = new THREE.DirectionalLight(0xffffff, 1.5);
light2.position.set(0, -1, 0);
scene.add(light2);
// Texts
loader = new THREE.FontLoader();
typeface = 'https://raw.githubusercontent.com/7dir/json-fonts/master/fonts/cyrillic/roboto/Roboto_Regular.json';
//particleGroup
particleGroup = new THREE.Group();
particleGroup.position.x = 0;
particleGroup.position.y = -45;
particleGroup.position.z = 0;
scene.add(particleGroup);
},
fullScreen: function() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
},
attachEvents: function() {
window.addEventListener('resize', this.fullScreen, false);
},
addShapes: function() {
for (idx = 0; idx < shapes.length; idx++) {
shapes[idx].geometry = shapes[idx].geoCode.toNonIndexed();
m = new THREE.MeshLambertMaterial({
color: shapes[idx].color,
opacity: 0,
transparent: true,
wireframe: true
});
shapes[idx].geometry.center();
shape = new THREE.Mesh(shapes[idx].geometry, m);
scene.add(shape);
}
},
computePointsInside: function(idx) {
shapes[idx].points = this.fillWithPoints(shapes[idx].geometry, MAX_PARTICLES);
},
addText: function() {
loader.load(typeface, (font) => {
//var x, y, z, index1, index2;
//x = y = z = index1 = index2 = 0;
var m = new THREE.MeshPhongMaterial({
color: 0x8F3985,
opacity: .8,
specular: 0xffffff,
shininess: 100
});
for (i = 0; i < MAX_PARTICLES; i++) {
g = new THREE.TextGeometry(Math.random() < .5 ? '6' : '9', {
font: font,
size: PARTICLE_SIZE,
height: 0.1
});
var text = new THREE.Mesh(g, m);
text.position.x = 0;
text.position.y = 0;
text.position.z = 0;
text.rotation.x = Math.random() * 2 * Math.PI;
text.rotation.y = Math.random() * 2 * Math.PI;
text.rotation.z = Math.random() * 2 * Math.PI;
text.scale.x = (Math.random() * (0.95 - 0.1) + 0.95).toFixed(4);
text.scale.y = (Math.random() * (0.95 - 0.1) + 0.95).toFixed(4);
text.scale.z = (Math.random() * (0.95 - 0.1) + 0.95).toFixed(4);
//var pointsInsideShape = shapes[0].points.attributes.position.array;
//text.position.x = pointsInsideShape[ index2 ++ ];
//text.position.y = pointsInsideShape[ index2 ++ ];
//text.position.z = pointsInsideShape[ index2 ++ ];
particleGroup.add(text);
}
});
},
animationSequence: function() {
var x, y, z, index;
x = y = z = index = 0;
var pointsInsideShape = shapes[0].points.attributes.position.array;
for (i = 0; i < MAX_PARTICLES; i++) {
var tl = new TimelineLite();
tl.from(particleGroup.children[i].position, 2, {
x: pointsInsideShape[index++],
y: pointsInsideShape[index++],
z: pointsInsideShape[index++]
})
}
},
animate: function() {
window.requestAnimationFrame(sts.animate);
particleGroup.rotation.y += 0.005;
renderer.render(scene, camera)
},
fillWithPoints: function(geometry, count) {
var ray = new THREE.Ray()
var size = new THREE.Vector3();
geometry.computeBoundingBox();
var bbox = geometry.boundingBox;
var points = [];
var dir = new THREE.Vector3(1, 1, 1).normalize();
for (var i = 0; i < count; i++) {
var p = setRandomVector(bbox.min, bbox.max);
points.push(p);
}
function setRandomVector(min, max) {
var v = new THREE.Vector3(
THREE.Math.randFloat(min.x, max.x),
THREE.Math.randFloat(min.y, max.y),
THREE.Math.randFloat(min.z, max.z)
);
if (!isInside(v)) {
return setRandomVector(min, max);
}
return v;
}
function isInside(v) {
ray.set(v, dir);
var counter = 0;
var pos = geometry.attributes.position;
var faces = pos.count / 3;
var vA = new THREE.Vector3(),
vB = new THREE.Vector3(),
vC = new THREE.Vector3();
for (var i = 0; i < faces; i++) {
vA.fromBufferAttribute(pos, i * 3 + 0);
vB.fromBufferAttribute(pos, i * 3 + 1);
vC.fromBufferAttribute(pos, i * 3 + 2);
if (ray.intersectTriangle(vA, vB, vC)) counter++;
}
return counter % 2 == 1;
}
return new THREE.BufferGeometry().setFromPoints(points);
},
init: function() {
this.config();
this.initScene();
this.attachEvents();
this.addShapes();
this.computePointsInside(0);
this.computePointsInside(1);
this.computePointsInside(2);
this.addText();
this.animate();
this.animationSequence();
}
}
sts.init();
body {
margin: 0;
overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/109/three.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.3/TweenMax.min.js" type="text/javascript"></script>

我为animationSequence添加了轻微的延迟

setTimeout(() => this.animationSequence(), 1000);

这不是最好的方法,理想情况下,您会等到particleGroup.children加载数据

经过一番调查,我找到了罪魁祸首。

addText: function() {
loader.load(typeface, (font) => {

将其包装在承诺中

addText: function() {
return new Promise((resolve, reject) => {
loader.load(typeface, (font) => {

使用将其余逻辑放入然后回调

this.addText().then(_ => {
this.animate();
this.animationSequence();
})

工作示例

var renderer, camera, scene, light, shapes, triggers, particleCount, particleGroup,
defaultAnimationSpeed, morphAnimationSpeed, colorToStartWith, textGeometries, loader, typeface,
animationVars;
const MAX_PARTICLES = 100, PARTICLE_SIZE = .65;
var sts = {
config: function() {
shapes = [
{
"geoCode": new THREE.BoxBufferGeometry(13, 13, 13),
"textMat": new THREE.MeshPhongMaterial({ color: 0x029894 }),
"color": 0x029894,
"size": [50, 50, 50]
},
{
"geoCode": new THREE.SphereBufferGeometry(25, 33, 33),
"textMat": new THREE.MeshPhongMaterial({ color: 0x8F3985 }),
"color": 0x8F3985,
"size": [25, 33, 33]
},
{
"geoCode": new THREE.ConeBufferGeometry(25, 50, 30),
"textMat": new THREE.MeshPhongMaterial({ color: 0x11659C }),
"color": 0x11659C,
"size": [25, 50, 30]
}
];
triggers = document.getElementsByTagName('span');
particleGroup = new THREE.Group();
defaultAnimationSpeed = 1;
morphAnimationSpeed = 18;
normalSpeed = (defaultAnimationSpeed / 100),
fullSpeed = (morphAnimationSpeed / 100)
colorToStartWith = '#8F3985';
textGeometries = new Array();
},
initScene: function() {
//Renderer
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setClearColor(0xffffff, 1);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Scene
scene = new THREE.Scene();
// Camera and position
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.y = -25;
camera.position.z = 45;
camera.rotation.x = -.45;
// Lighting
light = new THREE.DirectionalLight( 0xffffff, 1 );
		light.position.set( 1, 1, 1 ).normalize();
scene.add(light);
		var light2 = new THREE.DirectionalLight( 0xffffff, 1.5 );
		light2.position.set( 0, - 1, 0 );
		scene.add( light2 );
// Texts
loader = new THREE.FontLoader();
typeface = 'https://raw.githubusercontent.com/7dir/json-fonts/master/fonts/cyrillic/roboto/Roboto_Regular.json';
//particleGroup
particleGroup = new THREE.Group();
particleGroup.position.x = 0;
particleGroup.position.y = -45;
particleGroup.position.z = 0;
scene.add(particleGroup);
},
fullScreen: function() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
},
attachEvents: function() {
window.addEventListener('resize', this.fullScreen, false);
},
addShapes: function() {
for (idx = 0; idx < shapes.length; idx++) {
shapes[idx].geometry = shapes[idx].geoCode.toNonIndexed();
m = new THREE.MeshLambertMaterial({
color: shapes[idx].color,
opacity: 0,
transparent: true,
wireframe: true
});
shapes[idx].geometry.center();
shape = new THREE.Mesh(shapes[idx].geometry, m);
scene.add(shape);
}
},
computePointsInside: function(idx) {
shapes[idx].points = this.fillWithPoints(shapes[idx].geometry, MAX_PARTICLES);
},
addText: function() {
return new Promise((resolve, reject) => {
loader.load(typeface, (font) => {
//var x, y, z, index1, index2;
//x = y = z = index1 = index2 = 0;
var m = new THREE.MeshPhongMaterial({color: 0x8F3985, opacity: .8, specular: 0xffffff, shininess: 100});
for (i = 0; i < MAX_PARTICLES; i++) {
g = new THREE.TextGeometry( Math.random() < .5 ? '6' : '9', {
font: font,
size: PARTICLE_SIZE,
height: 0.1
});
var text = new THREE.Mesh(g, m);
text.position.x = 0;
text.position.y = 0;
text.position.z = 0;
text.rotation.x = Math.random() * 2 * Math.PI;
text.rotation.y = Math.random() * 2 * Math.PI;
text.rotation.z = Math.random() * 2 * Math.PI;
text.scale.x = (Math.random() * (0.95 - 0.1) + 0.95).toFixed(4);
text.scale.y = (Math.random() * (0.95 - 0.1) + 0.95).toFixed(4);
text.scale.z = (Math.random() * (0.95 - 0.1) + 0.95).toFixed(4);
//var pointsInsideShape = shapes[0].points.attributes.position.array;
//text.position.x = pointsInsideShape[ index2 ++ ];
//text.position.y = pointsInsideShape[ index2 ++ ];
//text.position.z = pointsInsideShape[ index2 ++ ];
particleGroup.add(text);
}
resolve();
});
})
},
animationSequence: function() {
var x, y, z, index;
x = y = z = index = 0;

const children = particleGroup.children;

var pointsInsideShape = shapes[0].points.attributes.position.array;
for (i = 0; i < MAX_PARTICLES; i++) {
var tl = new TimelineLite();
const child = children[i];

tl.from(child.position, 2, {
x: pointsInsideShape[ index ++ ],
y: pointsInsideShape[ index ++ ],
z: pointsInsideShape[ index ++ ]
})
}
},
animate: function() {
window.requestAnimationFrame(sts.animate);
particleGroup.rotation.y +=0.005;
renderer.render(scene, camera)
},
fillWithPoints: function(geometry, count) {

var ray = new THREE.Ray()

var size = new THREE.Vector3();
geometry.computeBoundingBox();
var bbox = geometry.boundingBox;

var points = [];

var dir = new THREE.Vector3(1, 1, 1).normalize();
for (var i = 0; i < count; i++) {
var p = setRandomVector(bbox.min, bbox.max);
points.push(p);
}

function setRandomVector(min, max){
var v = new THREE.Vector3(
THREE.Math.randFloat(min.x, max.x),
THREE.Math.randFloat(min.y, max.y),
THREE.Math.randFloat(min.z, max.z)
);
if (!isInside(v)){return setRandomVector(min, max);}
return v;
}

function isInside(v){

ray.set(v, dir);
var counter = 0;
var pos = geometry.attributes.position;
var faces = pos.count / 3;
var vA = new THREE.Vector3(), vB = new THREE.Vector3(), vC = new THREE.Vector3();

for(var i = 0; i < faces; i++){
vA.fromBufferAttribute(pos, i * 3 + 0);
vB.fromBufferAttribute(pos, i * 3 + 1);
vC.fromBufferAttribute(pos, i * 3 + 2);
if (ray.intersectTriangle(vA, vB, vC)) counter++;
}

return counter % 2 == 1;
}

return new THREE.BufferGeometry().setFromPoints(points);
},
init: function() {
this.config();
this.initScene();
this.attachEvents();
this.addShapes();
this.computePointsInside(0);
this.computePointsInside(1);
this.computePointsInside(2);
this.addText().then(_ => {
this.animate();
this.animationSequence();
})
}
}
sts.init();
body {
margin: 0;
overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/109/three.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.3/TweenMax.min.js" type="text/javascript"></script>

最新更新