// FormasMemphis: o repertório de formas do estilo (zigue-zague, rabisco ondulado, triângulo, círculo, meia-lua, mais, grade de pontos) // que estouram, giram e flutuam. `formas` posiciona cada uma; `preset: 'cantos'` espalha 8 formas em volta do conteúdo. import React from 'react'; import {COR, mola, seg, useF} from '../base'; export type TipoForma = 'zigue' | 'onda' | 'triangulo' | 'circulo' | 'meia' | 'mais' | 'pontos' | 'anel'; export type Forma = {tipo: TipoForma; x: number; y: number; tam?: number; cor?: string; rot?: number; atraso?: number}; export type FormasMemphisProps = {formas?: Forma[]; preset?: 'cantos' | 'chuva'; inicio?: number}; const PRESETS: Record = { cantos: [ {tipo: 'zigue', x: 200, y: 250, tam: 260, cor: COR.azul, rot: -12}, {tipo: 'circulo', x: 930, y: 270, tam: 200, cor: COR.rosa}, {tipo: 'triangulo', x: 880, y: 1090, tam: 260, cor: COR.turquesa, rot: 18}, {tipo: 'onda', x: 190, y: 1130, tam: 280, cor: COR.roxo, rot: 8}, {tipo: 'mais', x: 90, y: 700, tam: 120, cor: COR.preto, rot: 12}, {tipo: 'pontos', x: 960, y: 700, tam: 200, cor: COR.preto}, {tipo: 'meia', x: 560, y: 190, tam: 160, cor: COR.laranja, rot: 20}, {tipo: 'anel', x: 520, y: 1230, tam: 170, cor: COR.rosa}, ], chuva: Array.from({length: 14}, (_, i) => ({tipo: (['zigue', 'circulo', 'triangulo', 'onda', 'mais', 'anel', 'meia'] as TipoForma[])[i % 7], x: 80 + ((i * 337) % 920), y: 230 + ((i * 211) % 1050), tam: 130 + (i % 3) * 50, cor: [COR.rosa, COR.azul, COR.turquesa, COR.roxo, COR.laranja][i % 5], rot: (i * 37) % 60 - 30, atraso: i})), }; const Desenho: React.FC<{tipo: TipoForma; tam: number; cor: string}> = ({tipo, tam, cor}) => { const s = {stroke: COR.preto, strokeWidth: 8, strokeLinejoin: 'round' as const, strokeLinecap: 'round' as const}; const sombra = `drop-shadow(10px 10px 0 ${COR.preto})`; const base = {width: tam, height: tam, overflow: 'visible' as const, filter: sombra}; switch (tipo) { case 'zigue': return ; case 'onda': return ; case 'triangulo': return ; case 'circulo': return ; case 'anel': return ; case 'meia': return ; case 'mais': return ; default: return {Array.from({length: 25}).map((_, i) => )}; } }; export const FormasMemphis: React.FC = ({formas, preset = 'cantos', inicio = 0}) => { const f = useF() - inicio; const lista = formas ?? PRESETS[preset]; return <>{lista.map((s, i) => { const t0 = (s.atraso ?? i) * 2.5; const p = mola(seg(f, t0, t0 + 12), 3); const tam = s.tam ?? 160; const flut = Math.sin(f / 10 + i * 1.7) * 14; const gira = (s.rot ?? 0) + (1 - p) * 120 + (s.tipo === 'circulo' || s.tipo === 'anel' || s.tipo === 'pontos' ? 0 : Math.sin(f / 18 + i) * 8) + (s.tipo === 'mais' ? f * 3 : 0); return
; })}; };