Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing in React gives errors.. #4

Closed
Arshazar opened this issue Aug 8, 2020 · 0 comments
Closed

Implementing in React gives errors.. #4

Arshazar opened this issue Aug 8, 2020 · 0 comments

Comments

@Arshazar
Copy link

Arshazar commented Aug 8, 2020

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

@Arshazar Arshazar closed this as completed Aug 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant