I wanted to use your code in react project, I changed somethings, but it ain't working....
this is the changed scene.js :
import * as THREE from "three"
import * as dat from "dat.gui"
import EffectComposer, {
Pass,
RenderPass,
ShaderPass,
TexturePass,
ClearPass,
MaskPass,
ClearMaskPass,
CopyShader,
} from '@johh/three-effectcomposer'
let OrbitControls = require("three-orbit-controls")(THREE)
const createInputEvents = require('simple-input-events');
const event = createInputEvents(window);
const clamp = (min, max) => (value) =>
value < min ? min : value > max ? max : value;
export function Scene (container) {
let scene = new THREE.Scene();
let renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true})
let width = window.innerWidth
let height = window.innerHeight
// this.renderer.setPixelRatio(window.devicePixelRatio);
renderer.setPixelRatio(1)
renderer.setSize(width, height)
renderer.sortObjects = false
renderer.outputEncoding = THREE.sRGBEncoding;
container.appendChild(renderer.domElement)
let camera = new THREE.PerspectiveCamera(
70,
width / height,
100,
1000
)
let cameraDistance = 400
camera.position.set(0, 0, cameraDistance)
camera.lookAt(0, 0, 0)
let time = 0
let speed = 0
let targetSpeed = 0
let mouse = new THREE.Vector2()
let followMouse = new THREE.Vector2()
let prevMouse = new THREE.Vector2()
let paused = false
let controls = new OrbitControls(camera, renderer.domElement)
let that = this;
let settings = {
velo: 0,
scale: 0,
colorful: ()=>{
// that.makeColorful()
that.customPass.uniforms.uType.value = 0
},
zoom: ()=>{
that.customPass.uniforms.uType.value = 1
},
random: ()=>{
that.customPass.uniforms.uType.value = 2
},
};
let gui = new dat.GUI()
// this.gui.add(this.settings, "progress", -1, 2, 0.01);
// this.gui.add(this.settings, "velo", 0, 1, 0.01);
// this.gui.add(this.settings, "scale", 0, 1, 0.01);
gui.add(settings, "colorful")
gui.add(settings, "zoom")
gui.add(settings, "random")
window.addEventListener("resize", resize.bind(this))
let composer = new EffectComposer(renderer)
let renderPass = new RenderPass(scene, camera)
composer.addPass(renderPass)
//custom shader pass
let counter = 0.0
let myEffect = {
uniforms: {
"tDiffuse": { value: null },
"distort": { value: 0 },
"resolution": { value: new THREE.Vector2(1.,window.innerHeight/window.innerWidth) },
"uMouse": { value: new THREE.Vector2(-10,-10) },
"uVelo": { value: 0 },
"uScale": { value: 0 },
"uType": { value: 0 },
"time": { value: 0 }
},
vertexShader: `
uniform float time;
uniform float progress;
uniform vec2 resolution;
varying vec2 vUv;
uniform sampler2D texture1;
const float pi = 3.1415925;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0 );
}`,
fragmentShader: `
uniform float time;
uniform float progress;
uniform sampler2D tDiffuse;
uniform vec2 resolution;
varying vec2 vUv;
uniform vec2 uMouse;
uniform float uVelo;
uniform int uType;
float circle(vec2 uv, vec2 disc_center, float disc_radius, float border_size) {
uv -= disc_center;
uv*=resolution;
float dist = sqrt(dot(uv, uv));
return smoothstep(disc_radius+border_size, disc_radius-border_size, dist);
}
float map(float value, float min1, float max1, float min2, float max2) {
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
}
float remap(float value, float inMin, float inMax, float outMin, float outMax) {
return outMin + (outMax - outMin) * (value - inMin) / (inMax - inMin);
}
float hash12(vec2 p) {
float h = dot(p,vec2(127.1,311.7));
return fract(sin(h)*43758.5453123);
}
// #define HASHSCALE3 vec3(.1031, .1030, .0973)
vec2 hash2d(vec2 p)
{
vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));
p3 += dot(p3, p3.yzx+19.19);
return fract((p3.xx+p3.yz)*p3.zy);
}
void main(){
vec2 newUV = vUv;
vec4 color = vec4(1.,0.,0.,1.);
// colorful
if(uType==0){
float c = circle(newUV, uMouse, 0.0, 0.2);
float r = texture2D(tDiffuse, newUV.xy += c * (uVelo * .5)).x;
float g = texture2D(tDiffuse, newUV.xy += c * (uVelo * .525)).y;
float b = texture2D(tDiffuse, newUV.xy += c * (uVelo * .55)).z;
color = vec4(r, g, b, 1.);
}
// zoom
if(uType==1){
float c = circle(newUV, uMouse, 0.0, 0.1+uVelo*2.)*40.*uVelo;
vec2 offsetVector = normalize(uMouse - vUv);
vec2 warpedUV = mix(vUv, uMouse, c * 0.99); //power
color = texture2D(tDiffuse,warpedUV) + texture2D(tDiffuse,warpedUV)*vec4(vec3(c),1.);
}
// zoom
if(uType==2){
float hash = hash12(vUv*10.);
// float c = -circle(newUV, uMouse, 0.0, 0.1+uVelo*2.)*40.*uVelo;
// vec2 offsetVector = -normalize(uMouse - vUv);
// vec2 warpedUV = mix(vUv, uMouse, c * 0.6); //power
// vec2 warpedUV1 = mix(vUv, uMouse, c * 0.3); //power
// vec2 warpedUV2 = mix(vUv, uMouse, c * 0.1); //power
// color = vec4(
// texture2D(tDiffuse,warpedUV ).r,
// texture2D(tDiffuse,warpedUV1 ).g,
// texture2D(tDiffuse,warpedUV2 ).b,
// 1.);
// color = vec4(,0.,0.,1.);
float c = circle(newUV, uMouse, 0.0, 0.1+uVelo*0.01)*10.*uVelo;
vec2 offsetVector = normalize(uMouse - vUv);
// vec2 warpedUV = mix(vUv, uMouse, 20.*hash*c); //power
vec2 warpedUV = vUv + vec2(hash - 0.5)*c; //power
color = texture2D(tDiffuse,warpedUV) + texture2D(tDiffuse,warpedUV)*vec4(vec3(c),1.);
}
gl_FragColor = color;
}
`
}
let customPass = new ShaderPass(myEffect)
customPass.renderToScreen = true
composer.addPass(customPass)
event.on('move', ({ position, event, inside, dragging }) => {
// mousemove / touchmove
mouse.x = (position[0] / width)
mouse.y = 1. - (position[1]/ height)
})
let geometry = new THREE.PlaneBufferGeometry(1, 1, 80, 80)
let material = new THREE.ShaderMaterial({
extensions: {
derivatives: "#extension GL_OES_standard_derivatives : enable"
},
side: THREE.DoubleSide,
uniforms: {
time: { type: "f", value: 0 },
progress: { type: "f", value: 0 },
angle: { type: "f", value: 0 },
texture1: { type: "t", value: null },
texture2: { type: "t", value: null },
resolution: { type: "v4", value: new THREE.Vector4() },
uvRate1: {
value: new THREE.Vector2(1, 1)
}
},
// wireframe: true,
transparent: true,
vertexShader: `
uniform float time;
uniform float progress;
uniform vec4 resolution;
varying vec2 vUv;
uniform sampler2D texture1;
const float pi = 3.1415925;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0 );
}`,
fragmentShader: `
uniform float time;
uniform float progress;
uniform sampler2D texture1;
uniform vec4 resolution;
varying vec2 vUv;
void main(){
vec2 newUV = (vUv - vec2(0.5))*resolution.zw + vec2(0.5);
// newUV.x += 0.02*sin(newUV.y*20. + time);
gl_FragColor = texture2D(texture1,newUV);
}
`
})
function resize() {
renderer.setSize(width, height)
camera.aspect = width / height
camera.fov = 2 * Math.atan(width / camera.aspect / (2 * cameraDistance)) * (180 / Math.PI); // in degrees
customPass.uniforms.resolution.value.y = height / width
camera.updateProjectionMatrix();
}
resize()
function render() {
time+=0.05
getSpeed()
scene.children.forEach(m => {
if (m.material.uniforms) {
m.material.uniforms.angle.value = settings.angle
m.material.uniforms.time.value = time
}
});
customPass.uniforms.time.value = time
customPass.uniforms.uMouse.value = followMouse
// this.customPass.uniforms.uVelo.value = this.settings.velo;
customPass.uniforms.uVelo.value = Math.min(targetSpeed, 0.05);
targetSpeed *=0.999;
// this.renderer.render(this.scene, this.camera);
if(composer) composer.render()
}
render()
function createMesh(o) {
let material = this.material.clone()
let texture = new THREE.Texture(o.image)
texture.needsUpdate = true
// image cover
let imageAspect = o.iHeight / o.iWidth
let a1
let a2
if (o.height / o.width > imageAspect) {
a1 = (o.width / o.height) * imageAspect
a2 = 1
} else {
a1 = 1
a2 = o.height / o.width / imageAspect
}
texture.minFilter = THREE.LinearFilter
material.uniforms.resolution.value.x = o.width
material.uniforms.resolution.value.y = o.height
material.uniforms.resolution.value.z = a1
material.uniforms.resolution.value.w = a2
material.uniforms.progress.value = 0
material.uniforms.angle.value = 0.3
material.uniforms.texture1.value = texture
material.uniforms.texture1.value.needsUpdate = true
let mesh = new THREE.Mesh(geometry, material)
mesh.scale.set(o.width, o.height, o.width / 2)
return mesh
}
function stop() {
paused = true;
}
function play() {
paused = false
render()
}
function getSpeed(){
speed = Math.sqrt( (prevMouse.x- mouse.x)**2 + (prevMouse.y- mouse.y)**2 );
targetSpeed -= 0.1*(targetSpeed - this.speed);
followMouse.x -= 0.1*(followMouse.x - mouse.x);
followMouse.y -= 0.1*(followMouse.y - mouse.y);
prevMouse.x = mouse.x;
prevMouse.y = mouse.y;
}
return {
createMesh: createMesh,
scene: scene,
render: render,
targetSpeed: targetSpeed
}
}
this is the changed app.js:
import imagesLoaded from "imagesloaded"
import {Scene} from "./scene"
let scene
// helper functions
const MathUtils = {
// map number x from range [a, b] to [c, d]
map: (x, a, b, c, d) => ((x - a) * (d - c)) / (b - a) + c,
// linear interpolation
lerp: (a, b, n) => (1 - n) * a + n * b
};
// body element
const wrapper = document.querySelector('.pic-wrapper')
let IMAGES
// calculate the viewport size
let winsize;
const calcWinsize = () =>
(winsize = { width: window.innerWidth, height: window.innerHeight });
calcWinsize();
// and recalculate on resize
window.addEventListener("resize", calcWinsize);
window.onbeforeunload = function() {
window.scrollTo(0, 0);
};
// scroll position and update function
let docScroll;
const getPageYScroll = () =>
(docScroll = window.pageYOffset || document.documentElement.scrollTop)
window.addEventListener("scroll", getPageYScroll)
// Item
function Item (el, scroll) {
let DOM = { el: el.img }
let currentScroll = docScroll
let animated = false
let isBeingAnimatedNow = false
let shouldRollBack = false
let shouldUnRoll = false
let positions = []
const bounds = DOM.el.getBoundingClientRect()
const fromTop = bounds.top
const windowHeight = window.innerHeight
const withoutHeight = fromTop - windowHeight
const withHeight = fromTop + bounds.height
let insideTop = withoutHeight - docScroll
let insideRealTop = fromTop + docScroll
let insideBottom = withHeight - docScroll + 50
let width = bounds.width
let height = bounds.height
let left = bounds.left
let src = document.getElementById('picture')
let mesh = scene.createMesh({
width: width,
height: height,
src: src,
image: DOM.el,
iWidth: DOM.el.width,
iHeight: DOM.el.height
})
scene.scene.add(mesh)
// use the IntersectionObserver API to check when the element is inside the viewport
// only then the element translation will be updated
let options = {
root: null,
rootMargin: "0px",
threshold: [0, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]
}
let observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
positions.push(entry.boundingClientRect.y)
let compareArray = this.positions.slice(
positions.length - 2,
positions.length
);
let down = compareArray[0] > compareArray[1]
let isVisible = entry.intersectionRatio > 0.0
let shouldRollBack = false
let shouldUnRoll = false
if (
entry.intersectionRatio < 0.5 &&
entry.boundingClientRect.y > 0 &&
isVisible &&
!down
) {
shouldRollBack = true
}
if (
entry.intersectionRatio > 0.5 &&
entry.boundingClientRect.y > 0 &&
isVisible
) {
shouldUnRoll = true
}
console.log(isVisible, 'vis')
mesh.visible = isVisible
})
}, options)
observer.observe(DOM.el)
function resize() {
// on resize rest sizes and update the translation value
mesh.scale.set(width, height, 200)
render(scroll.renderedStyles.translationY.current)
scroll.shouldRender = true
}
// init/bind events
window.addEventListener("resize", () => resize())
function render(s) {
currentScroll = s
mesh.position.y = currentScroll + winsize.height / 2 - insideRealTop - height / 2
mesh.position.x = 0 - winsize.width / 2 + left + width / 2
}
render(0)
}
function SmoothScroll() {
let shouldRender = false
// the <main> element
let DOM = { main: document.querySelector(".pic-main") };
// the scrollable element
// we translate this element when scrolling (y-axis)
DOM.scrollable = DOM.main.querySelector(".scrollable");
// the items on the page
let items = [];
IMAGES.forEach(image => {
if (image.img.classList.contains("js-image")) {
items.push(new Item(image, this))
}
})
document.addEventListener('mousemove',()=>{
shouldRender = true
})
// here we define which property will change as we scroll the page
// in this case we will be translating on the y-axis
// we interpolate between the previous and current value to achieve the smooth scrolling effect
let renderedStyles = {
translationY: {
// interpolated value
previous: 0,
// current value
current: 0,
// amount to interpolate
ease: 0.1,
// current value setter
// in this case the value of the translation will be the same like the document scroll
setValue: () => docScroll
}
}
// set the body's height
function setSize() {
wrapper.style.height = `${DOM.scrollable.scrollHeight}px`
}
setSize()
// set the initial values
for (const key in renderedStyles) {
renderedStyles[key].current = renderedStyles[key].previous = renderedStyles[key].setValue()
}
setPosition()
shouldRender = true
// translate the scrollable element
function setPosition() {
if (
Math.round(renderedStyles.translationY.previous) !==
Math.round(renderedStyles.translationY.current) ||
renderedStyles.translationY.previous < 10
) {
shouldRender = true;
DOM.scrollable.style.transform = `translate3d(0,${-1 * renderedStyles.translationY.previous}px,0)`
for (const item of items) {
if (item.isVisible || item.isBeingAnimatedNow) {
item.render(renderedStyles.translationY.previous);
}
}
}
if(scene.targetSpeed > 0.01) shouldRender = true
if (shouldRender) {
shouldRender = false
scene.render()
}
}
// the <main> element's style needs to be modified
DOM.main.style.position = "fixed"
DOM.main.style.width = DOM.main.style.height = "100%"
DOM.main.style.top = DOM.main.style.left = 0
DOM.main.style.overflow = "hidden"
// init/bind events
window.addEventListener("resize", () => setSize());
// start the render loop
requestAnimationFrame(() => render())
function render() {
// update the current and interpolated values
for (const key in renderedStyles) {
renderedStyles[key].current = renderedStyles[key].setValue()
renderedStyles[key].previous = MathUtils.lerp(
renderedStyles[key].previous,
renderedStyles[key].current,
renderedStyles[key].ease
)
}
// and translate the scrollable element
setPosition()
// loop..
requestAnimationFrame(() => render())
}
}
/***********************************/
/********** Preload stuff **********/
export const pictureAnimation = () => {
const preloadImages = new Promise((resolve, reject) => {
imagesLoaded(document.getElementById("picture"), { background: true }, resolve);
});
preloadImages.then(images => {
IMAGES = images.images
})
console.log(IMAGES)
const preloadEverything = [preloadImages]
// And then..
Promise.all(preloadEverything).then(() => {
// Remove the loader
// Get the scroll position
getPageYScroll()
// Initialize the Smooth Scrolling
let container = document.querySelector(".pic-container")
scene = new Scene(container)
new SmoothScroll()
})
}
I don't know what to do