mirror of
https://github.com/troisjs/trois.git
synced 2024-11-24 04:12:02 +08:00
update demos
This commit is contained in:
parent
ece3164f22
commit
6be8406c8f
File diff suppressed because one or more lines are too long
@ -9,7 +9,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<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 -->
|
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-178028522-1"></script>
|
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-178028522-1"></script>
|
||||||
|
@ -13,16 +13,17 @@ 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 Demo4 from './components/demos/Demo4.vue';
|
||||||
import Slider1 from './components/demos/Slider1.vue';
|
import Slider1 from './components/demos/Slider1.vue';
|
||||||
|
import Slider2 from './components/demos/Slider2.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, Slider1, DemoGLTF,
|
Demo1, Demo2, Demo3, Demo4, Slider1, Slider2, DemoGLTF,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tests: ['Demo1', 'Demo2', 'Demo3', 'Demo4', 'Slider1', 'DemoGLTF'],
|
tests: ['Demo1', 'Demo2', 'Demo3', 'Demo4', 'Slider1', 'Slider2', 'DemoGLTF'],
|
||||||
test: 'Demo1',
|
test: 'Demo1',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -10,14 +10,12 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
images: [
|
images: [
|
||||||
{ src: 'https://assets.codepen.io/33787/img1.jpg' },
|
{ src: 'https://troisjs.github.io/trois/images/img1.jpg' },
|
||||||
{ src: 'https://assets.codepen.io/33787/img2.jpg' },
|
{ src: 'https://troisjs.github.io/trois/images/img2.jpg' },
|
||||||
{ src: 'https://assets.codepen.io/33787/img3.jpg' },
|
{ src: 'https://troisjs.github.io/trois/images/img3.jpg' },
|
||||||
{ src: 'https://assets.codepen.io/33787/img4.jpg' },
|
{ src: 'https://troisjs.github.io/trois/images/img4.jpg' },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
22
src/components/demos/Slider2.vue
Normal file
22
src/components/demos/Slider2.vue
Normal 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>
|
@ -9,7 +9,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { Object3D } from 'three';
|
import { Object3D } from 'three';
|
||||||
import { gsap, Power4 } from 'gsap';
|
import { gsap, Power4 } from 'gsap';
|
||||||
import { lerp, limit } from '../../tools.js';
|
import { lerp } from '../../tools.js';
|
||||||
import AnimatedPlane from './AnimatedPlane.js';
|
import AnimatedPlane from './AnimatedPlane.js';
|
||||||
import useTextures from '../../use/useTextures';
|
import useTextures from '../../use/useTextures';
|
||||||
|
|
||||||
@ -93,9 +93,9 @@ export default {
|
|||||||
onWheel(e) {
|
onWheel(e) {
|
||||||
// e.preventDefault();
|
// e.preventDefault();
|
||||||
if (e.deltaY > 0) {
|
if (e.deltaY > 0) {
|
||||||
this.targetProgress = limit(this.targetProgress + 1 / 20, 0, this.images.length - 1);
|
this.setTargetProgress(this.targetProgress + 1 / 20);
|
||||||
} else {
|
} else {
|
||||||
this.targetProgress = limit(this.targetProgress - 1 / 20, 0, this.images.length - 1);
|
this.setTargetProgress(this.targetProgress - 1 / 20);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onClick(e) {
|
onClick(e) {
|
||||||
@ -113,14 +113,19 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
navNext() {
|
navNext() {
|
||||||
if (Number.isInteger(this.targetProgress)) this.targetProgress += 1;
|
if (Number.isInteger(this.targetProgress)) this.setTargetProgress(this.targetProgress + 1);
|
||||||
else this.targetProgress = Math.ceil(this.targetProgress);
|
else this.setTargetProgress(Math.ceil(this.targetProgress));
|
||||||
this.targetProgress = limit(this.targetProgress, 0, this.images.length - 1);
|
|
||||||
},
|
},
|
||||||
navPrevious() {
|
navPrevious() {
|
||||||
if (Number.isInteger(this.targetProgress)) this.targetProgress -= 1;
|
if (Number.isInteger(this.targetProgress)) this.setTargetProgress(this.targetProgress - 1);
|
||||||
else this.targetProgress = Math.floor(this.targetProgress);
|
else this.setTargetProgress(Math.floor(this.targetProgress));
|
||||||
this.targetProgress = limit(this.targetProgress, 0, this.images.length - 1);
|
},
|
||||||
|
setTargetProgress(value) {
|
||||||
|
this.targetProgress = value;
|
||||||
|
if (this.targetProgress < 0) {
|
||||||
|
this.progress += this.images.length;
|
||||||
|
this.targetProgress += this.images.length;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
updateProgress() {
|
updateProgress() {
|
||||||
const progress1 = lerp(this.progress, this.targetProgress, 0.1);
|
const progress1 = lerp(this.progress, this.targetProgress, 0.1);
|
||||||
@ -130,9 +135,10 @@ export default {
|
|||||||
const p0 = this.progress % 1;
|
const p0 = this.progress % 1;
|
||||||
const p1 = progress1 % 1;
|
const p1 = progress1 % 1;
|
||||||
if ((pdiff > 0 && p1 < p0) || (pdiff < 0 && p0 < p1)) {
|
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.plane1.setTexture(this.textures[i]);
|
||||||
this.plane2.setTexture(this.textures[i + 1]);
|
this.plane2.setTexture(this.textures[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.progress = progress1;
|
this.progress = progress1;
|
||||||
|
150
src/components/sliders/Slider2.vue
Normal file
150
src/components/sliders/Slider2.vue
Normal 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>
|
109
src/components/sliders/ZoomBlurImage.js
Normal file
109
src/components/sliders/ZoomBlurImage.js
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
export { default as Renderer } from './Renderer.js';
|
export { default as Renderer } from './Renderer.js';
|
||||||
|
export { default as OrthographicCamera } from './OrthographicCamera.js';
|
||||||
export { default as PerspectiveCamera } from './PerspectiveCamera.js';
|
export { default as PerspectiveCamera } from './PerspectiveCamera.js';
|
||||||
export { default as Camera } from './PerspectiveCamera.js';
|
export { default as Camera } from './PerspectiveCamera.js';
|
||||||
export { default as Scene } from './Scene.js';
|
export { default as Scene } from './Scene.js';
|
||||||
|
@ -4,6 +4,7 @@ export const TroisJSVuePlugin = {
|
|||||||
install: (app) => {
|
install: (app) => {
|
||||||
const comps = [
|
const comps = [
|
||||||
'Camera',
|
'Camera',
|
||||||
|
'OrthographicCamera',
|
||||||
'PerspectiveCamera',
|
'PerspectiveCamera',
|
||||||
'Renderer',
|
'Renderer',
|
||||||
'Scene',
|
'Scene',
|
||||||
|
@ -22,6 +22,11 @@ export function lerp(value1, value2, amount) {
|
|||||||
return value1 + (value2 - value1) * 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) {
|
export function lerpv3(v1, v2, amount) {
|
||||||
v1.x = lerp(v1.x, v2.x, amount);
|
v1.x = lerp(v1.x, v2.x, amount);
|
||||||
v1.y = lerp(v1.y, v2.y, amount);
|
v1.y = lerp(v1.y, v2.y, amount);
|
||||||
|
Loading…
Reference in New Issue
Block a user