forked from rajun/ar-test
feat: add AR phone illustration component
This commit is contained in:
parent
bcb0b5fc69
commit
c9c36d5fa3
129
app/components/auth/ar-illustration.tsx
Normal file
129
app/components/auth/ar-illustration.tsx
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
import { Armchair } from '~/components/auth/armchair';
|
||||||
|
|
||||||
|
export function ArIllustration() {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 400 460"
|
||||||
|
className="h-auto w-full max-w-[380px] animate-[float_7s_ease-in-out_infinite] drop-shadow-[0_30px_60px_rgba(0,0,0,0.6)]"
|
||||||
|
role="img"
|
||||||
|
aria-label="An armchair placed in a room through a phone camera in augmented reality"
|
||||||
|
>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="chair-back" x1="0" y1="0" x2="1" y2="1">
|
||||||
|
<stop offset="0%" stopColor="#fb923c" />
|
||||||
|
<stop offset="55%" stopColor="#c2410c" />
|
||||||
|
<stop offset="100%" stopColor="#7c2d12" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="chair-back-inner" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0%" stopColor="#f97316" />
|
||||||
|
<stop offset="100%" stopColor="#9a3412" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="chair-cushion" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0%" stopColor="#fdba74" />
|
||||||
|
<stop offset="100%" stopColor="#ea580c" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="chair-base" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0%" stopColor="#c2410c" />
|
||||||
|
<stop offset="100%" stopColor="#7c2d12" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="chair-arm-left" x1="0" y1="0" x2="1" y2="0">
|
||||||
|
<stop offset="0%" stopColor="#9a3412" />
|
||||||
|
<stop offset="100%" stopColor="#ea580c" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="chair-arm-right" x1="0" y1="0" x2="1" y2="0">
|
||||||
|
<stop offset="0%" stopColor="#f97316" />
|
||||||
|
<stop offset="100%" stopColor="#9a3412" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="chair-wood" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0%" stopColor="#92582f" />
|
||||||
|
<stop offset="100%" stopColor="#3f2412" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="ar-screen" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0%" stopColor="#161616" />
|
||||||
|
<stop offset="60%" stopColor="#1a1511" />
|
||||||
|
<stop offset="100%" stopColor="#221810" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="ar-grid-fade" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0%" stopColor="white" stopOpacity="0" />
|
||||||
|
<stop offset="100%" stopColor="white" stopOpacity="1" />
|
||||||
|
</linearGradient>
|
||||||
|
<mask id="ar-grid-mask">
|
||||||
|
<rect x="0" y="200" width="400" height="200" fill="url(#ar-grid-fade)" />
|
||||||
|
</mask>
|
||||||
|
<clipPath id="ar-screen-clip">
|
||||||
|
<rect x="118" y="38" width="164" height="364" rx="24" />
|
||||||
|
</clipPath>
|
||||||
|
<radialGradient id="ar-glow" cx="50%" cy="50%" r="50%">
|
||||||
|
<stop offset="0%" stopColor="#f97316" stopOpacity="0.3" />
|
||||||
|
<stop offset="100%" stopColor="#f97316" stopOpacity="0" />
|
||||||
|
</radialGradient>
|
||||||
|
<filter id="ar-blur" x="-50%" y="-50%" width="200%" height="200%">
|
||||||
|
<feGaussianBlur stdDeviation="5" />
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
{/* Phone body */}
|
||||||
|
<rect x="108" y="28" width="184" height="384" rx="32" fill="#0b0b0b" stroke="#2a2a2a" strokeWidth="2" />
|
||||||
|
<rect x="118" y="38" width="164" height="364" rx="24" fill="url(#ar-screen)" />
|
||||||
|
|
||||||
|
<g clipPath="url(#ar-screen-clip)">
|
||||||
|
{/* Wall / floor horizon */}
|
||||||
|
<rect x="118" y="38" width="164" height="176" fill="white" opacity="0.015" />
|
||||||
|
|
||||||
|
{/* Perspective floor seen through the camera */}
|
||||||
|
<g stroke="#f97316" strokeOpacity="0.3" strokeWidth="1" mask="url(#ar-grid-mask)">
|
||||||
|
{[240, 262, 290, 326, 372].map((y) => (
|
||||||
|
<line key={y} x1="100" y1={y} x2="300" y2={y} />
|
||||||
|
))}
|
||||||
|
{[-260, -170, -90, -30, 30, 90, 170, 260].map((dx) => (
|
||||||
|
<line key={dx} x1="200" y1="214" x2={200 + dx} y2="420" />
|
||||||
|
))}
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<ellipse cx="200" cy="320" rx="96" ry="40" fill="url(#ar-glow)" />
|
||||||
|
|
||||||
|
{/* Placement reticle */}
|
||||||
|
<ellipse cx="200" cy="320" rx="76" ry="19" fill="none" stroke="#f97316" strokeWidth="1.5" strokeDasharray="5 5">
|
||||||
|
<animate attributeName="stroke-dashoffset" from="0" to="-20" dur="2s" repeatCount="indefinite" />
|
||||||
|
</ellipse>
|
||||||
|
<ellipse cx="200" cy="320" rx="60" ry="15" fill="#f97316" fillOpacity="0.12">
|
||||||
|
<animate attributeName="fill-opacity" values="0.18;0.05;0.18" dur="2.4s" repeatCount="indefinite" />
|
||||||
|
</ellipse>
|
||||||
|
|
||||||
|
<Armchair />
|
||||||
|
|
||||||
|
{/* Camera scan brackets */}
|
||||||
|
<g fill="none" stroke="white" strokeOpacity="0.55" strokeWidth="2" strokeLinecap="round">
|
||||||
|
<path d="M136 152 V138 H150" />
|
||||||
|
<path d="M264 152 V138 H250" />
|
||||||
|
<path d="M136 342 V356 H150" />
|
||||||
|
<path d="M264 342 V356 H250" />
|
||||||
|
</g>
|
||||||
|
|
||||||
|
{/* AR badge */}
|
||||||
|
<rect x="180" y="62" width="40" height="18" rx="9" fill="#f97316" fillOpacity="0.15" stroke="#f97316" strokeOpacity="0.6" />
|
||||||
|
<text x="200" y="74.5" textAnchor="middle" fontSize="9" fontWeight="700" letterSpacing="1" fill="#fb923c" fontFamily="Inter, sans-serif">AR</text>
|
||||||
|
|
||||||
|
{/* Shutter */}
|
||||||
|
<circle cx="200" cy="380" r="12" fill="none" stroke="white" strokeOpacity="0.4" strokeWidth="2" />
|
||||||
|
<circle cx="200" cy="380" r="8" fill="#f97316" />
|
||||||
|
</g>
|
||||||
|
|
||||||
|
{/* Notch */}
|
||||||
|
<rect x="172" y="46" width="56" height="8" rx="4" fill="#0b0b0b" />
|
||||||
|
|
||||||
|
{/* Floating particles */}
|
||||||
|
{[
|
||||||
|
{ cx: 70, cy: 120, r: 3, d: '3s' },
|
||||||
|
{ cx: 330, cy: 90, r: 2, d: '4s' },
|
||||||
|
{ cx: 345, cy: 260, r: 3, d: '3.6s' },
|
||||||
|
{ cx: 55, cy: 300, r: 2, d: '4.4s' },
|
||||||
|
{ cx: 95, cy: 210, r: 1.5, d: '2.8s' },
|
||||||
|
].map((p) => (
|
||||||
|
<circle key={`${p.cx}-${p.cy}`} cx={p.cx} cy={p.cy} r={p.r} fill="#f97316">
|
||||||
|
<animate attributeName="opacity" values="0.15;0.8;0.15" dur={p.d} repeatCount="indefinite" />
|
||||||
|
</circle>
|
||||||
|
))}
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user