DEVLOG :
Project: PixieR
Version: 2.0.0
Type: Web App (100% client-side)
Stack: Vanilla JS + Canvas API + CSS
License: MIT
Status: Beta
[+] Built:
- Basic HTML structure with card-based UI
- File upload with drag & drop support
- Canvas setup for pixelation using Canvas API
- Dark/light theme toggle with CSS custom properties
- Interactive grid background with cursor glow effect
[+] Pixelation Engine:
- doPixelate() function that downsamples images
- Three scale modes: Fit, Stretch, Crop
- Realtime preview with 120ms debounce
- Custom grid size input (4×4 to 1024×1024)
- Preset chips: 16, 32, 64, 128, 256
- Linked dimensions toggle (🔗 / 🔓)
[+] How pixelation works:
Original Image
↓ drawImage(src, 0, 0, pixelW, pixelH)
Tiny Canvas (W×H pixels)
↓ CSS image-rendering: pixelated
Final display (zoomed with crisp edges)
[+] Core Code Snippet:
const small = document.createElement('canvas');
small.width = sw; small.height = sh;
const sc = small.getContext('2d');
sc.drawImage(srcImg, 0, 0, sw, sh);
out.getContext('2d').drawImage(small, 0, 0);
[+] Key Decisions:
- No frameworks → keep it lightweight (~18KB)
- Single HTML file → easy to share, no build step
- Canvas API → native browser support, fast
[+] Challenges & Solutions:
Challenge: Crop mode required calculating source coordinates
Solution: Used aspect ratio comparison to determine sx, sy, sW, sH
Challenge: Maintaining aspect ratio in Fit mode
Solution: Compare pw/ph vs srcRatio to determine scaling axis
Challenge: Making chips highlight correctly on value change
Solution: setChipActive() toggles .on class based on value
[+] View Modes:
- Side by Side (split-view)
- Compare Slider (drag to compare original vs pixelated)
- Pixel Only (fullscreen pixel art display)
[+] Compare Slider Implementation:
/* Clip the pixelated layer */
#compare-pixel {
clip-path: inset(0 50% 0 0);
}
Drag updates percentage → changes clip-path value dynamically.
Supports both mouse and touch events for mobile.
[+] Eyedropper Tool:
- Hover over any pixel to see hex color
- Click to copy hex code to clipboard
- Tooltip follows cursor with color preview
[+] Eyedropper Logic:
pixelCanvas.addEventListener('mousemove', (e) => {
const cx = Math.floor((e.clientX - rect.left) / zoom);
const cy = Math.floor((e.clientY - rect.top) / zoom);
const px = ctx.getImageData(cx, cy, 1, 1).data;
const hex = '#' + px[0].toString(16) + ...;
tip.innerHTML = `${hex} (${cx},${cy})`;
});
[+] Export Features:
- Download as PNG, JPG, or WebP
- Automatic filename: pixier_{W}x{H}.ext
[+] Zoom Slider:
- Range: 1× to 20×
- CSS-based scaling, doesn’t re-render
- Maintains crisp pixelated edges
[+] The “Pixelate!” Button Experience:
- Disabled until image loaded
- 5-second “processing” animation (UX theater)
- Controls unlock after first conversion
- Shimmer effect on completion
- After first use: realtime updates (120ms debounce)
Comments 0
No comments yet. Be the first!
Sign in to join the conversation.