我把我的Portfolio藏在漆黑中。Google Gemini帮助我点燃了火把。
Source: Dev.to
这是对Built with Google Gemini: Writing Challenge的提交
我用 Google Gemini 构建的项目
作品集本该展示你作为工程师的独特之处。然而,随着时间的推移,我们都开始做同样的事:一个简洁的页眉、一组弹性的 CSS 网格项目卡片,以及一个巨大的“联系我”按钮。我意识到,发现工程师作品的最佳方式并不仅仅是阅读内容本身,而是发现的过程本身。
于是,我决定把我的整个简历投进漆黑之中。
我打造了 交互式手电筒作品集——一个实验性的、移动优先的单页应用(SPA),屏幕始终保持全黑。唯一阅读我的个人简介、技能或查看项目的方式,是在屏幕上拖动一个虚拟的、闪烁的“手电筒”,在黑暗中切出一块光亮的区域。
我没有使用 React、Next.js 或任何大型库,而是纯粹用 HTML、CSS 和原生 DOM 操作来实现。计算移动手电筒的物理效果并处理复杂的 HTML5 Canvas 混合模式本会是个巨大的难题——直到 Google Gemini 作为我的数学搭档程序员出现。
演示
您可以在 Google Cloud Run 部署上实时体验作品集(使用轻量级 nginx:alpine 镜像进行容器化)。无需额外设置——只需打开链接并开始拖动火把。
Source:
我学到的内容
高级 Canvas 混合模式(技术深度)
我加深了对 HTML5 Canvas API 的理解,尤其是 globalCompositeOperation。目标是渲染全黑画面,并在鼠标移动的地方“切出”一个透明孔。Gemini 帮我实现了这段逻辑,同时不影响浏览器的帧率:
// Fill the screen with darkness
ctx.fillStyle = '#050505';
ctx.globalCompositeOperation = 'source-over';
ctx.fillRect(0, 0, width, height);
// "Cut out" the darkness using the glowing gradient
ctx.globalCompositeOperation = 'destination-out';
ctx.fillStyle = gradient; // radial gradient for soft edges
ctx.beginPath();
ctx.arc(startX, startY, maxRadius, 0, Math.PI * 2);
ctx.fill();
掌握如何在同一个 <canvas> 元素上叠加 destination-out(手电筒光束)和 screen/lighter(环境火焰光晕)令人非常有成就感。
将物理机制转化为交互
普通的自定义光标感觉轻飘飘的。我希望我的火把感觉沉重。与 Gemini 合作让我学会如何把视觉物理学转化为可执行的提示。我描述了逻辑:“根据鼠标移动速度让火把像沉重的摆锤一样倾斜”,Gemini 生成了必要的 Math.cos 和 Math.sin 旋转矩阵,使 SVG 火把在枢轴上真实摆动。
原生性能的力量
仅依赖 requestAnimationFrame 和 Canvas 上下文,而不使用虚拟 DOM 差分,使得应用瞬间加载,并在渲染数百个受数学驱动的火焰粒子时仍能保持流畅的 60 FPS。
Google Gemini 反馈
什么做得很出色
Gemini 在长时间的架构讨论中保持上下文的能力无与伦比。当我从现代手电筒切换到中世纪风格的木质火把时,我只需让 Gemini “将手电筒元素改为冒火的木质火把,但保留噪声叠加和我们之前讨论的物理”。它在尊重现有 z‑index 层的前提下生成了新的 SVG 坐标。将摩擦、重力和摆动等概念转化为 JavaScript 数学公式,为我节省了在 MDN 文档中查找的数小时。
我遇到的阻力
我必须明确提示 Gemini 对移动端触摸事件进行优化。火把效果最初在桌面上 mousemove 能正常工作,但在 touchmove/touchstart 上却不行,导致滚动异常。Gemini 最终提供了正确的代码(添加 { passive: true }),但我必须先发现这个问题。它有时还需要被引导使用原生 CSS Flexbox 方案,而不是立即使用 JavaScript 视口计算来实现隐藏内容的网格布局。
