Skip to content

Instantly share code, notes, and snippets.

@jesperlandberg
Created June 29, 2021 17:07
Show Gist options
  • Save jesperlandberg/00ab2e337ee9c88963d9552154134340 to your computer and use it in GitHub Desktop.
Save jesperlandberg/00ab2e337ee9c88963d9552154134340 to your computer and use it in GitHub Desktop.
import {
Mesh,
Plane,
Program,
Texture,
Vec2
} from '@/lib/ogl'
import gsap from 'gsap'
import Core from '../Core'
import Elem from '../Elem'
import Pool from '../Pool'
import vertex from '@/gl/shaders/plane/vert.vert'
import fragment from '@/gl/shaders/plane/frag.frag'
import { evt, store, u, p } from '@/app/index'
const { qs, rect, blendEase } = u
export default class extends Elem {
init(args) {
const { gl } = Core
super.init(args)
this.geometry = new Plane(gl, {widthSegments: 25, heightSegments: 25})
this.texture = new Texture(gl, {
generateMipmaps: false,
minFilter: gl.LINEAR,
})
const src = this.el.dataset.src || this.el.dataset.glSrc
if (!src) return
const type = src.split('.').pop()
if (type !== 'mp4') {
const img = new Image()
img.crossOrigin = '*'
img.src = src
img.decode().then(() => {
const { u_size } = this.program.uniforms
this.texture.image = img
u_size.value.x = img.naturalWidth
u_size.value.y = img.naturalHeight
})
} else {
this.vid = document.createElement('video')
this.vid.src = src
this.vid.loop = true
this.vid.muted = true
this.vid.play()
this.vid.oncanplay = () => {
const { u_size } = this.program.uniforms
u_size.value.x = this.vid.videoWidth
u_size.value.y = this.vid.videoHeight
}
}
this.program = new Program(gl, {
vertex,
fragment,
uniforms: {
u_texture: { value: this.texture },
u_toRes: { value: new Vec2(0, 0) },
u_toPos: { value: new Vec2(0, 0) },
u_res: { value: new Vec2(this.bounds.width, this.bounds.height) },
u_pos: { value: new Vec2(this.position.x, this.position.y) },
u_offset: { value: new Vec2(this.camUnit.width, this.camUnit.height) },
u_size: { value: new Vec2(1, 1) },
u_progress: { value: 0 },
u_triggerProgress: { value: .5 },
u_time: { value: 0 },
u_alpha: { value: 1 },
},
cullFace: null,
depthTest: false
})
this.mesh = new Mesh(gl, {
geometry: this.geometry,
program: this.program,
})
this.addChild(this.mesh)
Pool.planesGroup.addChild(this)
Pool.planes[this.name] = this
this.onAdd()
}
onAdd() {
this.trigger()
}
updateVid() {
if (this.vid.readyState >= this.vid.HAVE_ENOUGH_DATA) {
!this.texture.image && (this.texture.image = this.vid)
this.texture.needsUpdate = true
}
}
updateY(y = 0, diff = 0) {
super.updateY(y)
this.program && (this.program.uniforms.u_time.value = Core.time)
this.vid && this.updateVid()
}
transition = (to) => {
const { u_progress, u_toPos, u_toRes, u_pos } = this.program.uniforms
const nBounds = rect(qs('.js-gl-hero', to))
const nSize = this.getSize(
nBounds,
0,
0
)
u_toPos.value.x = nSize.pX
u_toPos.value.y = nSize.pY
u_toRes.value.x = nBounds.width
u_toRes.value.y = nBounds.height
gsap.timeline()
.set(u_pos.value, {
x: this.position.x,
y: this.position.y,
})
.to(u_progress, {
value: 1,
duration: 1,
ease: 'power2'
}, 0)
.add(() => {
this.update()
this.keep = false
this.static = false
})
}
trigger() {
const { u_triggerProgress } = this.program.uniforms
gsap.to(u_triggerProgress, {
value: 1,
duration: 3,
ease: 'expo',
scrollTrigger: {
trigger: this.el,
start: 'top bottom-=25%'
}
})
}
resize() {
super.resize()
const { u_res, u_pos, u_progress } = this.program.uniforms
const { width, height } = this.bounds
const { x, y } = this.position
u_progress.value = 0
u_res.value.x = width
u_res.value.y = height
u_pos.value.x = x
u_pos.value.y = y
}
destroy() {
super.destroy()
this.mesh.renderOrder = 1
this.out = true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment