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

update demos

This commit is contained in:
Kevin Levron 2020-10-07 23:52:53 +02:00
parent ece3164f22
commit 6be8406c8f
11 changed files with 316 additions and 23 deletions

File diff suppressed because one or more lines are too long

View File

@ -9,7 +9,7 @@
</head>
<body>
<div id="app"></div>
<script type="module" src="index.26cced0d.js"></script>
<script type="module" src="index.52f7a901.js"></script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-178028522-1"></script>

View File

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

View File

@ -10,14 +10,12 @@ export default {
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' },
{ src: 'https://troisjs.github.io/trois/images/img1.jpg' },
{ src: 'https://troisjs.github.io/trois/images/img2.jpg' },
{ src: 'https://troisjs.github.io/trois/images/img3.jpg' },
{ src: 'https://troisjs.github.io/trois/images/img4.jpg' },
],
};
},
mounted() {
},
};
</script>

View File

@ -0,0 +1,22 @@
<template>
<Slider2 :images="images" />
</template>
<script>
import Slider2 from '../sliders/Slider2.vue';
export default {
components: { Slider2 },
data() {
return {
images: [
{ src: 'https://troisjs.github.io/trois/images/img10.jpg' },
{ src: 'https://troisjs.github.io/trois/images/img6.jpg' },
{ src: 'https://troisjs.github.io/trois/images/img7.jpg' },
{ src: 'https://troisjs.github.io/trois/images/img8.jpg' },
{ src: 'https://troisjs.github.io/trois/images/img2.jpg' },
],
};
},
};
</script>

View File

@ -9,7 +9,7 @@
<script>
import { Object3D } from 'three';
import { gsap, Power4 } from 'gsap';
import { lerp, limit } from '../../tools.js';
import { lerp } from '../../tools.js';
import AnimatedPlane from './AnimatedPlane.js';
import useTextures from '../../use/useTextures';
@ -93,9 +93,9 @@ export default {
onWheel(e) {
// e.preventDefault();
if (e.deltaY > 0) {
this.targetProgress = limit(this.targetProgress + 1 / 20, 0, this.images.length - 1);
this.setTargetProgress(this.targetProgress + 1 / 20);
} else {
this.targetProgress = limit(this.targetProgress - 1 / 20, 0, this.images.length - 1);
this.setTargetProgress(this.targetProgress - 1 / 20);
}
},
onClick(e) {
@ -113,14 +113,19 @@ export default {
}
},
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);
if (Number.isInteger(this.targetProgress)) this.setTargetProgress(this.targetProgress + 1);
else this.setTargetProgress(Math.ceil(this.targetProgress));
},
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);
if (Number.isInteger(this.targetProgress)) this.setTargetProgress(this.targetProgress - 1);
else this.setTargetProgress(Math.floor(this.targetProgress));
},
setTargetProgress(value) {
this.targetProgress = value;
if (this.targetProgress < 0) {
this.progress += this.images.length;
this.targetProgress += this.images.length;
}
},
updateProgress() {
const progress1 = lerp(this.progress, this.targetProgress, 0.1);
@ -130,9 +135,10 @@ export default {
const p0 = this.progress % 1;
const p1 = progress1 % 1;
if ((pdiff > 0 && p1 < p0) || (pdiff < 0 && p0 < p1)) {
const i = Math.floor(progress1);
const i = Math.floor(progress1) % this.images.length;
const j = (i + 1) % this.images.length;
this.plane1.setTexture(this.textures[i]);
this.plane2.setTexture(this.textures[i + 1]);
this.plane2.setTexture(this.textures[j]);
}
this.progress = progress1;

View File

@ -0,0 +1,150 @@
<template>
<Renderer ref="renderer" antialias mouse-move="body">
<OrthographicCamera ref="camera" :position="{ z: 10 }" />
<!-- <Camera :position="{ z: 10 }" /> -->
<Scene ref="scene" />
</Renderer>
</template>
<script>
import { Vector2 } from 'three';
import { gsap, Power4 } from 'gsap';
import { lerp, lerpv2 } from '../../tools.js';
import ZoomBlurImage from './ZoomBlurImage.js';
import useTextures from '../../use/useTextures.js';
export default {
props: {
images: Array,
events: { type: Object, default: () => { return { wheel: true, click: true, keyup: true }; } },
},
setup() {
const center = new Vector2();
const { textures, loadTextures } = useTextures();
return {
center,
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.image1.uStrength,
{
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.animate);
this.three.onAfterResize(this.onResize);
},
initScene() {
const scene = this.$refs.scene.scene;
this.image1 = new ZoomBlurImage(this.three);
this.image1.setMap(this.textures[0]);
this.image2 = new ZoomBlurImage(this.three);
this.image2.setMap(this.textures[1]);
this.setImagesProgress(0);
scene.add(this.image1.mesh);
scene.add(this.image2.mesh);
},
animate() {
const { mouse } = this.three;
this.center.copy(mouse).divideScalar(2).addScalar(0.5);
lerpv2(this.image1.uCenter.value, this.center, 0.1);
lerpv2(this.image2.uCenter.value, this.center, 0.1);
this.updateProgress();
},
onResize() {
this.image1.updateUV();
this.image2.updateUV();
},
onWheel(e) {
// e.preventDefault();
if (e.deltaY > 0) {
this.setTargetProgress(this.targetProgress + 1 / 20);
} else {
this.setTargetProgress(this.targetProgress - 1 / 20);
}
},
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.setTargetProgress(this.targetProgress + 1);
else this.setTargetProgress(Math.ceil(this.targetProgress));
},
navPrevious() {
if (Number.isInteger(this.targetProgress)) this.setTargetProgress(this.targetProgress - 1);
else this.setTargetProgress(Math.floor(this.targetProgress));
},
setTargetProgress(value) {
this.targetProgress = value;
if (this.targetProgress < 0) {
this.progress += this.images.length;
this.targetProgress += this.images.length;
}
},
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.images.length;
const j = (i + 1) % this.images.length;
this.image1.setMap(this.textures[i]);
this.image2.setMap(this.textures[j]);
}
this.progress = progress1;
this.setImagesProgress(this.progress % 1);
},
setImagesProgress(progress) {
this.image1.uStrength.value = progress;
this.image2.uStrength.value = -1 + progress;
},
},
};
</script>

View File

@ -0,0 +1,109 @@
import {
Mesh,
PlaneBufferGeometry,
ShaderMaterial,
Vector2,
} from 'three';
export default function ZoomBlurImage(three) {
let geometry, material, mesh;
const uMap = { value: null };
const uCenter = { value: new Vector2(0.5, 0.5) };
const uStrength = { value: 0 };
const uUVOffset = { value: new Vector2(0, 0) };
const uUVScale = { value: new Vector2(1, 1) };
init();
return { geometry, material, mesh, uCenter, uStrength, setMap, updateUV };
function init() {
geometry = new PlaneBufferGeometry(2, 2, 1, 1);
material = new ShaderMaterial({
transparent: true,
uniforms: {
map: uMap,
center: uCenter,
strength: uStrength,
uvOffset: uUVOffset,
uvScale: uUVScale,
},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
// adapted from https://github.com/evanw/glfx.js
fragmentShader: `
uniform sampler2D map;
uniform vec2 center;
uniform float strength;
uniform vec2 uvOffset;
uniform vec2 uvScale;
varying vec2 vUv;
float random(vec3 scale, float seed) {
/* use the fragment position for a different seed per-pixel */
return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);
}
void main() {
vec2 tUv = vUv * uvScale + uvOffset;
if (abs(strength) > 0.001) {
vec4 color = vec4(0.0);
float total = 0.0;
vec2 toCenter = center * uvScale + uvOffset - tUv;
/* randomize the lookup values to hide the fixed number of samples */
float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0);
for (float t = 0.0; t <= 20.0; t++) {
float percent = (t + offset) / 20.0;
float weight = 2.0 * (percent - percent * percent);
vec4 texel = texture2D(map, tUv + toCenter * percent * strength);
/* switch to pre-multiplied alpha to correctly blur transparent images */
texel.rgb *= texel.a;
color += texel * weight;
total += weight;
}
gl_FragColor = color / total;
/* switch back from pre-multiplied alpha */
gl_FragColor.rgb /= gl_FragColor.a + 0.00001;
gl_FragColor.a = 1.0 - abs(strength);
} else {
gl_FragColor = texture2D(map, tUv);
}
}
`,
});
mesh = new Mesh(geometry, material);
}
function setMap(value) {
uMap.value = value;
updateUV();
}
function updateUV() {
const ratio = three.size.ratio;
const iRatio = uMap.value.image.width / uMap.value.image.height;
uUVOffset.value.set(0, 0);
uUVScale.value.set(1, 1);
if (iRatio > ratio) {
uUVScale.value.x = ratio / iRatio;
uUVOffset.value.x = (1 - uUVScale.value.x) / 2;
} else {
uUVScale.value.y = iRatio / ratio;
uUVOffset.value.y = (1 - uUVScale.value.y) / 2;
}
}
}

View File

@ -1,4 +1,5 @@
export { default as Renderer } from './Renderer.js';
export { default as OrthographicCamera } from './OrthographicCamera.js';
export { default as PerspectiveCamera } from './PerspectiveCamera.js';
export { default as Camera } from './PerspectiveCamera.js';
export { default as Scene } from './Scene.js';

View File

@ -4,6 +4,7 @@ export const TroisJSVuePlugin = {
install: (app) => {
const comps = [
'Camera',
'OrthographicCamera',
'PerspectiveCamera',
'Renderer',
'Scene',

View File

@ -22,6 +22,11 @@ export function lerp(value1, value2, amount) {
return value1 + (value2 - value1) * amount;
};
export function lerpv2(v1, v2, amount) {
v1.x = lerp(v1.x, v2.x, amount);
v1.y = lerp(v1.y, v2.y, amount);
};
export function lerpv3(v1, v2, amount) {
v1.x = lerp(v1.x, v2.x, amount);
v1.y = lerp(v1.y, v2.y, amount);