惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
J
Java Code Geeks
博客园 - 【当耐特】
宝玉的分享
宝玉的分享
腾讯CDC
D
DataBreaches.Net
Microsoft Azure Blog
Microsoft Azure Blog
Engineering at Meta
Engineering at Meta
V
V2EX
F
Fortinet All Blogs
MyScale Blog
MyScale Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
Tailwind CSS Blog
Jina AI
Jina AI
GbyAI
GbyAI
大猫的无限游戏
大猫的无限游戏
A
About on SuperTechFans
酷 壳 – CoolShell
酷 壳 – CoolShell
爱范儿
爱范儿
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
U
Unit 42
B
Blog
M
MIT News - Artificial intelligence
N
Netflix TechBlog - Medium

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
3D Zig Zag Matrix
Dan · 2026-05-22 · via DEV Community

Project Overview
3D Zig-Zag Matrix — a small interactive visual that renders a zig‑zag numbered matrix as a rotating 3D wave of colored points on an HTML canvas. It started as a compact demo combining a classic zig‑zag matrix generator with a simple perspective projection and animation. I finished it by polishing the visuals, fixing projection/rotation math, adding responsive canvas sizing, and improving the demo copy for the GitHub/DEV submission.

Polished DEV Submission (ready to paste)
What I Built

I built a small interactive demo called 3D Zig‑Zag Matrix that visualizes a zig‑zag traversal of an
𝑛
×
𝑛
matrix as a rotating 3D wave of colored points. The project combines a compact algorithmic generator with a lightweight 3D projection and animation loop so you can see the zig‑zag order come alive.

Demo

Live demo: (paste your hosted URL here)

Screenshots / GIF: Add a short GIF or screenshot showing the rotating wave.

How to run locally: Clone the repo, open index.html in a browser, or serve with a static server.

The Comeback Story

The project began as a small codepen-style prototype with working logic but rough visuals and a few bugs in the projection and resizing behavior. To finish it up I:

Fixed the 3D projection and rotation math so the grid rotates smoothly.

Made the canvas responsive to window resizes and device pixel ratio.

Added a wave effect tied to the zig‑zag index for a more organic motion.

Cleaned up the code and added comments so others can extend it.

My Experience with GitHub Copilot

GitHub Copilot helped speed up the iteration loop: it suggested the initial projection formula, offered small refactors for the animation loop, and proposed color cycling logic. I reviewed and adapted the suggestions to match the visual style I wanted.

How to Run Locally
Save the HTML below as index.html and the JavaScript as zigzag.js in the same folder.

Open index.html in a modern browser (Chrome, Edge, Firefox).

Optionally serve with a static server (e.g., npx http-server) for a stable local URL.

Improved Code
index.html

html
<!doctype html>

3D Zig-Zag Matrix

<br> :root { background: #000; }<br> html,body { height:100%; margin:0; }<br> body {<br> display:flex;<br> align-items:center;<br> justify-content:center;<br> background:#000;<br> color:#fff;<br> font-family:system-ui,Segoe UI,Roboto,Helvetica,Arial,sans-serif;<br> }<br> canvas { display:block; width:100%; height:100vh; }<br> .ui {<br> position:fixed;<br> left:12px;<br> top:12px;<br> z-index:10;<br> background:rgba(0,0,0,0.4);<br> padding:8px 10px;<br> border-radius:8px;<br> backdrop-filter:blur(4px);<br> color:#fff;<br> font-size:13px;<br> }<br> .ui input { width:48px; }<br>

Size:
Cell:

zigzag.js

javascript
// Zig-zag matrix generator
function createZigZagMatrix(n) {
const matrix = Array.from({ length: n }, () => Array(n).fill(0));
let num = 0;
for (let d = 0; d < 2 * n - 1; d++) {
if (d % 2 === 0) {
for (let i = Math.min(d, n - 1); i >= Math.max(0, d - n + 1); i--) {
matrix[i][d - i] = num++;
}
} else {
for (let i = Math.max(0, d - n + 1); i <= Math.min(d, n - 1); i++) {
matrix[i][d - i] = num++;
}
}
}
return matrix;
}

// Canvas setup
const canvas = document.getElementById('zigzagCanvas');
const ctx = canvas.getContext('2d', { alpha: false });

function resizeCanvas() {
const dpr = Math.max(1, window.devicePixelRatio || 1);
canvas.width = Math.floor(window.innerWidth * dpr);
canvas.height = Math.floor(window.innerHeight * dpr);
canvas.style.width = window.innerWidth + 'px';
canvas.style.height = window.innerHeight + 'px';
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
}
window.addEventListener('resize', resizeCanvas);
resizeCanvas();

// UI controls
const sizeInput = document.getElementById('sizeInput');
const cellInput = document.getElementById('cellInput');

let size = Math.max(2, Math.min(40, parseInt(sizeInput.value, 10) || 8));
let cellSize = Math.max(8, Math.min(80, parseInt(cellInput.value, 10) || 28));

sizeInput.addEventListener('change', () => {
size = Math.max(2, Math.min(40, parseInt(sizeInput.value, 10) || 8));
resetMatrix();
});
cellInput.addEventListener('change', () => {
cellSize = Math.max(8, Math.min(80, parseInt(cellInput.value, 10) || 28));
});

// Colors
const colors = [
'#FF6B6B', '#FFD93D', '#6BCB77', '#4D96FF', '#9B5DE5',
'#00BBF9', '#FF7AB6', '#F6AE2D', '#2EC4B6', '#FF6F91'
];

// State
let zigZagMatrix = createZigZagMatrix(size);
let angleX = 0;
let angleY = 0;
let time = 0;

function resetMatrix() {
zigZagMatrix = createZigZagMatrix(size);
}

// Simple 3D rotate and perspective projection
function project3D(x, y, z, cameraZ = 800, fov = 800) {
const zRel = cameraZ - z;
const scale = fov / zRel;
return {
x: x * scale,
y: y * scale,
scale
};
}

function drawMatrix() {
// Clear with slight fade for motion trails
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, canvas.width, canvas.height);

const cx = canvas.width / (2 * (window.devicePixelRatio || 1));
const cy = canvas.height / (2 * (window.devicePixelRatio || 1));

for (let i = 0; i < size; i++) {
for (let j = 0; j < size; j++) {
const value = zigZagMatrix[i][j];
// center grid around origin
const x0 = (j - (size - 1) / 2) * cellSize;
const y0 = (i - (size - 1) / 2) * cellSize;
// wave along value index and time
const wave = Math.sin(value * 0.25 + time * 0.02) * (cellSize * 0.9);
let x = x0;
let y = y0;
let z = wave;

  // rotate around Y then X
  const cosY = Math.cos(angleY), sinY = Math.sin(angleY);
  const cosX = Math.cos(angleX), sinX = Math.sin(angleX);

  // rotate Y
  let rx = x * cosY - z * sinY;
  let rz = x * sinY + z * cosY;
  // rotate X
  let ry = y * cosX - rz * sinX;
  rz = y * sinX + rz * cosX;

  const p = project3D(rx, ry, rz + 400, 1000, 1000);
  const screenX = cx + p.x;
  const screenY = cy + p.y;

  // size based on depth
  const radius = Math.max(2, 8 * p.scale);

  ctx.beginPath();
  ctx.fillStyle = colors[value % colors.length];
  ctx.globalAlpha = 0.95;
  ctx.arc(screenX, screenY, radius, 0, Math.PI * 2);
  ctx.fill();

  // subtle highlight
  ctx.beginPath();
  ctx.globalAlpha = 0.25;
  ctx.fillStyle = '#fff';
  ctx.arc(screenX - radius * 0.35, screenY - radius * 0.35, Math.max(0.6, radius * 0.35), 0, Math.PI * 2);
  ctx.fill();
  ctx.globalAlpha = 1;
}

}

// animate
angleX += 0.007;
angleY += 0.01;
time += 1;
requestAnimationFrame(drawMatrix);
}

drawMatrix();
Notes and Suggestions
Hosting: Use GitHub Pages for a quick demo URL. Add the demo link to your DEV post.

Accessibility: Add keyboard controls to pause/step the animation and ARIA labels for the UI.

Extensions: Try rendering lines between points in zig‑zag order, or add a depth-sorted glow for a neon look.

Performance: For very large sizes, consider OffscreenCanvas or WebGL for faster rendering.