Following up on last week's plan, this week's task is to address how to create the animation effects on my website's homepage.
Because I had previously tried using Javascript to implement animation effects in web pages in my other course (connected Deivices), I wasn't entirely unfamiliar with how to embed animations into HTML.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Home</title>
<link rel="stylesheet" href="navbar.css">
<link rel="stylesheet" href="home.css">
<script src="<https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.0/p5.min.js>"></script>
<script src="<https://unpkg.com/[email protected]/delaunator.min.js>"></script>
</head>
<body>
<div id="navbar-root"></div>
<div class="page">
<div class="page-layout">
<div class="page-content">
<main>
<nav class="home-links" aria-label="Home quick links">
<a href="design.html">design</a>
<a href="gallery.html">gallery</a>
</nav>
</main>
</div>
</div>
</div>
<script src="navbar.js"></script>
<script src="sketch.js"></script>
</body>
</html>
First, include the p5js <head> tag in your HTML, and then leave space for the JavaScript in the <body> tag.
* {
padding-right: 0%;
margin: 0%;
}
html,
body {
height: 100%;
}
body {
font-family: "Diatype", "ABCDiatype", "Inter", "PingFang SC", "Microsoft YaHei", sans-serif;
}
canvas {
display: block;
position: fixed;
top: 0;
left: 0;
z-index: -1;
}
.page {
min-height: calc(100vh - 120px);
width: 100vw;
/* background-color: #c6c6c6; */
background-color: transparent;
pointer-events: none;
}
.page-layout,
.page-content,
main {
min-height: inherit;
}
.page-content {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
}
.home-links {
position: absolute;
top: 50%;
transform: translateY(-50%);
display: flex;
flex-direction: column;
align-items: center;
gap: 24px;
}
.home-links a {
color: #ff0000;
font-weight: bold;
text-align: center;
text-decoration: underline;
font-size: clamp(12px, 2vw, 18px);
pointer-events: auto;
}
The main CSS modification is to remove the original background color in the page layout and change it to background-color: transparent;. To handle the canvas generated by p5js, the layout is done in the CSS first. pointer-events: none; allows the mouse to interact with the p5js-generated canvas by passing through the background.
Next, you only need to deal with the JSscript files, just like in p5js. However, I had no idea how to achieve this effect. But I discovered (actually, I asked the AI) that there is a library that can generate triangles quite well. delaunator.
The relevant usage manual and tutorials are here : https://mapbox.github.io/delaunator/
Using this library requires knowing all the nodes needed to generate the triangle in advance. So my idea is to generate points that fill the entire screen each frame and store them in an array. And that includes the four edge points of the entire screen.
let currentPoints = [];
for (let p of points) {
let nx = p.x + ...
let ny = p.y + ...
currentPoints.push([nx, ny]);
}
currentPoints.push([-margin, -margin], ...);
for (let i = 0; i < triangles.length; i += 3) {
let p1 = currentPoints[triangles[i]];
let p2 = currentPoints[triangles[i + 1]];
let p3 = currentPoints[triangles[i + 2]];
triangle(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]);
}
In terms of color processing, the colors of the chassis image are extracted first.
let realPixel = bgGraphics.get(sampleX, sampleY);
let realColor = color(realPixel[0], realPixel[1], realPixel[2]);
Because mouse interaction has been added (completely replicating the original effect is almost impossible, so a spotlight-like function has been added). Each triangle calculates its distance from the mouse, and only when the distance to the mouse is less than a set value will it map the color of the image below. This color is then blended with the "white-gray" floating on the surface.
let d = dist(mouseX, mouseY, cx, cy);
let mixRatio = map(d, 0, spotlightRadius, 0, 1);
mixRatio = constrain(mixRatio, 0, 1);
mixRatio = pow(mixRatio, 1.5);
let baseColor = lerpColor(realColor, fogColor, mixRatio);
let tiltLight = noise(cx * 0.004, cy * 0.004, time * 2);
let brightnessMultiplier = map(tiltLight, 0, 1, 0.4, 1.6);
let finalR = constrain(red(baseColor) * brightnessMultiplier, 0, 255);
let finalG = constrain(green(baseColor) * brightnessMultiplier, 0, 255);
let finalB = constrain(blue(baseColor) * brightnessMultiplier, 0, 255);
fill(finalR, finalG, finalB);