eletrotupi / tcc/ commit / 85435e3

api: fix icons on glide animation, add logo, drop giant square img

Pedro Lucas Porcellis porcellis@eletrotupi.com 20 days ago 85435e34bb5cc0625f3ec5d629a5f44a728632a7
Parents: a929bda
3 file(s) changed
  • api/src/static/index.html +8 -10
  • api/src/static/js/app.js +6 -52
  • api/src/static/styles/main.css +8 -0
api/src/static/index.html
1 1
<!DOCTYPE html>
2 2
<html class="light" lang="pt-BR">
3 3
  <head>
4 4
    <meta charset="utf-8"/>
5 5
    <meta content="width=device-width, initial-scale=1.0" name="viewport"/>
▸ 63 unchanged lines
69 69
  </head>
70 70

71 71
  <body class="text-text-primary">
72 72
    <header class="docked full-width top-0 sticky z-50 bg-surface-light/95 backdrop-blur-md border-b border-border-subtle shadow-sm">
73 73
      <nav class="flex justify-between items-center w-full px-container-padding max-w-7xl mx-auto h-16">
74 -
        <div class="text-headline-lg font-headline-lg text-text-primary">nexo</div>
74 +
        <div class="flex items-center gap-2">
75 +
          <img src="/images/logo.svg" alt="" class="w-6 h-6 spin-slow" />
76 +
          <span class="text-headline-lg font-headline-lg text-text-primary">nexo</span>
77 +
        </div>
75 78
        <div class="hidden md:flex gap-8">
76 79
          <a class="text-text-primary font-bold border-b-2 border-status-active-bg transition-colors duration-200" href="#">
77 80
            Funcionalidades
78 81
          </a>
79 82

▸ 36 unchanged lines
116 119
          </div>
117 120
        </div>
118 121

119 122
        <div class="flex-1 relative flex items-center justify-center">
120 123
          <div class="absolute -top-12 -left-12 w-64 h-64 bg-brand-green/10 rounded-full blur-3xl animate-pulse"></div>
121 -
          <div id="logo-container" class="relative z-10 w-64 h-64 md:w-80 md:h-80 cursor-pointer select-none">
122 -
            <img id="logo-img" alt="nexo" src="/images/logo.svg" class="w-full h-full" />
123 -
          </div>
124 +
          <div id="logo-container" class="relative z-10 w-64 h-64 md:w-80 md:h-80 cursor-pointer select-none"></div>
124 125
        </div>
125 126
      </section>
126 127

127 128
      <section class="bg-surface-light py-20 border-y border-border-subtle">
128 129
        <div class="max-w-7xl mx-auto px-container-padding">
▸ 10 unchanged lines
139 140
                  <div class="bg-background-light p-8 rounded-xl border border-border-subtle h-full group hover:shadow-md transition-shadow">
140 141
                    <div class="w-12 h-12 bg-pill-indigo rounded-lg flex items-center justify-center mb-6">
141 142
                      <svg class="w-6 h-6 text-indigo-600 morph-icon" viewBox="0 0 24 24" fill="currentColor">
142 143
                        <defs>
143 144
                          <path class="morph-resting" d="M12 3 L13 10 L20 8 L14 12 L20 16 L13 14 L12 21 L11 14 L4 16 L10 12 L4 8 L11 10 Z"/>
144 -
                          <path class="morph-alt" d="M12 1 L13 10 L22 7 L14 12 L22 17 L13 14 L12 23 L11 14 L2 17 L10 12 L2 7 L11 10 Z"/>
145 -
                          <path class="morph-shape" d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z"/>
145 +
                          <path class="morph-shape" d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>
146 146
                        </defs>
147 147
                        <path d="M12 3 L13 10 L20 8 L14 12 L20 16 L13 14 L12 21 L11 14 L4 16 L10 12 L4 8 L11 10 Z"/>
148 148
                      </svg>
149 149
                    </div>
150 150
                    <h3 class="font-headline-md text-xl mb-3">Monitoramento de Humor</h3>
▸ 12 unchanged lines
163 163
                  <div class="bg-background-light p-8 rounded-xl border border-border-subtle h-full group hover:shadow-md transition-shadow">
164 164
                    <div class="w-12 h-12 bg-pill-purple rounded-lg flex items-center justify-center mb-6">
165 165
                      <svg class="w-6 h-6 text-purple-600 morph-icon" viewBox="0 0 24 24" fill="currentColor">
166 166
                        <defs>
167 167
                          <path class="morph-resting" d="M12 3 L13 10 L20 8 L14 12 L20 16 L13 14 L12 21 L11 14 L4 16 L10 12 L4 8 L11 10 Z"/>
168 -
                          <path class="morph-alt" d="M12 2 L15 8 L21 7 L17 12 L21 17 L15 16 L12 22 L9 16 L3 17 L7 12 L3 7 L9 8 Z"/>
169 -
                          <path class="morph-shape" d="M20 6h-4V4c0-1.1-.9-2-2-2h-4c-1.1 0-2 .9-2 2v2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zM10 4h4v2h-4V4zm10 16H4V8h16v12z M13 10h-2v3H8v2h3v3h2v-3h3v-2h-3z"/>
168 +
                          <path class="morph-shape" d="M17 11h-4V7h-2v4H7v2h4v4h2v-4h4z"/>
170 169
                        </defs>
171 170
                        <path d="M12 3 L13 10 L20 8 L14 12 L20 16 L13 14 L12 21 L11 14 L4 16 L10 12 L4 8 L11 10 Z"/>
172 171
                      </svg>
173 172
                    </div>
174 173
                    <h3 class="font-headline-md text-xl mb-3">Gestão de Saúde</h3>
▸ 10 unchanged lines
185 184
                  <div class="bg-background-light p-8 rounded-xl border border-border-subtle h-full group hover:shadow-md transition-shadow">
186 185
                    <div class="w-12 h-12 bg-pill-blue rounded-lg flex items-center justify-center mb-6">
187 186
                      <svg class="w-6 h-6 text-blue-600 morph-icon" viewBox="0 0 24 24" fill="currentColor">
188 187
                        <defs>
189 188
                          <path class="morph-resting" d="M12 3 L13 10 L20 8 L14 12 L20 16 L13 14 L12 21 L11 14 L4 16 L10 12 L4 8 L11 10 Z"/>
190 -
                          <path class="morph-alt" d="M17 4 L14 11 L21 12 L14 13 L17 20 L12 14 L7 20 L10 13 L3 12 L10 11 L7 4 L12 10 Z"/>
191 -
                          <path class="morph-shape" d="M9.27 4.49c-1.63 7.54 3.75 12.41 7.66 13.8A7.993 7.993 0 0 1 12 20c-4.41 0-8-3.59-8-8 0-3.45 2.2-6.4 5.27-7.51m2.72-2.48C6.4 2.01 2 6.54 2 12c0 5.52 4.48 10 10 10 3.71 0 6.93-2.02 8.66-5.02-7.51-.25-12.09-8.43-8.32-14.97h-.35z"/>
189 +
                          <path class="morph-shape" d="M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9 9-4.03 9-9c0-.46-.04-.92-.1-1.36-.98 1.37-2.58 2.26-4.4 2.26-2.98 0-5.4-2.42-5.4-5.4 0-1.81.89-3.42 2.26-4.4-.44-.06-.9-.1-1.36-.1z"/>
192 190
                        </defs>
193 191
                        <path d="M12 3 L13 10 L20 8 L14 12 L20 16 L13 14 L12 21 L11 14 L4 16 L10 12 L4 8 L11 10 Z"/>
194 192
                      </svg>
195 193
                    </div>
196 194

▸ 204 unchanged lines
401 399
    <script src="https://cdn.jsdelivr.net/npm/atropos/atropos.min.js"></script>
402 400
    <script src="/js/app.js">
403 401
    </script>
404 402
  </body>
405 403
</html>
api/src/static/js/app.js
1 1
const { animate, utils, stagger, splitText, morphTo } = anime;
2 2

3 3
// Motion path: glowing dot traces the logo outline.
4 4
// morphTo on hover: logo → 16-pt star, tries to mimic the logo
5 5

▸ 103 unchanged lines
109 109
  });
110 110

111 111
  svg.appendChild(trail);
112 112
  svg.appendChild(dot);
113 113

114 -
  const img = container.querySelector('img');
115 -
  if (img) container.replaceChild(svg, img);
116 -
  else container.appendChild(svg);
114 +
  container.appendChild(svg);
117 115

118 116
  // Motion path
119 117
  const totalLen = logoPathEl.getTotalLength();
120 118
  if (!totalLen) return;
121 119

▸ 86 unchanged lines
208 206
    });
209 207

210 208
  setupLogoAnimations();
211 209

212 210
  document.querySelectorAll('.glide__slide .morph-icon').forEach(svg => {
213 -
    const path = svg.querySelector(':scope > path');
211 +
    const path    = svg.querySelector(':scope > path');
214 212
    const resting = svg.querySelector('defs .morph-resting');
215 -
    const alt = svg.querySelector('defs .morph-alt');
216 -
    const shape = svg.querySelector('defs .morph-shape');
217 -
    const card = svg.closest('.group');
218 -

219 -
    let hovered = false;
220 -
    let spikeCycle = null;
221 -

222 -
    const rotAnim = animate(svg, {
223 -
      rotate: 360,
224 -
      loop: true,
225 -
      duration: 7000,
226 -
      ease: 'linear',
227 -
    });
228 -

229 -
    function runSpikeCycle() {
230 -
      if (hovered) return;
231 -
      const targets = [resting, alt];
232 -
      let i = 0;
233 -

234 -
      function step() {
235 -
        if (hovered) return;
236 -
        i = (i + 1) % targets.length;
237 -
        spikeCycle = animate(path, {
238 -
          d: morphTo(targets[i]),
239 -
          duration: 1800,
240 -
          ease: 'inOutSine',
241 -
          onComplete: () => setTimeout(step, 600),
242 -
        });
243 -
      }
244 -
      step();
245 -
    }
246 -

247 -
    runSpikeCycle();
213 +
    const shape   = svg.querySelector('defs .morph-shape');
214 +
    const card    = svg.closest('.group');
248 215

249 216
    card.addEventListener('pointerenter', () => {
250 -
      hovered = true;
251 -
      spikeCycle?.pause();
252 -
      rotAnim.pause();
253 -
      animate(path, { d: morphTo(shape), duration: 500, ease: 'inOutCubic' });
217 +
      animate(path, { d: morphTo(shape),   duration: 500, ease: 'inOutCubic' });
254 218
    });
255 -

256 219
    card.addEventListener('pointerleave', () => {
257 -
      hovered = false;
258 -
      animate(path, {
259 -
        d: morphTo(resting),
260 -
        duration: 500,
261 -
        ease: 'inOutCubic',
262 -
        onComplete: () => {
263 -
          rotAnim.play();
264 -
          runSpikeCycle();
265 -
        },
266 -
      });
220 +
      animate(path, { d: morphTo(resting), duration: 500, ease: 'inOutCubic' });
267 221
    });
268 222
  });
269 223
});
api/src/static/styles/main.css
1 1
body {
2 2
  font-family: 'Inter', sans-serif; background-color: #f6f8f6;
3 3
}
4 4

5 5
.material-symbols-outlined {
▸ 10 unchanged lines
16 16

17 17
.morph-icon {
18 18
  transform-origin: center;
19 19
}
20 20

21 +
@keyframes spin-slow {
22 +
  to { transform: rotate(360deg); }
23 +
}
24 +

25 +
.spin-slow {
26 +
  animation: spin-slow 12s linear infinite;
27 +
}
28 +

21 29
.btn-hover-effect {
22 30
  transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
23 31
}
24 32

25 33
.btn-hover-effect:active {
26 34
  transform: scale(0.95);
27 35
}