Files
pbakaus_impeccable/public/js/components/lens.js
T
Paul BakausandClaude Opus 4.5 2181137d04 Consolidate skills + add patterns source file
Major changes:
- Consolidate 8 design skills into single frontend-design skill with 7 reference files
- Add source/patterns.md as single source of truth for patterns/antipatterns
- Patterns are merged into skill during build, served via API for website
- Website now dynamically renders both "What TO Do" and "What NOT to Do" sections
- Update build system to handle directory-based skills with references
- Add /api/patterns endpoint to server
- Refactor website with new Antidote section layout

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 14:08:30 -08:00

64 lines
1.8 KiB
JavaScript

export function initLensEffect() {
const container = document.getElementById("lens-comparison");
if (!container) return;
const lensContainer = container.querySelector(".lens-container");
const lensAfter = container.querySelector(".lens-after");
const lensCircle = container.querySelector(".lens-circle");
if (!lensContainer || !lensAfter || !lensCircle) return;
let isHovering = false;
function updateLens(x, y) {
const rect = lensContainer.getBoundingClientRect();
const relX = ((x - rect.left) / rect.width) * 100;
const relY = ((y - rect.top) / rect.height) * 100;
const clampedX = Math.max(25, Math.min(75, relX));
const clampedY = Math.max(30, Math.min(70, relY));
lensAfter.style.clipPath = `circle(120px at ${clampedX}% ${clampedY}%)`;
lensCircle.style.setProperty("--lens-x", `${clampedX}%`);
lensCircle.style.setProperty("--lens-y", `${clampedY}%`);
lensCircle.style.left = `${clampedX}%`;
lensCircle.style.top = `${clampedY}%`;
}
lensContainer.addEventListener("mouseenter", () => {
isHovering = true;
});
lensContainer.addEventListener("mouseleave", () => {
isHovering = false;
// Reset to default position
updateLens(
lensContainer.getBoundingClientRect().left +
lensContainer.offsetWidth * 0.7,
lensContainer.getBoundingClientRect().top +
lensContainer.offsetHeight * 0.5,
);
});
lensContainer.addEventListener("mousemove", (e) => {
if (isHovering) {
updateLens(e.clientX, e.clientY);
}
});
// Touch support
lensContainer.addEventListener("touchmove", (e) => {
e.preventDefault();
const touch = e.touches[0];
updateLens(touch.clientX, touch.clientY);
});
// Initialize at default position
updateLens(
lensContainer.getBoundingClientRect().left +
lensContainer.offsetWidth * 0.7,
lensContainer.getBoundingClientRect().top +
lensContainer.offsetHeight * 0.5,
);
}