81 Three.jsはTWEENプラグインを使ってアニメーションを実現します。
概要
実現ケース
ケースビューの住所:http://www.wjceo.com/blog/threejs/2018-03-27/141.htmlは、まず、 を導入する必要がある。私達は対象を具体化して、ケースの中で、二つの補間を作りました。 補間アニメーションは、モデルのロードが完了したら起動する必要があるので、以下の関数の末尾に 補間起動後、 。
Tween.js
は軽量級のJavaScript
ライブラリです。中国語の公式サイトは以下の通りです。http://www.createjs.cc/tweenjs/。このライブラリにより、ある属性が2つの値の間で遷移することが容易に実現され、開始値と終了値の間のすべての中間値が自動的に計算され、このプロセスはtweening
(補間)と呼ばれる。基礎は調べて下さい:Tween.js補間のアニメーションのプラグインは入門します実現ケース
ケースビューの住所:http://www.wjceo.com/blog/threejs/2018-03-27/141.html
Tween.js
プラグインファイル<script src="/lib/js/libs/tween.min.js">script>
tween
とtweenBack
。tween
補間は、position
の属性がどのように1から0に遷移するかを定義し、tweenBack
はちょうど反対である。chain()
方法を使用することによって、この二つの補間を接続することができ、アニメーションが起動されると、プログラムはこの二つの補間サイクルにある。コードの最後に定義されるのはonUpdate
方法であり、この方法は、現在のposition
の値を取得することによって、全頂点のy
軸の位置を再生成する。var position = {
y: 1};
tween = new TWEEN.Tween(position).to({
y: 0}, 5000);
tween.easing(TWEEN.Easing.Sinusoidal.InOut);
var tweenBack = new TWEEN.Tween(position).to({
y: 1}, 5000);
tweenBack.easing(TWEEN.Easing.Sinusoidal.InOut);
tween.chain(tweenBack);
tweenBack.chain(tween);
var count = geometry.getAttribute("position").count;
//
geometry.computeBoundingBox();
var minY = geometry.boundingBox.min.y;
var onUpdate = function () {
var y = this.y;
var arr = [];
for (var i = 0; i < count; i++) {
arr.push(geometry.localPosition[i * 3]);
arr.push((geometry.localPosition[i * 3 + 1]-minY) * y);
arr.push(geometry.localPosition[i * 3 + 2]);
}
geometry.getAttribute("position").array = new Float32Array(arr);
geometry.getAttribute("position").needsUpdate = true;
};
tween.onUpdate(onUpdate);
tweenBack.onUpdate(onUpdate);
tween.start()
を呼び出します。tween.start();
Tween.js
ライブラリにいつすべての補間を更新するかを知らせる必要があります。ですから、更新するたびに、TWEEN.update()
方法を呼び出します。function render() {
TWEEN.update();
renderer.render(scene, camera);
}
ケースコード
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<style type="text/css">
html, body {
margin: 0;
height: 100%;
}
canvas {
display: block;
}
style>
head>
<body onload="draw();">
body>
<script src="/lib/three.js">script>
<script src="/lib/js/loaders/PLYLoader.js">script>
<script src="/lib/js/controls/OrbitControls.js">script>
<script src="/lib/js/libs/stats.min.js">script>
<script src="/lib/js/libs/tween.min.js">script>
<script src="/lib/js/libs/dat.gui.min.js">script>
<script>
var renderer;
function initRender() {
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
//
renderer.setClearColor(0xffffff);
document.body.appendChild(renderer.domElement);
}
var camera;
function initCamera() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 50);
camera.lookAt(new THREE.Vector3(0, 0, 0));
}
var scene;
function initScene() {
scene = new THREE.Scene();
}
// dat.GUI
var gui;
function initGui() {
//
gui = {};
var datGui = new dat.GUI();
// gui ,gui.add( , , , )
}
var light;
function initLight() {
scene.add(new THREE.AmbientLight(0x444444));
light = new THREE.PointLight(0xffffff);
light.position.set(0, 50, 50);
//
light.castShadow = true;
scene.add(light);
}
function initModel() {
//
var helper = new THREE.AxesHelper(50);
scene.add(helper);
var loader = new THREE.PLYLoader();
loader.load("/lib/models/ply/binary/Lucy100k.ply", function (geometry) {
//
geometry.computeVertexNormals();
// ,
var material = new THREE.MeshStandardMaterial({color: 0x0055ff});
var mesh = new THREE.Mesh(geometry, material);
mesh.rotation.y = Math.PI;
mesh.scale.set(0.02, 0.02, 0.02);
scene.add(mesh);
//
var position = geometry.getAttribute("position").array;
geometry.localPosition = [];
for (var i = 0; i < position.length; i++) {
geometry.localPosition.push(position[i]);
}
// tween
initTween(geometry);
});
}
// tween
var tween;
function initTween(geometry) {
var position = {y: 1};
tween = new TWEEN.Tween(position).to({y: 0}, 5000);
tween.easing(TWEEN.Easing.Sinusoidal.InOut);
var tweenBack = new TWEEN.Tween(position).to({y: 1}, 5000);
tweenBack.easing(TWEEN.Easing.Sinusoidal.InOut);
tween.chain(tweenBack);
tweenBack.chain(tween);
var count = geometry.getAttribute("position").count;
//
geometry.computeBoundingBox();
var minY = geometry.boundingBox.min.y;
var onUpdate = function () {
var y = this.y;
var arr = [];
for (var i = 0; i < count; i++) {
arr.push(geometry.localPosition[i * 3]);
arr.push((geometry.localPosition[i * 3 + 1]-minY) * y);
arr.push(geometry.localPosition[i * 3 + 2]);
}
geometry.getAttribute("position").array = new Float32Array(arr);
geometry.getAttribute("position").needsUpdate = true;
};
tween.onUpdate(onUpdate);
tweenBack.onUpdate(onUpdate);
tween.start();
}
//
var stats;
function initStats() {
stats = new Stats();
document.body.appendChild(stats.dom);
}
// , ,
var controls;
function initControls() {
controls = new THREE.OrbitControls(camera, renderer.domElement);
// animate ,
//controls.addEventListener( 'change', render );
//
controls.enableDamping = true;
//
//controls.dampingFactor = 0.25;
//
controls.enableZoom = true;
//
controls.autoRotate = false;
controls.autoRotateSpeed = 0.5;
//
controls.minDistance = 1;
//
controls.maxDistance = 200;
//
controls.enablePan = true;
}
function render() {
TWEEN.update();
renderer.render(scene, camera);
}
//
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
render();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
//
render();
//
stats.update();
controls.update();
requestAnimationFrame(animate);
}
function draw() {
initGui();
initRender();
initScene();
initCamera();
initLight();
initModel();
initControls();
initStats();
animate();
window.onresize = onWindowResize;
}
script>
html>