Levende Bilder og Videoer med curtains.js

0
11

Mens du surfer på nyeste award-vinnende nettsteder, kan du merke en masse fancy bilde forvrengning animasjoner eller fine 3D-effekter. De fleste av dem er laget med WebGL, et API slik at GPU-akselerert bildebehandling effekter og animasjoner. De har også en tendens til å bruke biblioteker bygget på toppen av WebGL som three.js eller pixi.js. Begge er svært kraftig verktøy for å lage henholdsvis 2D-og 3D-scener.

Men, du bør huske på at disse bibliotekene var ikke opprinnelig ble utformet for å lage lysbildeserier eller animere DOM-elementer. Det er et bibliotek som er utformet bare for det, skjønt, og vi kommer til å dekke hvordan du bruker det her, i dette innlegget.

WebGL, CSS-Posisjonering, og Reaksjonsevne

Si at du arbeider med et bibliotek som three.js eller pixi.js og du ønsker å bruke den til å lage vekselsvirkningene, som mouseover og bla hendelser på elementer. Du kan kjøre inn i problemer! Hvordan vil du plassere din WebGL elementer i forhold til dokumentet og annen DOM elementer? Hvordan ville håndtere respons?

Dette er akkurat hva jeg hadde i tankene når du oppretter curtains.js.

Curatins.js lar deg opprette fly som inneholder bilder og videoer (WebGL vi vil kalle dem teksturer) som fungerer som ren HTML-elementer, med posisjon og størrelse er definert av CSS-regler. Men disse planene kan være forbedret med de uendelige mulighetene av WebGL shaders.

Vent, shaders?

Shaders er små programmer som er skrevet i GLSL som vil fortelle din GPU hvordan å gjengi flyene. Å vite hvordan shaders arbeid er obligatorisk her fordi dette er hvordan skal vi håndtere animasjoner. Hvis du aldri har hørt om dem, kan du ønsker å lære det grunnleggende først. Det er mange gode nettsteder for å begynne å lære dem, som Boken av Shaders.

Nå som du får ideen, la oss lage vår første fly!

Oppsett av et grunnleggende plan

For å vise vår første flyet, vi trenger en bit av HTML, CSS og JavaScript for å lage flyet. Så vår shaders vil animere den.

HTML

HTML vil være veldig enkelt her. Vi vil lage en <div> som vil holde våre lerret, og en div som vil holde vårt bilde.

<body>
<!– div som vil holde våre WebGL lerret –>
<div id=”lerret”></div>

<!– div brukes til å lage våre fly –>
<div class=”fly”>

<!– bilde som vil bli brukt som en struktur av våre fly –>
<img src=”path/to/my-image.jpg” />

</div>

</body>
CSS

Vi vil bruke CSS for å sikre at <div> som brytes lerretet vil være større enn vår planet, og gjelder alle størrelser til flyet div. (Vår WebGL-flyet vil ha nøyaktig samme størrelse og stillinger av denne div.)

body {
/* få kroppen til å passe med vår viewport */
position: relative;
bredde: 100%;
høyde: 100vh;
margin: 0;

/* skjul rullefelt */
overflow: hidden;
}

#lerret {
/* kontroller lerretet wrapper passer til dokumentet. * /
position: absolute;
øverst: 0;
høyre: 0;
nederst: 0;
venstre: 0;
}
.flyet {
/* angi størrelsen på flyet */
bredde: 80%;
maks bredde: 1400px;
høyde: 80vh;
position: relative;
øverst: 10vh;
margin: 0 auto;
}

.flyet img {
/* skjule img-element */
display: none;
}
JavaScript

Det er litt mer arbeid i JavaScript. Vi trenger å instantiate våre WebGL sammenheng, lage en plan med uniform parametere, og bruke det.

vinduet.onload = function() {
// pass-id-div som vil bryte lerret å sette opp vår WebGL sammenheng og legge til lerretet til våre pakker
var webGLCurtain = nye Gardiner(“lerret”);

// få våre fly element
var planeElement = – dokument.getElementsByClassName(“fly”)[0];

// sett vår første parametre (grunnleggende uniformer)
var params = {
vertexShaderID: “plan-vs”, // våre vertex shader-ID
fragmentShaderID: “plan-fs”, // våre framgent shader-ID
uniformer: {
tid: {
navn: “uTime”, // uniform navn som vil bli videreformidlet til våre shaders
type: “1f”, // dette betyr at våre uniform er en dupp
verdi: 0,
},
}
}

// lager våre fly mesh
var flyet = webGLCurtain.addPlane(planeElement, params);

// bruker onRender metode for våre fly skjøt på hver requestAnimationFrame samtale
fly.onRender(function() {
fly.uniformer.gang.verdien++; // oppdaterer vår tid enhetlig verdi
});

}
Shaders

Vi trenger å skrive vertex shader. Det vil ikke gjøre mye, bortsett fra posisjonen vår plan basert på modellen vise og projeksjon matrix og passere varyings til fragment shader:

<!– vertex shader –>
<script id=”fly-vs” type=”x-shader/x-vertex”>
#ifdef GL_ES
presisjon mediump flyte;
#endif

// disse er obligatoriske egenskaper i den lib sett
attributtet vec3 aVertexPosition;
attributtet vec2 aTextureCoord;

// disse er obligatoriske uniformer at lib sett og som inneholder vår modell vise og projeksjon matrix
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;

// hvis du vil passere din vertex og struktur koord. til fragment shader
varierende vec3 vVertexPosition;
varierende vec2 vTextureCoord;

void main() {
// få vertex posisjon fra sin attributt
vec3 vertexPosition = aVertexPosition;
// setter sin posisjon basert på projeksjon og model view matrix
gl_Position = uPMatrix * uMVMatrix * vec4(vertexPosition, 1.0);

// sett varyings
vTextureCoord = aTextureCoord;
vVertexPosition = vertexPosition;
}
</script>

Nå vårt fragment shader. Det er der vi vil legge litt vekt effekt basert på vår tid uniform og tekstur koordinater.

<!– fragment shader –>
<script id=”fly-fs” type=”x-shader/x-fragment”>
#ifdef GL_ES
presisjon mediump flyte;
#endif

// få våre varyings
varierende vec3 vVertexPosition;
varierende vec2 vTextureCoord;

// uniform erklærte vi inne i vår javascript
uniform flyte uTime;

// våre tekstur sampler (dette er lib standard navn, men det kan bli endret)
uniform sampler2D uSampler0;

void main() {
// komme i vår struktur koord.
vec2 textureCoord = vTextureCoord;

// fortrenge vår punkter langs begge akser basert på vår tid uniform og struktur UVs
// dette vil skape en slags vann overflaten effekt
// prøve å kommentere en linje eller endre konstanter for å se hvordan det endrer effekten
// påminnelse : teksturer koord. er alt fra 0.0 til 1.0 på begge aksen
const float PI = 3.141592;

textureCoord.x += (
synd(textureCoord.x * 10.0 + ((uTime * (PI / 3.0)) * 0.031))
+ sin(textureCoord.y * 10.0 + ((uTime * (PI / 2.489)) * 0.017))
) * 0.0075;

textureCoord.y += (
synd(textureCoord.y * 20.0 + ((uTime * (PI / 2.023)) * 0.023))
+ sin(textureCoord.x * 20.0 + ((uTime * (PI / 3.1254)) * 0.037))
) * 0.0125;

gl_FragColor = texture2D(uSampler0, textureCoord);
}
</script>

Et nå! Du er nå ferdig, og hvis alt gikk bra, du burde se noe som dette.

Se Penn curtains.js grunnleggende fly av Martin Laxenaire (@martinlaxenaire) på CodePen.

Legge til 3D og vekselsvirkningene

Ok, det er ganske kult så langt, men vi startet dette innlegget snakker om 3D og vekselsvirkningene, så la oss se på hvordan vi kan legge dem i.

Om knutepunktene

For å legge til en 3D-effekt vi ville ha til å endre flyet hjørnene posisjon inne i vertex shader. Men i vårt første eksempel, hadde vi ikke å oppgi hvor mange noder våre flyet skulle ha, så det ble opprettet med en standard geometri inneholder seks hjørner danner to trekanter :

For å få anstendig 3D animasjoner, ville vi trenge flere trekanter, og dermed mer noder:

Dette flyet har fem segmenter langs bredden og fem segmenter langs dens høyde. Som et resultat, har vi 50 trekanter og 150 totalt knutepunktene.

Refactoring vår JavaScript

Heldigvis, det er lett å angi vår planet definisjon som det kunne være inne i vår første parametere.

Vi er også kommer til å lytte til mus posisjon for å legge til en bit av interaksjon. Å gjøre det riktig, er vi nødt til å vente på flyet for å være klar, konvertere våre musen dokument koordinatene til vår WebGL klippet plass koordinater og sender dem til shaders som en uniform.

// vi bruker vinduet onload tilfelle her, men dette er ikke obligatorisk
vinduet.onload = function() {
// spor musen posisjoner for å sende det til shaders
var mousePosition = {
x: 0,
y: 0,
};

// pass-id-div som vil bryte lerret å sette opp vår WebGL sammenheng og legge til lerretet til våre pakker
var webGLCurtain = nye Gardiner(“lerret”);

// få våre fly element
var planeElement = – dokument.getElementsByClassName(“fly”)[0];

// sett vår første parametre (grunnleggende uniformer)
var params = {
vertexShaderID: “plan-vs”, // våre vertex shader-ID
fragmentShaderID: “plan-fs”, // våre framgent shader-ID
widthSegments: 20,
heightSegments: 20, // vi har nå 20*20*6 = 2400 hjørner !
uniformer: {
tid: {
navn: “uTime”, // uniform navn som vil bli videreformidlet til våre shaders
type: “1f”, // dette betyr at våre uniform er en dupp
verdi: 0,
},
mousePosition: { // våre mus posisjon
navn: “uMousePosition”,
type: “2f”, // merk at dette er en lengde 2 rekke flyter
verdi: [mousePosition.x, mousePosition.y],
},
mouseStrength: { // styrken av virkningen (vi vil bidra til å dempe det hvis musen stopper å bevege seg)
navn: “uMouseStrength”, // uniform navn som vil bli videreformidlet til våre shaders
type: “1f”, // dette betyr at våre uniform er en dupp
verdi: 0,
},

}
}

// lager våre fly mesh
var flyet = webGLCurtain.addPlane(planeElement, params);

// når våre fly er klar, og vi kunne begynne å lytte til mus/touch hendelser og oppdatere sine uniformer
fly.onReady(function() {
// sett et synsfelt på 35 til exagerate perspektiv
// vi kunne ha gjort det direkte i den første params
fly.setPerspective(35);
// lytte vår mus/touch hendelser på hele dokumentet
// vi vil passere flyet som andre argument av vår funksjon
// vi kan være å håndtere flere fly på den måten
dokumentet.kroppen.addEventListener(“mousemove”, funksjon(e) {
handleMovement(e, fly);
});
dokumentet.kroppen.addEventListener(“touchmove”, funksjon(e) {
handleMovement(e, fly);
});
}).onRender(function() {
// oppdaterer vår tid enhetlig verdi
fly.uniformer.gang.verdien++;
// kontinuerlig nedgang musen styrke
fly.uniformer.mouseStrength.value = Matematikk.max(0, fly.uniformer.mouseStrength.verdi – 0.0075);
});

// håndtak musen flytte arrangementet
funksjonen handleMovement(e, fly) {
// kontakt event
hvis(e.targetTouches) {
mousePosition.x = e.targetTouches[0].clientX;
mousePosition.y = – e.targetTouches[0].clientY;
}
// mus-event
else {
mousePosition.x = e.clientX;
mousePosition.y = – e.clientY;
}
// konverter vår mus/touch posisjon til å koordinater i forhold til hjørner av flyet
var mouseCoords = flyet.mouseToPlaneCoords(mousePosition.x, mousePosition.y);
// oppdaterer våre mus posisjon uniform
fly.uniformer.mousePosition.value = [mouseCoords.x, mouseCoords.y];

// tilordne musen styrke
fly.uniformer.mouseStrength.verdi = 1;
}

}

Nå som vår JavaScript er gjort, må vi skrive våre shaders, slik at de kan bruke våre mus posisjon uniform.

Refactoring den shaders

La oss se på vår vertex shader første. Vi har tre uniformer som vi kan bruke i vårt effekt:

  1. den tid som er stadig økende
  2. musen posisjon
  3. våre mus styrke, som er stadig synkende til neste flytte musen

Vi vil bruke alle tre av dem for å skape en slags 3D-ripple effect.

<script id=”fly-vs” type=”x-shader/x-vertex”>
#ifdef GL_ES
presisjon mediump flyte;
#endif

// disse er obligatoriske egenskaper i den lib sett
attributtet vec3 aVertexPosition;
attributtet vec2 aTextureCoord;

// disse er obligatoriske uniformer at lib sett og som inneholder vår modell vise og projeksjon matrix
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;

// vår tid uniform
uniform flyte uTime;

// våre mus posisjon uniform
uniform vec2 uMousePosition;

// våre musen styrke
uniform flyte uMouseStrength;

// hvis du vil passere din vertex og struktur koord. til fragment shader
varierende vec3 vVertexPosition;
varierende vec2 vTextureCoord;

void main() {
vec3 vertexPosition = aVertexPosition;

// få avstanden mellom våre toppunktet og mus posisjon
float distanceFromMouse = avstand(uMousePosition, vec2(vertexPosition.x, vertexPosition.y));

// denne vil definere hvor nær bølgene vil være fra hverandre. Jo større tall, jo mer krusninger du får
float rippleFactor = 6.0;

// beregne våre ripple effect
float rippleEffect = cos(rippleFactor * (distanceFromMouse – (uTime / 120.0)));

// beregne våre forvrengning effekt
float distortionEffect = rippleEffect * uMouseStrength;

// bruke den til vår vertex posisjon
vertexPosition += distortionEffect / 15.0;

gl_Position = uPMatrix * uMVMatrix * vec4(vertexPosition, 1.0);

// varyings
vTextureCoord = aTextureCoord;
vVertexPosition = vertexPosition;
}
</script>

Som for fragment shader, vi kommer til å holde det enkelt. Vi kommer til å falsk lys og skygger basert på hver toppunktet posisjon:

<script id=”fly-fs” type=”x-shader/x-fragment”>
#ifdef GL_ES
presisjon mediump flyte;
#endif

// få våre varyings
varierende vec3 vVertexPosition;
varierende vec2 vTextureCoord;

// våre tekstur sampler (dette er lib standard navn, men det kan bli endret)
uniform sampler2D uSampler0;

void main() {
// komme i vår struktur koord.
vec2 textureCoords = vTextureCoord;

// bruker vår struktur
vec4 finalColor = texture2D(uSampler0, textureCoords);

// falske skygger basert på toppunktet posisjon langs Z-aksen
finalColor.rgb -= klemme(-vVertexPosition.z, 0.0, 1.0);

// falsk lys basert på toppunktet posisjon langs Z-aksen
finalColor.rgb += klemme(vVertexPosition.z, 0.0, 1.0);

// håndtering premultiplied alpha (nyttig hvis vi brukte en png med gjennomsiktighet)
finalColor = vec4(finalColor.rgb * finalColor.en, finalColor.a);

gl_FragColor = finalColor;
}
</script>

Og der du går!

Se Penn curtains.js ripple effect eksempel av Martin Laxenaire (@martinlaxenaire) på CodePen.

Med disse to enkle eksempler, og vi har sett hvordan å lage en plan og samhandle med det.

Videoer og vekt shaders

Vårt siste eksempel vil opprette en grunnleggende fullskjerm video lysbildefremvisning ved bruk av en vekt shader å forbedre overganger.

Vekt shader konsept

Den vekt shader vil skape en fin forvrengning effekt. Det vil bli skrevet inn i vårt fragment shader ved hjelp av en gråtoner og bilde vil forskyve pixel koordinatene til videoer basert på struktur RGB-verdier. Her er bildet vi skal bruke:

Effekten vil bli beregnet basert på hver pikslers RGB-verdi, med en svart piksel blir [0, 0, 0] og en hvit piksel [1, 1, 1] (GLSL tilsvarende for [255, 255, 255]). For å forenkle, vi vil bare bruke den røde kanalen verdi, som med et gråtonebilde rød, grønn og blå er alltid lik.

Du kan prøve å lage din egen gråskala (det fungerer bra med geometrisk form ) for å få din unike overgangseffekter.

Flere teksturer og videoer

Et fly kan ha mer enn én struktur ganske enkelt ved å legge til flere bildet tagger. Denne gangen, i stedet for bilder vi ønsker å bruke videoer. Vi er bare nødt til å erstatte <img / > – kodene, med en <video /> en. Men det er to ting du bør vite når det kommer til video:

  • Videoen vil alltid passer den eksakte størrelsen på flyet, noe som betyr at flyet har til å ha samme bredde/høyde-forhold som din video. Dette er ikke en stor avtale tho fordi det er lett å håndtere med CSS.
  • På mobile enheter, kan vi ikke autokjør videoer uten en bruker gest, som en klikk på arrangementet. Det er derfor tryggere å legge til en “inn-nettsted” – knappen for å vise og starte våre videoer.

HTML

HTML-koden er fortsatt ganske grei. Vi vil skape våre lerret div wrapper, våre fly div inneholder teksturer og a-knappen for å utløse video autoplay. Bare merke til bruk av data-sampler-attributtet på bilde og video koder—det vil være nyttig i vårt fragment shader.

<body>
<div id=”lerret”></div>
<!– dette div vil håndtere fullskjerm video størrelser og posisjoner –>
<div class=”fly-wrapper”>
<div class=”fly”>
<!– legg merke til her er vi ved hjelp av data-sampler-attributtet for å nevne våre sampler uniformer –>
<img src=”path/to/displacement.jpg” data-sampler=”vekt” />
<video src=”sti/til/video.mp4″ data-sampler=”firstTexture”></video>
<video src=”sti/til/video-2.mp4″ data-sampler=”secondTexture”></video>
</div>
</div>

<div id=”skriv inn stedet-wrapper”>
<span id=”skriv inn stedet”>
Klikk for å angi nettsted
</span>
</div>
</body>
CSS

Den stylesheet vil håndtere et par ting: vis-knappen, og skjuler lerretet før brukeren har angitt område, størrelse og posisjon vår fly-wrapper div til å håndtere fullscreen responsive videoer.

@media-skjerm, {

body {
margin: 0;
font-size: 18px;
font-family: ‘PT Sans’, Verdana, sans-serif;
bakgrunn: #212121;
line-height: 1.4;
høyde: 100vh;
bredde: 100vw;
overflow: hidden;
}

/*** lerret ***/

#lerret {
position: absolute;
øverst: 0;
høyre: 0;
nederst: 0;
venstre: 0;
z-index: 10;

/* skjul lerretet før brukeren klikker på knappen */
dekkevne: 0;
overgang: dekkevne 0.5 s letthet-i;
}

/* vise lerret */
.video-begynte #lerret {
dekkevne: 1;
}

.plan-wrapper {
position: absolute;

/* senter våre fly wrapper */
venstre: 50%;
øverst: 50%;
forvandle: translate(-50%, -50%);
z-index: 15;
}

.flyet {
position: absolute;
øverst: 0;
høyre: 0;
nederst: 0;
venstre: 0;

/* fortelle brukeren at han kan klikke på flyet */
cursor: pointer;
}

/* skjule det opprinnelige bildet og videoer */
.flyet img, .flyet video {
display: none;
}

/* senter knappen */
#skriv inn stedet-wrapper {
skjerm: flex;
rettferdiggjøre-innhold: center;
juster-elementer: center;
juster-innhold: center;
position: absolute;
øverst: 0;
høyre: 0;
nederst: 0;
venstre: 0;
z-index: 30;

/* skjul-knappen til alt er klart */
dekkevne: 0;
overgang: dekkevne 0.5 s letthet-i;
}

/* vis-knapp */
.gardiner-klar #skriv inn stedet-wrapper {
dekkevne: 1;
}

/* skjul-knappen etter at du klikker på hendelsen */
.gardiner-klar.video-begynte #skriv inn stedet-wrapper {
dekkevne: 0;
peker-aktiviteter: ingen;
}

#skriv inn stedet {
polstring: 20 piksler;
color: white;
bakgrunn: #ee6557;
max-width: 200px;
text-align: center;
cursor: pointer;
}

}

/* fullskjerm video responsive */
@media-skjerm, og (maks-aspect-ratio: 1920/1080) {
.plan-wrapper {
høyde: 100vh;
bredde: 177vh;
}
}

@media-skjerm, og (min-aspect-ratio: 1920/1080) {
.plan-wrapper {
bredde: 100vw;
høyde: 56.25 vw;
}
}
JavaScript

Som for JavaScript, vi vil gå som dette:

  • Angi et par variabler til å lagre våre slideshow staten
  • Lage Gardiner objekt og legge til flyet til det
  • Når flyet er klar, kan du lytte til et klikk på arrangementet for å starte våre videoer avspilling (legg merke til bruken av playVideos () – metoden). Legge til en annen klikk på arrangementet for å bytte mellom de to videoene.
  • Oppdatere våre overgang timer uniform inne i onRender () – metoden

vinduet.onload = function() {

// her vil vi håndtere struktur som er synlig og timer til overgangen mellom bildene
var activeTexture = 1;
var transitionTimer = 0;

// setter opp våre WebGL sammenheng og legge til lerretet til våre pakker
var webGLCurtain = nye Gardiner(“lerret”);

// få våre fly element
var planeElements = – dokument.getElementsByClassName(“fly”);

// noen grunnleggende parametre
var params = {
vertexShaderID: “plan-vs”,
fragmentShaderID: “plan-fs”,
imageCover: false, // vår vekt struktur har for å passe flyet
uniformer: {
transitionTimer: {
navn: “uTransitionTimer”,
type: “1f”,
verdi: 0,
},
},
}

var flyet = webGLCurtain.addPlane(planeElements[0], params);

// lager våre fly
fly.onReady(function() {
// display-knappen
dokumentet.kroppen.classList.legge til(“gardiner-klar”);

// når våre fly er klart vi legge til en klikk event lytteren som vil bytte den aktive strukturen verdi
planeElements[0].addEventListener(“klikk”, function() {
hvis(activeTexture == 1) {
activeTexture = 2;
}
else {
activeTexture = 1;
}
});

// klikk på for å spille av videoer
dokumentet.bürgerliches(“skriv inn stedet”).addEventListener(“klikk”, function() {
// display lerret og skjul-knappen
dokumentet.kroppen.classList.legge til(“video-gang”);

// spille våre videoer
fly.playVideos();
}, false);

}).onRender(function() {
// øke eller minske vår timer basert på den aktive strukturen verdi
// på 60fps dette skal vare ett sekund
hvis(activeTexture == 2) {
transitionTimer = Matematikk.min(60, transitionTimer + 1);
}
else {
transitionTimer = Matematikk.max(0, transitionTimer – 1);
}
// oppdaterer vår overgang timer uniform
fly.uniformer.transitionTimer.value = transitionTimer;
});
}
Shaders

Dette er hvor all magien oppstår. Som i vårt første eksempel, vertex shader vil ikke gjøre mye, og du må fokusere på fragment shader som vil skape et “dykk i” effekt:

<script id=”fly-vs” type=”x-shader/x-vertex”>
#ifdef GL_ES
presisjon mediump flyte;
#endif

// standard obligatorisk variabler
attributtet vec3 aVertexPosition;
attributtet vec2 aTextureCoord;

uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;

// varyings
varierende vec3 vVertexPosition;
varierende vec2 vTextureCoord;

// tilpassede uniformer
uniform flyte uTransitionTimer;

void main() {

vec3 vertexPosition = aVertexPosition;

gl_Position = uPMatrix * uMVMatrix * vec4(vertexPosition, 1.0);

// varyings
vTextureCoord = aTextureCoord;
vVertexPosition = vertexPosition;
}
</script>

<script id=”fly-fs” type=”x-shader/x-fragment”>
#ifdef GL_ES
presisjon mediump flyte;
#endif

varierende vec3 vVertexPosition;
varierende vec2 vTextureCoord;

// tilpassede uniformer
uniform flyte uTransitionTimer;

// våre teksturer samplere
// legg merke til hvordan det samsvarer med våre data-sampler attributter
uniform sampler2D firstTexture;
uniform sampler2D secondTexture;
uniform sampler2D vekt;

void main( void ) {
// våre tekstur koord.
vec2 textureCoords = vec2(vTextureCoord.x, vTextureCoord.y);

// våre vekt tekstur
vec4 displacementTexture = texture2D(vekt, textureCoords);

// våre vekt faktor er en dupp varierende fra 1 til 0, basert på-tidtaker
float displacementFactor = 1.0 – (cos(uTransitionTimer / (60.0 / 3.141592)) + 1.0) / 2.0;

// effekten faktor vil fortelle hvilken vei vi ønsker å fortrenge vår punkter
// den lenger fra sentrum av videoer, jo sterkere vil det være
vec2 effectFactor = vec2((textureCoords.x – 0.5) * 0.75, (textureCoords.y – 0.5) * 0.75);

// beregne våre hjemløse koordinater til vår første video
vec2 firstDisplacementCoords = vec2(textureCoords.x – displacementFactor * (displacementTexture.r * effectFactor.x), textureCoords.y – displacementFactor * (displacementTexture.r * effectFactor.y));
// motsatte vekt effekt på andre video
vec2 secondDisplacementCoords = vec2(textureCoords.x – (1.0 – displacementFactor) * (displacementTexture.r * effectFactor.x), textureCoords.y – (1.0 – displacementFactor) * (displacementTexture.r * effectFactor.y));

// bruke teksturer
vec4 firstDistortedColor = texture2D(firstTexture, firstDisplacementCoords);
vec4 secondDistortedColor = texture2D(secondTexture, secondDisplacementCoords);

// blanding både teksturer basert på vår vekt faktor
vec4 finalColor = mix(firstDistortedColor, secondDistortedColor, displacementFactor);

// håndtering premultiplied alfa
finalColor = vec4(finalColor.rgb * finalColor.en, finalColor.a);

// bruker vår shader
gl_FragColor = finalColor;
}
</script>

Her er vår lille video lysbildefremvisning med en kjølig overgang effekt:

Se Penn curtains.js video slideshow av Martin Laxenaire (@martinlaxenaire) på CodePen.

Dette eksemplet er en flott måte å vise deg hvordan å lage en lysbildefremvisning med curtains.js: det kan hende du ønsker å bruke bilder i stedet for videoer, endre vekt tekstur, endre fragment shader eller til og med legge til flere lysbilder…

Går dypere

Vi har bare skrapt overflaten av hva som er mulig med curtains.js. Du kan prøve å opprette flere fly med en kule mus over effekt for artikkelen tommelen for eksempel. Mulighetene er nesten uendelige.

Hvis du ønsker å se flere eksempler som dekker alle de grunnleggende bruksområder, kan du sjekke bibliotekets hjemmeside eller GitHub-repo.

Jetpack WordPress plugin går på dette nettstedet, slår ikke bare relaterte innlegg nedenfor, men sikkerhet og sikkerhetskopiering, Markdown-støtte, søk nettstedet, kommentar form, sosiale nettverk-tilkoblinger, og mer!