Wireframe Globe Arc
介绍
画布绘制的点线线框地球缓慢自转,近处点更亮更大,一条粉到蓝的渐变弧线在两点间反复描绘,底部有蓝粉色呼吸光晕;左上角放标题与说明,适合做全球可用的背景。
拆自整页模板 念成 AI 应用构建器首页,可以单独使用,也能和同一模板拆出的其他组件拼回整页。
纯 HTML、CSS 与少量原生 JS,没有框架依赖。复制提示词交给 Claude Code、Cursor、Trae 或 Codex,模型会把 Wireframe Globe Arc 加进你的项目并换成你的配色。
适用场景
首屏、登录页和发布页的背景层:给大面积留白加一点质感,又不抢正文。
安装
订阅 Builder 后,用 8pt CLI 装进项目,或在已接入 8pt MCP 的编辑器里直接调用。
$ npm i -g @8pt-dev/cli && 8pt add wireframe-globe-arc
mcp › 使用 8pt MCP 调用 get_component("wireframe-globe-arc")
代码
Wireframe Globe Arc 的源码,动效只用 transform 与 opacity,并尊重减少动态效果设置。
<section class="x-wga"><canvas class="glb" aria-hidden="true"></canvas><span class="wga-glow"></span><div class="wga-cap"><h3>随时随地,都能用</h3><p>网页、平板与手机自动适配,访客在哪儿打开都顺手。</p></div></section>
.x-wga{--ink:#1C1C1A;--mut:#5F5F5B;--line:#E9E7E1;--cream:#FCFBF8;--card:#F5F4EF;--blue:#4C7DFF;--pink:#FF66CC;--red:#FF2E63;--org:#FF7A1A;font-family:"Inter","Noto Sans SC","PingFang SC","Microsoft YaHei",system-ui,sans-serif;-webkit-font-smoothing:antialiased;text-align:left;color:var(--ink)}.x-wga,.x-wga *{box-sizing:border-box}.x-wga a{color:inherit;text-decoration:none}.x-wga button{font:inherit;cursor:pointer;color:inherit}.x-wga img{display:block;max-width:100%}.x-wga{position:relative;width:100%;max-width:1100px;height:640px;margin:0 auto;border-radius:22px;background:radial-gradient(60% 60% at 50% 45%,#202128,#141518);box-shadow:inset 0 0 0 1px rgba(255,255,255,.07);overflow:hidden;color:#fff}.x-wga .glb{position:absolute;left:0;top:0;width:100%;height:88%}.x-wga .wga-glow{position:absolute;left:-10%;right:-10%;bottom:-30%;height:55%;border-radius:50%;background:radial-gradient(closest-side,#B9CBFF,#4C6FFF 45%,rgba(255,102,204,.45) 72%,transparent);filter:blur(24px);animation:wgaG 6s ease-in-out infinite alternate}@keyframes wgaG{to{transform:scale(1.06);opacity:.8}}.x-wga .wga-cap{position:absolute;left:34px;top:30px;max-width:340px}.x-wga h3{margin:0 0 6px;font-size:20px;font-weight:600;letter-spacing:-.02em}.x-wga p{margin:0;font-size:13.5px;line-height:1.6;color:#AFAFAA}@media (max-width:640px){.x-wga{height:480px}}@media (prefers-reduced-motion:reduce){.x-wga *,.x-wga *::before,.x-wga *::after{animation:none!important;transition:none!important}}.x-wga{background-image:radial-gradient(rgba(255,255,255,.09) 1px,transparent 1.4px),radial-gradient(60% 60% at 50% 45%,#202128,#141518);background-size:16px 16px,100% 100%;height:700px}.x-wga{width:1100px;max-width:100%;box-sizing:border-box}(root) => {const drawGlobe=(cv)=>{const ctx=cv.getContext('2d');const N=220,P=[],E=[];const ga=Math.PI*(3-Math.sqrt(5));for(let i=0;i<N;i++){const y=1-(i/(N-1))*2,r=Math.sqrt(1-y*y),t=ga*i;P.push([Math.cos(t)*r,y,Math.sin(t)*r])}
for(let i=0;i<N;i++)for(let j=i+1;j<N;j++){const dx=P[i][0]-P[j][0],dy=P[i][1]-P[j][1],dz=P[i][2]-P[j][2];if(dx*dx+dy*dy+dz*dz<0.058)E.push([i,j])}
const ll=(la,lo)=>{la*=Math.PI/180;lo*=Math.PI/180;return [Math.cos(la)*Math.cos(lo),Math.sin(la),Math.cos(la)*Math.sin(lo)]};const A=ll(28,-60),B=ll(-12,40);
let W=0,H=0,dpr=1,raf,a=0,prog=0;const red=matchMedia('(prefers-reduced-motion: reduce)').matches;
const fit=()=>{dpr=Math.min(2,devicePixelRatio||1);W=cv.clientWidth;H=cv.clientHeight;cv.width=W*dpr;cv.height=H*dpr};fit();const ro=new ResizeObserver(fit);ro.observe(cv);
const rot=(p)=>{const c=Math.cos(a),s=Math.sin(a),t=0.32,ct=Math.cos(t),st=Math.sin(t);let x=p[0]*c-p[2]*s,z=p[0]*s+p[2]*c,y=p[1];const y2=y*ct-z*st,z2=y*st+z*ct;return [x,y2,z2]};
const frame=()=>{ctx.setTransform(dpr,0,0,dpr,0,0);ctx.clearRect(0,0,W,H);const R=Math.min(W,H)*0.42,cx=W/2,cy=H/2;const Q=P.map(rot);
ctx.lineWidth=0.6;for(const [i,j] of E){const z=(Q[i][2]+Q[j][2])/2;ctx.strokeStyle='rgba(200,210,255,'+(0.05+0.22*(z+1)/2)+')';ctx.beginPath();ctx.moveTo(cx+Q[i][0]*R,cy-Q[i][1]*R);ctx.lineTo(cx+Q[j][0]*R,cy-Q[j][1]*R);ctx.stroke()}
for(const q of Q){const z=(q[2]+1)/2;ctx.fillStyle='rgba(255,255,255,'+(0.15+0.85*z)+')';ctx.beginPath();ctx.arc(cx+q[0]*R,cy-q[1]*R,0.6+1.4*z,0,7);ctx.fill()}
const a1=rot(A),b1=rot(B);const pts=[];for(let k=0;k<=40;k++){const t=k/40;let x=a1[0]*(1-t)+b1[0]*t,y=a1[1]*(1-t)+b1[1]*t,z=a1[2]*(1-t)+b1[2]*t;const l=Math.hypot(x,y,z)||1,h=1+0.25*Math.sin(Math.PI*t);pts.push([cx+x/l*h*R,cy-y/l*h*R])}
const n=Math.max(2,Math.min(41,Math.floor(prog*40)));const gr=ctx.createLinearGradient(pts[0][0],pts[0][1],pts[40][0],pts[40][1]);gr.addColorStop(0,'#FF4FA3');gr.addColorStop(1,'#5B8CFF');ctx.strokeStyle=gr;ctx.lineWidth=2.2;ctx.beginPath();ctx.moveTo(pts[0][0],pts[0][1]);for(let k=1;k<n;k++)ctx.lineTo(pts[k][0],pts[k][1]);ctx.stroke();
for(const [p,c] of [[pts[0],'#FF4FA3'],[pts[n-1],'#5B8CFF']]){ctx.fillStyle=c;ctx.beginPath();ctx.arc(p[0],p[1],4,0,7);ctx.fill();ctx.strokeStyle='rgba(255,255,255,.9)';ctx.lineWidth=1.5;ctx.stroke()}
…订阅 Builder 查看完整源码。查看价格