Created
August 28, 2020 16:52
-
-
Save bozzin/0a452540969e4de92747beaad3c7c274 to your computer and use it in GitHub Desktop.
Text Curtains.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="page-wrap"> | |
<!-- div that will hold our WebGL canvas --> | |
<!--<nav class="main-nav"> | |
<div class="logo"><img src="" alt="" class="img-logo">AB</div> | |
<ul class="main-menu"> | |
<li><a href="">HOME</a></li> | |
<li><a href="">ABOUT</a></li> | |
<li><a href="">WORKS</a></li> | |
<li><a href="">CONTACT</a></li> | |
</ul> | |
</nav>---> | |
<div id="canvas"></div> | |
<!-- div used to create our plane --> | |
<div class="plane"> | |
<!-- images that will be used as textures by our plane --> | |
<div class="title-hero"> | |
<h1 class="text">Alain Barrios</h1> | |
</div> | |
</div> | |
</div> | |
<script id="vs" type="f"> | |
#ifdef GL_ES | |
precision mediump float; | |
#endif | |
#define TAU 6.28318530718 | |
uniform float uTime; | |
// those are the mandatory attributes that the lib sets | |
attribute vec3 aVertexPosition; | |
attribute vec2 aTextureCoord; | |
// those are mandatory uniforms that the lib sets and that contain our model view and projection matrix | |
uniform mat4 uMVMatrix; | |
uniform mat4 uPMatrix; | |
uniform mat4 texture0Matrix; | |
// if you want to pass your vertex and texture coords to the fragment shader | |
varying vec3 vVertexPosition; | |
varying vec2 vTextureCoord0; | |
varying float vTime; | |
void main() { | |
vec3 vertexPosition = aVertexPosition; | |
vTime = uTime; | |
vTextureCoord0 = aTextureCoord; | |
vVertexPosition = vertexPosition; | |
gl_Position = uPMatrix * uMVMatrix * vec4(vertexPosition, 1.0); | |
} | |
</script> | |
<script id="fs" type="f"> | |
#ifdef GL_ES | |
precision mediump float; | |
#endif | |
#define TAU 6.28318530718 | |
#define PI 3.14159265359 | |
#define S(a,b,n) smoothstep(a,b,n) | |
#define NUM_OCTAVES 5 | |
varying float vTime; | |
uniform float uProgress; | |
uniform vec2 uReso; | |
uniform vec2 uMouse; | |
varying vec3 vVertexPosition; | |
varying vec2 vTextureCoord0; | |
uniform sampler2D planeTexture; | |
void main(){ | |
float radius = 0.4; | |
vec2 uv0 = vTextureCoord0; | |
vec2 st = (gl_FragCoord.xy - 0.5 * uReso) / min(uReso.x, uReso.y); | |
vec2 mouse = (uMouse - 0.5 * uReso) / min(uReso.x, uReso.y); | |
float dist = length(st - mouse); | |
float mag = pow(clamp(radius - dist / radius, 0.0, 1.0), 0.7); | |
vec2 len = (mouse - st) * mag; | |
float x = uv0.y * TAU * 15.0 + vTime * 5.0; | |
float y = uv0.x * TAU * 15.0 + vTime * 5.0; | |
float distx = cos(x+y) / 1000.0 * cos(y); | |
float disty = sin(x-y) / 1000.0 * cos(y); | |
vec2 distortion = vec2(distx, disty) + len; | |
vec4 color0 = texture2D(planeTexture, uv0 + distortion); | |
gl_FragColor = color0; | |
} | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class WEBGL { | |
constructor(set) { | |
this.curtains = new Curtains({ container: "canvas" }); | |
this.planeElement = set.planeElement; | |
this.mouse = { | |
x: 0, | |
y: 0 | |
}; | |
this.font = 'a' | |
this.params = { | |
vertexShader: document.getElementById("vs").textContent, // our vertex shader ID | |
fragmentShader: document.getElementById("fs").textContent, // our framgent shader ID | |
uniforms: { | |
time: { | |
name: "uTime", // uniform name that will be passed to our shaders | |
type: "1f", // this means our uniform is a float | |
value: 0 | |
}, | |
mousepos: { | |
name: "uMouse", | |
type: "2f", | |
value: [0, 0] | |
}, | |
resolution: { | |
name: "uReso", | |
type: "2f", | |
value: [0, 0] | |
}, | |
progress: { | |
name: "uProgress", | |
type: "1f", | |
value: 0 | |
} | |
} | |
}; | |
} | |
loadFont(name, urlFont) { | |
const font = new FontFace(`${name}`, `url(${urlFont})`); | |
return new Promise(resolve => { | |
font.load().then(font_face => { | |
document.fonts.add(font_face); | |
document.body.style.fontFamily = font.family; | |
resolve(font_face); | |
}); | |
}); | |
} | |
async createCanvas(plane, canvas) { | |
this.font = this.font && await this.loadFont( | |
"futura", | |
"https://cdn.statically.io/gh/AlainBarrios/Fonts/12a918f9/futura%20medium%20bt.ttf?raw=true" | |
); | |
const boundingPlane = plane.getBoundingRect(); | |
const planeElement = plane.htmlElement; | |
// get styles of the h1 title | |
const textStyles = window.getComputedStyle(planeElement.children[0]); | |
const relWidth = boundingPlane.width / this.curtains.pixelRatio; | |
const relHeight = boundingPlane.height / this.curtains.pixelRatio; | |
const ctx2d = canvas.getContext("2d"); | |
canvas.width = ctx2d.width = relWidth; | |
canvas.height = ctx2d.height = relHeight; | |
// set styles at text | |
ctx2d.fillStyle = textStyles.color; | |
ctx2d.font = `${textStyles.fontWeight} ${textStyles.fontSize} ${ | |
this.font.family | |
}`; | |
// text baseline and text align | |
ctx2d.textBaseline = "middle"; | |
ctx2d.textAlign = "center"; | |
// draw the text in the midlle or our plane | |
ctx2d.fillText(planeElement.textContent, relWidth / 2, relHeight / 2); | |
// update our canvas texture once on next draw call | |
if (plane.textures.length > 0) { | |
plane.textures[0].needUpdate(); | |
} | |
} | |
initPlane() { | |
// create our plane mesh | |
this.plane = this.curtains.addPlane(this.planeElement, this.params); | |
// use the onRender method of our plane fired at each requestAnimationFrame call | |
if (this.plane) { | |
const text = this.plane.htmlElement.textContent; | |
const canvas = document.createElement("canvas"); | |
this.createCanvas(this.plane, canvas); | |
canvas.setAttribute("data-sampler", "planeTexture"); | |
this.plane.loadCanvas(canvas); | |
this.plane.setScale(1, 1); | |
this.plane.onReady(() => { | |
this.plane.uniforms.resolution.value = [ | |
this.plane.getBoundingRect().width, | |
this.plane.getBoundingRect().height | |
]; | |
this.plane.textures[0].shouldUpdate = false; | |
this.update(); | |
this.initEvents(canvas); | |
}); | |
} | |
} | |
update() { | |
this.plane.onRender(() => { | |
this.plane.updatePosition(); | |
this.plane.uniforms.time.value += 0.01; // update our time uniform value | |
}); | |
} | |
initEvents(canvas) { | |
window.addEventListener("mousemove", e => { | |
const x = e.clientX; | |
const y = innerHeight - e.clientY; | |
TweenMax.to(this.plane.uniforms.mousepos.value, 0.7, { | |
0: x, | |
1: y | |
}); | |
}); | |
window.addEventListener("resize", () => { | |
this.plane.uniforms.resolution.value = [ | |
this.plane.getBoundingRect().width, | |
this.plane.getBoundingRect().height | |
]; | |
this.createCanvas(this.plane, this.plane.textures[0].source); | |
}); | |
} | |
} | |
const webgl = new WEBGL({ | |
planeElement: document.querySelector(".title-hero") | |
}); | |
webgl.initPlane(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.3/TweenMax.min.js"></script> | |
<script src="https://rawcdn.githack.com/martinlaxenaire/curtainsjs/95957f855ad9fd51850e97312cd389af76e9704e/build/curtains.min.js"></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*@font-face { | |
font-family: "futura"; | |
src: url(https://cdn.statically.io/gh/AlainBarrios/Fonts/12a918f9/futura%20medium%20bt.ttf?raw=true); | |
}*/ | |
:root { | |
/*--futura: "futura"*/; | |
--color1: rgba(255, 255, 255, 1); | |
--color2: rgba(0, 0, 0, 1); | |
--fontSize1: 3rem; | |
} | |
*, | |
*::before, | |
*::after { | |
box-sizing: border-box; | |
text-rendering: optimizeLegibility; | |
-webkit-font-smoothing: antialiased; | |
-moz-osx-font-smoothing: grayscale; | |
font-kerning: auto; | |
-webkit-text-size-adjust: 100%; | |
} | |
body { | |
margin: 0; | |
} | |
ul { | |
list-style: none; | |
margin: 0; | |
padding: 0; | |
} | |
a { | |
text-decoration: none; | |
color: var(--color2); | |
} | |
canvas { | |
display: block; | |
max-width: 100%; | |
} | |
.container-fluid { | |
max-width: 1200px; | |
margin-left: auto; | |
margin-right: auto; | |
} | |
#page-wrap { | |
position: relative; | |
display: flex; | |
flex-direction: column; | |
width: 100%; | |
height: 100vh; | |
} | |
.main-nav { | |
position: relative; | |
display: flex; | |
align-items: center; | |
padding: 15px; | |
} | |
.logo { | |
font-size: 2rem; | |
background-color: var(--color2); | |
color: var(--color1); | |
padding-left: 10px; | |
padding-right: 10px; | |
letter-spacing: 5px; | |
text-indent: 2.5px; | |
padding-top: 15px; | |
padding-bottom: 15px; | |
} | |
.main-menu { | |
padding-left: 30px; | |
display: flex; | |
justify-content: flex-end; | |
font-weight: bold; | |
} | |
.main-menu li { | |
margin-left: 30px; | |
margin-right: 30px; | |
} | |
#canvas { | |
/* make the canvas wrapper fits the document */ | |
position: absolute; | |
top: 0; | |
right: 0; | |
bottom: 0; | |
left: 0; | |
} | |
.plane { | |
/* define the size of your plane*/ | |
width: 100%; | |
height: 100vh; | |
z-index: 10; | |
cursor: crosshair; | |
} | |
.plane img { | |
/* hide the img element */ | |
display: none; | |
} | |
.title-hero { | |
width: 100%; | |
height: 100%; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
font-weight: bold; | |
font-size: calc(9/16 * 10vw); | |
} | |
.title-hero .text { | |
margin: 0; | |
opacity: 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment