Det ser kanskje merkelig ut her, men Red Dead Redemtion 2-effekten åpner for mange muligheter i CSS. 📸: Jørgen Jacobsen
Det ser kanskje merkelig ut her, men Red Dead Redemtion 2-effekten åpner for mange muligheter i CSS. 📸: Jørgen Jacobsen Vis mer

Effekten fra Red Dead Redemption 2 i CSS

En kombinasjon av enkle CSS-triks gir den unike effekten.

OBS! Denne effekten bruker eksperimentell CSS, som ennå ikke er implementert i Safari.

Det blir endel Red Dead Redemption 2-prat på kode24-kontoret om dagen.

Hypen rundt spillet har såvisst ikke lagt seg ennå. Kanskje ikke så rart, siden spillet visstnok tar 50 til 60 timer å fullføre.

I det siste har det til og med dukket opp flere norske elementer i spillet, blant annet dette avisutklippet som en bruker på Reddit fant og flere norskspråklige karakterer.

Noe av det første man opplever i spillet, og stadig oftere senere, er den litt snodige lasteskjermen. Den består av to like bilder, hvorav det ene er gjort invers. Så er det en slags kornete maskeringsanimasjon som veksler mellom de to variantene.

Lee Morgan er en av dem som har laget en CSS-versjon av animasjonen, inspirert av en guide fra nettsiden Codrops i 2016. Resultatet ser slik ut:

Og her er hvordan du får til det samme.

Slik henger det sammen

Løsningen er faktisk ganske enkel. Det er en kombinasjon av tre CSS-attributter: mask, animate og filter. Sammen med en maske-animasjon som er lagret som et mega-langt horisontalt png-bilde.

La oss bryte ned teknikken.

Bildene du ser i animasjonen i første avsnitt er samme bilde malt oppå hverandre. Den inverse versjonen blir til ved CSS-attributten:

filter: invert(1.0) grayscale(1.0);

Mask tillater at man kan bruke et bilde som maskering for et HTML-element. Enkelt forklart tar det imot et maskebilde (PNG eller SVG) og gjør de gjennomsiktige delene av bildet gjennomsiktig oppå HTML-elementet.

Til venstre ser du denne transparante PNG-fila. Til høyre bruker vi PNG-fila som en maske oppå vårt kode24-bilde.

Lang i maska

Men foreløpig har vi ingen animasjon. Det er her vårt megalange PNG-bilde kommer inn i bildet.

Det megalange PNG-bildet er egentlig en komprimert versjon av en video, ala denne. Hvor flere stillbilder fra videoen er satt ved siden av hverandre i en sekvens, slik som dette:

image: Effekten fra Red Dead Redemption 2 i CSS

Denne typen animasjon kalles ofte «ink overlay», og det finnes haugevis av dem.

Hvis du ønsker å lage din egen PNG-sekvens, må du importere en lignende video til et videoredigerings-program som Adobe After Effects. Fra der kutter du ned videoen, og eksporterer til en PNG-bildefil-sekvens. Da får du ut en haug med PNG-filer.

Deretter bruker du et program ala CSS Sprite Generator til å generete ett bilde fra sekvensen av PNG-filer. Codrops går grundigere gjennom denne sekvensen i sin artikkel om samme tema.

I vårt eksempel bruker vi den originalen bildesekvensen fra artikkelen til Lee Morgan.

.mask {
	-webkit-mask: url(https://www.dagbladet.no/files/2018/11/05/sheet.png);
	-webkit-mask-size: 7000% 100%;
	mask: url(https://www.dagbladet.no/files/2018/11/05/sheet.png);
	mask-size: 7000% 100%;
}

Sekvensen legger vi inn i CSS-en med mask-attributtet som tidligere, men merk at animasjonen til Lee består av 70 bilderammer etter hverandre i en PNG-fil. Dermed er masken vår 70 ganger så bred som bildet vårt, noe vi må kompensere for med mask-size: 7000% 100%;

Gjør vi ikke det blir hele det lange bildet tilpasset bredden vår, som illustrasjonen over viser (riktig til høyre, feil til venstre).

Animere masken

Sist, men ikke minst, må vi animere masken vår. Det gjør vi med CSS3-attributtet animation. Her bruker vi også et lite triks som kalles steps. Vanlige animasjoner i CSS animerer gjerne på en lineær linje. Men man kan også velge steps(x).

Steps er vanlig å bruke når man for eksempel skal animere en TV-spillfigur. Hele poenget er at man skal kunne bygge en animasjon som består av et gitt antall steg og hoppe mellom dem. Noe som er perfekt for vår animasjon, som består av 70 bilderammer, eller 70 steg om du vil.

Dermed lager vi en animasjon hvor vi flytter mask-position fra «0% 0» til «100% 0», på 69 steps. Merk at vi regner ett mindre step i animasjonen vår, siden den første rammen av animasjonen vår allerede er i bildet på step 0.

.mask {
	-webkit-mask: url(https://www.dagbladet.no/files/2018/11/05/sheet.png);
	-webkit-mask-size: 7000% 100%;
	mask: url(https://www.dagbladet.no/files/2018/11/05/sheet.png);
	mask-size: 7000% 100%;
	animation: mask 5s steps(69) infinite alternate;
	/* Merk at vi regner ett mindre skritt */
}
@keyframes mask{
	from{
	-webkit-mask-position: 0% 0;
	mask-position: 0% 0;
	}
	to{
	-webkit-mask-position: 100% 0;
	mask-position: 100% 0;
	}
}

Nå som du kan teknikken, hva med å prøve med en annen megalang bildesekvens, slik som den som brukes av Codrops?

Den komplette kildekoden finner du her:

<style>
	#example-4 {
		display: flex;
		width: 100%;
		height: 600px;
		position: relative;
	}
	.first,
	.second {
		position: relative;
		width: 50%;
		height: 100%;
	}
	#example-4 .regular-image {
		position: absolute;
		left: 0;
		top: 0;
		width: 100%;
		height: 100%;
		background-size: cover;
	}
	#example-4 .inverse {
		filter: invert(1.0) grayscale(1.0);
	}

	#example-4 .mask {
		-webkit-mask: url(https://www.dagbladet.no/files/2018/11/05/sheet.png);
		-webkit-mask-size: 7000% 100%;
		mask: url(https://www.dagbladet.no/files/2018/11/05/sheet.png);
		mask-size: 7000% 100%;
		animation: mask 5s steps(69) infinite alternate;
	}
	@keyframes mask{
	from{
		-webkit-mask-position: 0% 0;
		mask-position: 0% 0;
	}
	to{
		-webkit-mask-position: 100% 0;
		mask-position: 100% 0;
		}
	}
</style>
<div id="example-4">
	<div class="regular-image inverse" style="background-image: url(https://www.dagbladet.no/files/2018/11/05/kode24.jpg)">
	</div>
	<div class="regular-image mask" style="background-image: url(https://www.dagbladet.no/files/2018/11/05/kode24.jpg)">
	</div>
</div>