Оригинално видео: https://youtu.be/IjiE3bRdMTk

В днешния епизод ще продължим нашия курс по three.js, като импортираме експортиран блендер файл в нашия проект Webflow.

Преди няколко седмици разгледахме „как да съхранявате вашите външни активи на Webflow“, това може да е CSS, JavaScript. В този случай ние ще качим нашите Blender файлове или по-конкретно нашите GLTF файлове в тези външни хранилища и след това ще ги импортираме в нашата three.js сцена.

3D типове файлове

Когато става въпрос за three.js и 3D като цяло, има буквално стотици различни типове файлове и всички те имат своите различни плюсове и минуси. Някои от тях се основават на производителността, някои от тях буквално каква информация се съдържа в тези файлове. Много от тях се съхраняват във формат JSON, независимо дали вграждате текстурите или препращате към външни.

Става разхвърляно.

Ще използваме стандарт, който е придобил голяма популярност, много, много части от софтуерната поддръжка и ще го експортираме. Просто изглежда, че е 1 размер, подходящ за всички за много ситуации. Но просто знайте, че ако навлезете по-дълбоко в кода three.js, ще бъдете по-чувствителни към това какви файлови типове използвате за различни различни обстоятелства. За нашите намерения и цели GLTF ще бъде файловият тип, който ще използваме за нашия проект. Това не е непременно най-доброто решение, но това е, с което ще се спрем, защото е най-лесното за работа.

GLTFLoader

Трябва да заредим товарача, който отговаря за зареждането на GLTF файлове. Това всъщност е голям код, поради което трябва да импортираме отделен модул, който да ни позволи да направим това.

В нашите импортирания тук искаме да добавим нов ред код и да съпоставим „three/addons“ към...

https://unpkg.com/three@<version>/examples/jsm/

Ще искате да замените ‹version›, който съответства на версията three.js, която използвате (ние използваме 0.149.0)

Net трябва действително да го заредим.

import { GLTFLoader } from "three/addons/loaders/GLTFLoader";

Three.js редактор

Няма да разглеждаме как да експортирате вашите GLTF файлове от блендер. Вместо това следвайте този урок, но това, което смятате, че си струва да се спомене е, че ако отидете на threejs.org/editor. Можете да импортирате вашите файлове в този много основен редактор three.js. Това е добър начин да проверите дали файлът наистина работи. Можете също така да манипулирате нещата, да добавяте нови материали или просто да променяте позициите на нещата. three.js редакторът е наистина добър начин просто да добавите последните щрихи към вашия файл или може би да го промените, без да намесвате дизайнер.

GLTF трансформация

GLTF Transform компресира и оптимизира вашите GLTF файлове, за да ги направи по-малки и различни други неща. Използвам го основно за компресиране на текстури на Webp. Така че след като инсталирате CLI инструмента, можете да компресирате файла още повече.

gltf-transform webp [LINK-TO-FILE]

Взех нашите примерни модели на Fox the Kronos Group и избрах този 1, защото има някои анимации, свързани с него. Качих това в AWS и получих публичната връзка. Вижте другия ни видеоклип за избор на услуга за съхранение.

Зареждане на нашия GLTF файл

Ще създадем функция, наречена loadFox, и ще я извикаме от нашия конструктор.

// constructor 
this.loadFox() 
// class level 
loadFox() { }

След това трябва да създадем екземпляр GLTF loader и да заредим нашата лисица с метода за зареждане и да поставим нашия URL към нашия GLTF файл.

// loadFox 
const gltfLoader = new GLTFLoader() 
gltfLoader.load('<url-to-asset>')

Получаваме достъп до 3 функции. Първата функция е върху успеха на натоварването. Втората функция ще бъде прогрес и това може да е удобно за лента за зареждане. Третият 1 ще бъде на грешката.

Във функцията за успех получаваме достъп до обекта, който се зарежда. Регистриране на обекта, това е, с което ще работим. Това е лисицата.

gltfLoader.load( '<url-to-asset>', 
  (gltf) => console.log('success', gltf), 
  () => console.log('progress'), 
  () => console.log('error'))

Добавяне към нашата сцена

Все още няма да го видите на нашия екран, защото не сме заредили в нашата сцена, както трябва да правите с всеки отделен three.js обект, но нека просто да погледнем обекта, преди да направим това. Можете да видите, че имаме анимации, с които да играем, камери, сцени и отделни обекти. Имате достъп до всичко, което бихте очаквали, така че ако искате да знаете мащаба, ако искате да манипулирате мащаба, можете да третирате това като всеки друг обект сега, сякаш е създаден вътре в three.js.

Нека сега го добавим към нашата сцена.

this.scene.add(gltf.scene)

Трябва също да добавим малко светлини. Така че просто ще добавим малко околни светлини. Околната светлина е просто светлина от всички посоки.

// constructor 
this.addLights(); 
// class-level 
addLights() { 
  const ambientLight = new THREE.AmbientLight() 
  this.scene.add(ambientLight) 
}

И сега можете да видите нашата лисица. И то е огромно.

Групи

Искаме Лисицата да изглежда така, сякаш стои върху нашата кутия, докато се движи, така че ще увием и двете в група.

Нека да сортираме мащаба на тази лисица засега.

gltf.scene.scale.set(0.03, 0.03, 0.03)

Това е по-управляем размер. Сега ще създадем нашата група за кутията.

// createBox 
this.group = new THREE.Group() 
// + 
this.group.add(this.box) 
this.scene.add(this.group) 
// - this.scene.add(this.box)

При опресняване не трябва да виждате промени. перфектен А сега отиваме при тази лисица в групата и ще преместим тази лисица малко нагоре.

// addFox 
// + 
gltf.scene.position.y = 0.5 
this.group.add(gltf.scene) 
// - this.scene.add(gltf.scene)

Сега ще искаме да завъртим групата вместо само кутията, което е напълно практично.

// animate 
// + 
gsap.to(this.group.rotation, { 
// - gsap.to(this.box.rotation, ( ...

Миксер за анимация

Нека сега да разгледаме анимациите, до които имаме достъп във файла fox GLTF.

За да можем да избледняваме между анимациите, имаме нужда от миксер и да добавим нашия GLTF файл към него, тъй като той съдържа анимациите.

gltf.load('<asset>', (gltf) => { 
  // success method 
  this.mixer = new THREE.AnimationMixer(gltf.scene) 
})

Сега ще препращаме към отделните действия, които са в масив, за да можем да ги смесваме и след това да възпроизведем първото действие.

// gltf success method 
this.mixer = new THREE.AnimationMixer(gltf.scene) 
this.action1 = this.mixer.clipAction(gltf.animations[0]) 
this.action2 = this.mixer.clipAction(gltf.animations[1]) 
this.action1.play()

Това, което ще забележите, че нищо не се случва и това е, защото трябва да актуализираме миксера с всяка отметка на анимацията. Първо трябва да създадем часовник, за да проследяваме изминалото време и да използваме делта, за да актуализираме миксера.

// constructor 
this.clock = new THREE.Clock() 

// animate 
if (this.mixer) { 
  this.mixer.update(this.clock.getDelta()) 
}

Вече имаме нещо, което се играе!

Смесване между анимации

За да можем да смесваме между други анимации, трябва да избледняваме между различните действия, като проследяваме действието, което се изпълнява в момента. Ето една функция, която намерих. Това, което прави, изисква ново действие и продължителност, която е предварително зададена на 0,2 секунди

// class-level 
fadeToAction(action, duration = 0.2) { }

Трябва да зададем текущо активно действие, за да зададем предишното действие и да подредим ново действие.

Когато за първи път зареждаме лисицата, трябва да зададем първия актон като текущо изпълняващо се действие и да го изиграем вместо това. Трябва да видим, че всичко работи както преди.

// gltf success method 
this.mixer = new THREE.AnimationMixer(gltf.scene) 
this.action1 = this.mixer.clipAction(gltf.animations[0]) 
this.action2 = this.mixer.clipAction(gltf.animations[1]) 
// + 
this.activeAction = this.action1 
this.activeAction.play() 
// - this.action1.play()

Сега проследяваме активното в момента действие, можем да зададем новото действие вътре в метода за избледняване като това, което е преминало и да избледнеем предишното currentAction за дадена продължителност.

След това трябва да избледнеем в newAction.

fadeToAction(action, duration = 0.2) { 
  const previousAction = this.activeAction
  this.activeAction = action
 
  if (previousAction !== this.activeAction) {
    previousAction.fadeOut(duration)
  } 

  this.activeAction.reset()
    .setEffectiveTimeScale(1)
    .setEffectiveWeight(1)
    .fadeIn(duration)
    .play() 
}

Сега просто трябва да извикаме тази функция и да предадем ново действие, където трябва да избледнеем до нова анимация, независимо дали това е с щракване или друго.

// setEvents 
const titles = Array.from(document.querySelectorAll("h2"))
titles.forEach((title) => {
  title.addEventListener("mouseover", () => {
    this.fadeToAction(this.action2)
    this.isHovering = true
  })
  title.addEventListener("mouseleave", () => {
    this.fadeToAction(this.action1)
    this.isHovering = false
  })
})

Вижте „крайния код“ тук.

Първоначално публикувано на адрес https://thefullstackagency.xyz на 4 май 2023 г.