去年,我有机会与肖恩·王(Shawn Wang)(Swyx)合作就暂时的项目。目标是通过一些创意元素来增强他们的网站。这是一个令人着迷的挑战,因为我更像是一个开发人员,而不是设计师,但我却抓住了扩大设计技能的机会。
我的贡献之一是互动的星空背景。您可以在这里看到它:
使用Perspective和CSS自定义属性的BlockQuote概念。享受@temporalio的创意自由。添加一点点奇思妙想! ⚒️@reaectjs && @tailwindcss(站点是nextjs)?通过@codepen pic.twitter.com/s9xp2trrox链接到codepen
- jhey ??✨(@jh3yy)2021年7月2日
该设计的强度在于它作为可重复使用的React组件的实现,提供了高配置性。需要不同的形状而不是星星?想要精确控制粒子放置吗?您可以完全控制。
让我们构建此组件!我们将使用React,Greensock和HTML<canvas></canvas>
元素。 React是可选的,但使用它为将来的项目创建了可重复使用的组件。
从'https://cdn.skypack.dev/reeact'导入反应'; 从'https://cdn.skypack.dev/reaeact-dom'导入reactdom'; 从'https://cdn.skypack.dev/gsap'导入GSAP'; const root_node = document.queryselector('#app'); const starscape =()=><h1>很酷的东西!</h1> ; const app =()=><starscape></starscape> ; Reactdom.render(<app></app> ,root_node);
首先,我们渲染一个<canvas></canvas>
元素并获取引用以在React的useEffect
挂钩中使用。如果不使用React,请将参考直接存储在变量中。
const starscape =()=> { const canvasref = react.useref(null); 返回<canvas ref="{canvasRef}"></canvas>; };
我们会样式<canvas></canvas>
填充视口并坐在内容的背后:
帆布 { 位置:固定; 插图:0; 背景:#262626; z index:-1; 身高:100VH; 宽度:100VW; }
我们将通过使用具有不同不透明度和尺寸的圆圈来简化星星的渲染。在一个圆上画一个圆<canvas></canvas>
涉及获取上下文并使用arc
功能。让我们使用useEffect
钩在中心渲染一个圆圈(我们的星星):
const starscape =()=> { const canvasref = react.useref(null); const contextref = react.useref(null); react.useeffect(()=> { canvasref.current.width = window.innerwidth; canvasref.current.height = window.innerheight; contextref.current = canvasref.current.getContext('2d'); contextref.current.fillstyle ='Yellow'; contextref.current.beginath(); contextref.current.arc( window.innerwidth / 2,// x window.innerheight / 2,// y 100,//半径 0,//开始角度(弧度) Math.pi * 2 //末端角度(弧度) ); contextref.current.fill(); },[]); 返回<canvas ref="{canvasRef}"></canvas>; };
这会产生一个黄色的圆圈。其余代码将在此useEffect
之内。这就是为什么反应部分是可选的。您可以将此代码适应其他框架。
我们需要生成并渲染多个星星。让我们创建一个LOAD
功能来处理恒星生成和画布设置,包括帆布尺寸:
const load =()=> { const vmin = math.min(window.innerheight,window.innerwidth); const star_count = math.floor(vmin * densepratio); canvasref.current.width = window.innerwidth; canvasref.current.height = window.innerheight; starsref.current = new Array(star_count).fill()。map(()=>({{) x:gsap.utils.random(0,window.innerwidth,1), y:gsap.utils.random(0,window.innerheight,1), 尺寸:gsap.utils.random(1,Sizelimit,1), 比例:1, alpha:gsap.utils.random(0.1,defaultalpha,0.1), })); };
每个恒星都是具有定义其特征(x,y位置,大小,比例,alpha)的属性的对象。 sizeLimit
, defaultAlpha
和densityRatio
是传递给具有默认值的Starscape
组件。
样本星对象:
{ “ x”:1252, “ Y”:29, “大小”:4, “比例”:1, “ alpha”:0.5 }
为了渲染这些恒星,我们创建了一个RENDER
函数,该函数可在stars
阵列上迭代,并使用arc
函数呈现每个恒星:
const Render =()=> { contextref.current.ClearRect( 0, 0, canvasref.current.width, canvasref.current.height ); StarsRef.Current.Foreach((Star)=> { contextref.current.fillstyle =`hsla(0,100%,100%,$ {star.alpha})`; contextref.current.beginath(); contextref.current.arc(star.x,star.y,star.size / 2,0,math.pi * 2); contextref.current.fill(); }); };
clearRect
功能在渲染之前清除了画布,这对于动画至关重要。
完整的Starscape
组件(尚无交互性)如下:
完整的Starscape组件(没有互动性)
const starscape =({denseratio = 0.5,sizelimit = 5,defaultalpha = 0.5})=> { const canvasref = react.useref(null); const contextref = react.useref(null); const starsRef = react.useref(null); react.useeffect(()=> { contextref.current = canvasref.current.getContext('2d'); const load =()=> { const vmin = math.min(window.innerheight,window.innerwidth); const star_count = math.floor(vmin * densepratio); canvasref.current.width = window.innerwidth; canvasref.current.height = window.innerheight; starsref.current = new Array(star_count).fill()。map(()=>({{) x:gsap.utils.random(0,window.innerwidth,1), y:gsap.utils.random(0,window.innerheight,1), 尺寸:gsap.utils.random(1,Sizelimit,1), 比例:1, alpha:gsap.utils.random(0.1,defaultalpha,0.1), })); }; const Render =()=> { contextref.current.ClearRect(0,0,canvasref.current.width,canvasref.current.height); StarsRef.Current.Foreach((Star)=> { contextref.current.fillstyle =`hsla(0,100%,100%,$ {star.alpha})`; contextref.current.beginath(); contextref.current.arc(star.x,star.y,star.size / 2,0,math.pi * 2); contextref.current.fill(); }); }; const run =()=> { 加载(); 使成为(); }; 跑步(); window.addeventListener('resize',run); 返回()=> { window.removeEventListener('resize',run); }; },[]); 返回<canvas ref="{canvasRef}"></canvas>; };
在演示中尝试道具以查看其效果。要处理视口度调整大小,我们调用LOAD
并在调整大小上RENDER
(以优化的措施进行了辩论,此处省略了)。
现在,让我们进行背景互动。当指针移动时,光标附近的恒星会变亮并扩大规模。
我们将添加一个UPDATE
功能来计算指针与每个星星之间的距离,然后使用Greensock的mapRange
实用程序对恒星的比例和Alpha进行补充。我们还将添加scaleLimit
和proximityRatio
props来控制缩放行为。
const update =({x,y})=> { StarsRef.Current.Foreach((Star)=> { const距离= MATH.SQRT(MATH.POW(Star.X -X,2)Math.pow(Star.Y -Y,2)); gsap.to(星,{ 比例:scalemapperref.current(Math.min(距离,vminref.current * proximityratio)),),),),) alpha:alphamapperref.current(Math.min(距离,vminref.current * proximityratio)),),),),) }); }); };
为了渲染更新,我们使用gsap.ticker
( requestAnimationFrame
的一个很好的替代方法),将RENDER
添加到股票中并在清理中删除。我们将每秒(FPS)的帧设置为24。 RENDER
函数现在使用star.scale
值绘制弧线时。
加载(); gsap.ticker.add(渲染); gsap.ticker.fps(24); window.addeventListener('ressize',load); document.AddeventListener('PointerMove',Update); 返回()=> { window.removeEventListener('resize',load); document.removeEventListener('PointerMove',Update); gsap.ticker.remove(渲染); };
现在,当您移动鼠标时,星星会做出反应!
为了处理鼠标离开画布的情况,我们添加了一个pointerleave
事件侦听器,该侦听器将星星重新回到其原始状态:
const exit =()=> { GSAP.TO(StarsRef.Current,{scale:1,alpha:defaultalpha}); }; // ...活动听众... document.AddeventListener(“ Pointerleave”,退出); 返回()=> { // ... 清理 ... Document.RemoveEventListener(“ Pointerleave”,退出); gsap.ticker.remove(渲染); };
让我们添加一个Konami代码复活节彩蛋。如果输入代码,我们将收听键盘事件并触发动画。
const konami_code ='arrowup,arrowup,arrowdown,arrowdown,arrowleft,arrowLight,arrowleft,arrowleft,arrowright,keya,keya'; const coderef = react.useref([]); react.useeffect(()=> { const handlecode =(e)=> { coderef.current = [... coderef.current,e.code] .slice(coderef.current.length> 9?coderef.current.length-length -9:0); if(coderef.current.join(',').tolowercase()=== konami_code.tolowercase()){ //触发复活节彩蛋动画 } }; window.addeventListener('keyup',handlecode); 返回()=> { window.removeEventListener('keyup',handlecode); }; },[]);
带有Konami Code复活节彩蛋的完整的,交互式的Starscape
组件非常冗长,因此在这里省略了。但是,上面概述的原则演示了如何使用React,Greensock和HTML创建功能齐全且可定制的交互式星空背景<canvas></canvas>
。复活节彩蛋动画将涉及创建一个gsap.timeline
。
此示例演示了创建自己的自定义背景所需的技术。请记住要考虑背景如何与您网站的内容相互作用。尝试不同的形状,颜色和动画,以创建独特而引人入胜的视觉效果。
以上是内容的互动星空背景的详细内容。更多信息请关注PHP中文网其他相关文章!