1
0
mirror of https://github.com/troisjs/trois.git synced 2024-11-24 04:12:02 +08:00

add slider1

This commit is contained in:
Kevin Levron 2020-09-28 21:03:35 +02:00
parent d698324272
commit d504046f1b
5 changed files with 209 additions and 3 deletions

View File

@ -11,17 +11,17 @@
import Demo1 from './components/demos/Demo1.vue'; import Demo1 from './components/demos/Demo1.vue';
import Demo2 from './components/demos/Demo2.vue'; import Demo2 from './components/demos/Demo2.vue';
import Demo3 from './components/demos/Demo3.vue'; import Demo3 from './components/demos/Demo3.vue';
import Demo4 from './components/demos/Demo4.vue'; import Slider1 from './components/demos/Slider1.vue';
import DemoGLTF from './components/demos/DemoGLTF.vue'; import DemoGLTF from './components/demos/DemoGLTF.vue';
export default { export default {
name: 'App', name: 'App',
components: { components: {
Demo1, Demo2, Demo3, Demo4, DemoGLTF, Demo1, Demo2, Demo3, Slider1, DemoGLTF,
}, },
data() { data() {
return { return {
tests: ['Demo1', 'Demo2', 'Demo3', 'Demo4', 'DemoGLTF'], tests: ['Demo1', 'Demo2', 'Demo3', 'Slider1', 'DemoGLTF'],
test: 'Demo1', test: 'Demo1',
}; };
}, },

View File

@ -0,0 +1,23 @@
<template>
<Slider1 :images="images" />
</template>
<script>
import Slider1 from '../sliders/Slider1.vue';
export default {
components: { Slider1 },
data() {
return {
images: [
{ src: 'https://assets.codepen.io/33787/img1.jpg' },
{ src: 'https://assets.codepen.io/33787/img2.jpg' },
{ src: 'https://assets.codepen.io/33787/img3.jpg' },
{ src: 'https://assets.codepen.io/33787/img4.jpg' },
],
};
},
mounted() {
},
};
</script>

View File

@ -0,0 +1,151 @@
<template>
<Renderer ref="renderer">
<Camera ref="camera" :position="{ z: 150 }"></Camera>
<Scene ref="scene">
</Scene>
</Renderer>
</template>
<script>
import { Object3D } from 'three';
import { gsap, Power4 } from 'gsap';
import { lerp, limit } from '../../tools.js';
import AnimatedPlane from './AnimatedPlane.js';
import useTextures from './useTextures';
export default {
props: {
images: Array,
events: { type: Object, default: () => { return { wheel: true, click: true, keyup: true }; } },
},
setup() {
const { textures, loadTextures } = useTextures();
return {
textures,
loadTextures,
progress: 0,
targetProgress: 0,
};
},
mounted() {
this.three = this.$refs.renderer.three;
if (this.images.length < 2) {
console.error('This slider needs at least 2 images.');
} else {
this.loadTextures(this.images, this.init);
}
},
unmounted() {
document.removeEventListener('click', this.onClick);
document.removeEventListener('keyup', this.onKeyup);
window.removeEventListener('wheel', this.onWheel);
},
methods: {
init() {
this.initScene();
gsap.fromTo(this.plane1.uProgress,
{
value: -2,
},
{
value: 0,
duration: 2.5,
ease: Power4.easeOut,
}
);
if (this.events.click) document.addEventListener('click', this.onClick);
if (this.events.keyup) document.addEventListener('keyup', this.onKeyup);
if (this.events.wheel) window.addEventListener('wheel', this.onWheel);
this.three.onBeforeRender(this.updateProgress);
this.three.onAfterResize(this.onResize);
},
initScene() {
const renderer = this.three.renderer;
const scene = this.$refs.scene.scene;
this.plane1 = new AnimatedPlane({
renderer, screen: this.three.size,
size: 10,
anim: 1,
texture: this.textures[0],
});
this.plane2 = new AnimatedPlane({
renderer, screen: this.three.size,
size: 10,
anim: 2,
texture: this.textures[1],
});
this.setPlanesProgress(0);
this.planes = new Object3D();
this.planes.add(this.plane1.o3d);
this.planes.add(this.plane2.o3d);
scene.add(this.planes);
},
onResize() {
this.plane1.resize();
this.plane2.resize();
},
onWheel(e) {
// e.preventDefault();
if (e.deltaY > 0) {
this.targetProgress = limit(this.targetProgress + 1 / 20, 0, this.images.length - 1);
} else {
this.targetProgress = limit(this.targetProgress - 1 / 20, 0, this.images.length - 1);
}
},
onClick(e) {
if (e.clientY < this.three.size.height / 2) {
this.navPrevious();
} else {
this.navNext();
}
},
onKeyup(e) {
if (e.keyCode === 37 || e.keyCode === 38) {
this.navPrevious();
} else if (e.keyCode === 39 || e.keyCode === 40) {
this.navNext();
}
},
navNext() {
if (Number.isInteger(this.targetProgress)) this.targetProgress += 1;
else this.targetProgress = Math.ceil(this.targetProgress);
this.targetProgress = limit(this.targetProgress, 0, this.images.length - 1);
},
navPrevious() {
if (Number.isInteger(this.targetProgress)) this.targetProgress -= 1;
else this.targetProgress = Math.floor(this.targetProgress);
this.targetProgress = limit(this.targetProgress, 0, this.images.length - 1);
},
updateProgress() {
const progress1 = lerp(this.progress, this.targetProgress, 0.1);
const pdiff = progress1 - this.progress;
if (pdiff === 0) return;
const p0 = this.progress % 1;
const p1 = progress1 % 1;
if ((pdiff > 0 && p1 < p0) || (pdiff < 0 && p0 < p1)) {
const i = Math.floor(progress1);
this.plane1.setTexture(this.textures[i]);
this.plane2.setTexture(this.textures[i + 1]);
}
this.progress = progress1;
this.setPlanesProgress(this.progress % 1);
},
setPlanesProgress(progress) {
this.plane1.uProgress.value = progress;
this.plane2.uProgress.value = -1 + progress;
this.plane1.material.opacity = 1 - progress;
this.plane2.material.opacity = progress;
this.plane1.o3d.position.z = progress;
this.plane2.o3d.position.z = progress - 1;
},
},
};
</script>

View File

@ -0,0 +1,28 @@
import { TextureLoader } from 'three';
export default function useTextures() {
const loader = new TextureLoader();
const textures = [];
const loadTexture = (img, index) => {
return new Promise(resolve => {
loader.load(
img.src,
texture => {
textures[index] = texture;
resolve(texture);
}
);
});
};
const loadTextures = (images, cb) => {
textures.splice(0);
Promise.all(images.map(loadTexture)).then(cb);
};
return {
textures,
loadTextures,
};
};

View File

@ -17,3 +17,7 @@ export function lerpv3(v1, v2, amount) {
v1.y = lerp(v1.y, v2.y, amount); v1.y = lerp(v1.y, v2.y, amount);
v1.z = lerp(v1.z, v2.z, amount); v1.z = lerp(v1.z, v2.z, amount);
}; };
export function limit(val, min, max) {
return val < min ? min : (val > max ? max : val);
};