Skapa interaktiva bilder med JavaScript och HTML5 Canvas

, Author

Projekt 1: iskalla linjer

För bästa resultat, öppna i helskärm

För det första är våra linjer vita, så låt oss gå in i CSS:en och ge canvas en mörk bakgrund:

canvas {
background: linear-gradient(45deg, #0d1011 0% 20%, #163486);
}

Linjekonstruktör

Nu tillbaka till canvas.js . Låt oss skapa en ny Line klass:

class Line {
constructor(x, y, offset) {
this.x = x;
this.y = y;
this.offset = offset;
this.radians = 0;
this.velocity = 0.01;
}

Avse att bestämma varje linjes x och y position, har vi några andra egenskaper för att göra våra visuella bilder mer intressanta:

  • Vi kan använda offset egenskapen för att återge linjerna på olika avstånd från varandra.
  • Vi kommer också att använda oss av cirkulär rörelse i vårt exempel. Vi kan använda egenskapen radians för att definiera rörelsevinkeln och egenskapen velocity för att bestämma rörelsens hastighet.

Metod för ritning av linjer

Nästan vill vi rita våra linjer. Det finns en liten cirkel i botten av varje linje, som vi kan definiera med hjälp av funktionen arc, och sedan skjuter linjen iväg till toppen av skärmen:

class Line {
constructor(x, y, offset) {
this.x = x;
this.y = y;
this.offset = offset;
this.radians = 0;
this.velocity = 0.01;
} draw = () => {
c.strokeStyle = 'rgba(255, 255, 255, 0.5)';
c.fillStyle = 'rgba(255, 255, 255, 0.3)'; c.beginPath();
c.arc(this.x, this.y, 1, 0, Math.PI * 2, false);
c.fill();
c.moveTo(this.x, this.y);
c.lineTo(this.x + 300, this.y - 1000);
c.stroke();
c.closePath(); this.update();
} update = () => {
// this is where we control movement and interactivity
}
}

För att testa att det fungerar kan du skapa en exempellinje:

const line = new Line(250, 800, 0);
line.draw();

Generering av 100 linjer

Men vi vill att linjerna ska fylla hela skärmen, så vi behöver ett sätt att skapa en array med 100 linjer. Här är en enkel version:

const lineArray = ;for (let i = 0; i < 100; i++) { const start = { x: -250, y: 800 };
const unit = 25; lineArray.push(
new Line(
start.x + unit * i,
start.y + i * -3,
0.1 + (1 * i)
)
);
};

För att visa dessa linjer måste vi utlösa deras draw metoder. Eftersom vi snart ska animera dem är det bästa stället att göra det i animate-funktionen:

function animate() {
requestAnimationFrame(animate);
c.clearRect(0, 0, window.innerWidth, window.innerHeight);
lineArray.forEach(line => {
line.draw();
});
};animate();

Vi har nu 100 linjer! Men vi kan göra vår utgångsposition mer intressant: i koden nedan hjälper random-variabeln till att ge subtila variationer som ger den övergripande effekten ett mer naturligt utseende. (Jag använder också Math.sin(i) för att lägga till lite vågor i startpositionerna. Detta är inte nödvändigt, men det är en trevlig touch.)

const lineArray = ;for (let i = 0; i < 100; i++) { const start = { x: -250, y: 800 };
const random = Math.random() - 0.5;
const unit = 25; lineArray.push(
new Line(
start.x + ((unit + random) * i),
start.y + (i + random) * -3 + Math.sin(i) * unit,
0.1 + (1 * i)
)
);
};

Lek med siffrorna tills du har ett startmönster som du gillar!

Animation

Från här är det väldigt enkelt att lägga till animationen vi vill ha. Gå tillbaka till vår Line-klass och lägg sedan till följande i update-metoden:

this.radians += this.velocity;
this.y = this.y + Math.cos(this.radians + this.offset);

Med varje animationsram kommer this.radians att öka med this.velocity . Vi kommer sedan att använda this.radians för att skapa cirkelrörelse, via Math.cos .

Om du inte har stött på Math.sin eller Math.cos tidigare (eller om din trigonometri är lite ringrostig!) bör det inte hindra dig från att följa med. Du ska bara veta att Math.cos gör det möjligt för oss att skapa en rörelse fram och tillbaka, i ett mönster som är identiskt med den lila linjen i grafen nedan:

Kosinvågen

Sluttligen kommer linjerna att börja slingra sig i olika vinklar genom att lägga till this.offset.

Jag tycker att detta är en ganska fin effekt. Men för att få en sista touch kan vi lägga till lite interaktivitet. När användaren håller musen över linjerna får vi dem att ändra färg.

Interaktivitet

Det enklaste sättet att se om användarens mus befinner sig över en av linjerna är att använda canvas inbyggda isPointInPath-metod.

Men utan några ytterligare finjusteringar kommer detta inte att vara till någon större nytta. Linjerna är bara 1 pixel breda, så chansen att utlösa några förändringar kommer att vara för liten för att vara intressant!

En bra lösning på det här problemet är att skapa osynliga linjer bakom var och en av våra linjer. De osynliga linjerna ska vara bredare och vi kan använda dessa för att utlösa isPointInPath.

isPointInPath

Inom vår draw-metod ska vi skapa en funktion som heter drawLinePath . Den bör ta en width för våra osynliga linjer och en color (som våra synliga linjer kommer att bli när de osynliga linjerna är i kontakt):

const drawLinePath = (width = 0, color) => {
c.beginPath();
c.moveTo(this.x - (width / 2), this.y + (width / 2));
c.lineTo(this.x - (width / 2) + 300, this.y - (width / 2) - 1000);
c.lineTo(this.x + (width / 2) + 300, this.y - (width / 2) - 1000);
c.lineTo(this.x + (width / 2), this.y - (width / 2));
c.closePath();
if (c.isPointInPath(mouse.x, mouse.y) && color) {
c.strokeStyle = color;
};
};

(Observera att användandet av pilfunktioner ovan implicit binder den korrekta kontexten för this ).

Vi kan sedan enkelt lägga till olika bredder på de osynliga linjerna för att utlösa olika färgförändringar. Följande kod bör klargöra vad som händer:

drawLinePath(150, 'red');
drawLinePath(50, 'yellow');

Men om du vill ha en mer subtil effekt kan du prova:

drawLinePath(150, '#baf2ef');
drawLinePath(50, '#dcf3ff');

Och det var allt!

För den kompletta JavaScript-koden kan du kolla in denna gist.

Lämna ett svar

Din e-postadress kommer inte publiceras.