Creating a Dragon‑Shaped Wish Wall with Canvas and Bubble Animations
This article walks through building a wish‑wall where user wishes appear as floating bubbles forming a dragon shape, using HTML5 canvas to extract pixel data, generating bubble DOM elements with CSS animations, and provides full JavaScript code snippets for the implementation.
The story begins with a product manager requesting a "wish wall" where each user’s wish is shown as a bubble, and the brand logo (a dragon) should be formed by these bubbles on the front‑end, with floating animation, hover enlargement, and click‑to‑show details.
Core Requirements
Mouse interaction effects (simple).
Bubbles must float using CSS animation.
Bubbles arranged to form a dragon shape.
To achieve the dragon shape, the author decides to use an HTML5 canvas to process a dragon silhouette image, extract its pixel matrix, and then generate bubble DOM elements at the corresponding positions.
Step 1: Draw the Image onto Canvas
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var image = new Image();
image.src = "dragon.jpg";
image.onload = function() {
canvas.width = image.width;
canvas.height = image.height;
ctx.drawImage(image, 0, 0);
};Step 2: Get and Crop Canvas Pixel Data
var imageData = ctx.getImageData(0, 0, image.width, image.height).data;
ctx.fillStyle = "#ffffff";
ctx.fillRect(0, 0, image.width, image.height);
var gap = 6;
for (var h = 0; h < image.height; h += gap) {
for (var w = 0; w < image.width; w += gap) {
var position = (image.width * h + w) * 4;
var r = imageData[position], g = imageData[position + 1], b = imageData[position + 2];
if (r + g + b == 0) {
ctx.fillStyle = "#000";
ctx.fillRect(w, h, 4, 4);
}
}
}Step 3: Generate Bubble DOM Elements from Pixel Matrix
var dragonContainer = document.getElementById("container");
var dragonScale = 2;
for (var h = 0; h < image.height; h += gap) {
for (var w = 0; w < image.width; w += gap) {
var position = (image.width * h + w) * 4;
var r = imageData[position], g = imageData[position + 1], b = imageData[position + 2];
if (r + g + b == 0) {
var bubble = document.createElement("img");
bubble.src = "bubble.png";
bubble.setAttribute("class", "bubble");
var bubbleSize = Math.random() * 10 + 20;
bubble.style.left = (w * dragonScale - bubbleSize / 2) + "px";
bubble.style.top = (h * dragonScale - bubbleSize / 2) + "px";
bubble.style.width = bubble.style.height = bubbleSize + "px";
bubble.style.animationDuration = Math.random() * 6 + 4 + "s";
dragonContainer.appendChild(bubble);
}
}
}The resulting DOM consists of many img elements styled as bubbles, positioned to outline the dragon silhouette. The author notes that this approach uses many DOM nodes for illustration and suggests using a game engine like Pixi.js for better performance by rendering everything on canvas.
Finally, the article reminds readers that the story is fictional, based on a real project from 2011, and encourages developers to enjoy "fishing" (coding) while tackling such creative front‑end challenges.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
ByteFE
Cutting‑edge tech, article sharing, and practical insights from the ByteDance frontend team.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
