From 13cb7960bdc61d1109717853913c55a1b291aece Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Mon, 19 Aug 2024 18:05:02 +0200 Subject: [PATCH] chore(ux): add animated header with anime.js in p2p sections (#3271) feat(p2p): add animated header with anime.js Signed-off-by: Ettore Di Giacinto --- core/http/static/p2panimation.js | 73 ++++++++++++++++++++++++++++++ core/http/views/explorer.html | 62 ++++++++----------------- core/http/views/p2p.html | 26 +++++++---- core/http/views/partials/head.html | 69 ++++++++++++++++++++++++++-- embedded/webui_static.yaml | 4 +- 5 files changed, 178 insertions(+), 56 deletions(-) create mode 100644 core/http/static/p2panimation.js diff --git a/core/http/static/p2panimation.js b/core/http/static/p2panimation.js new file mode 100644 index 00000000..f31ed3f9 --- /dev/null +++ b/core/http/static/p2panimation.js @@ -0,0 +1,73 @@ +const canvas = document.getElementById('networkCanvas'); +const ctx = canvas.getContext('2d'); + +canvas.width = window.innerWidth; +canvas.height = window.innerHeight; + +const particles = []; +const lines = []; + +class Particle { + constructor(x, y) { + this.x = x; + this.y = y; + this.radius = 2 + Math.random() * 2; + this.color = `rgba(0, 255, 204, ${Math.random()})`; + this.speed = Math.random() * 2 + 1; + this.angle = Math.random() * Math.PI * 2; + } + + update() { + this.x += Math.cos(this.angle) * this.speed; + this.y += Math.sin(this.angle) * this.speed; + + if (this.x < 0 || this.x > canvas.width || this.y < 0 || this.y > canvas.height) { + this.x = Math.random() * canvas.width; + this.y = Math.random() * canvas.height; + } + } + + draw() { + ctx.beginPath(); + ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false); + ctx.fillStyle = this.color; + ctx.fill(); + } +} + +function connectParticles() { + for (let i = 0; i < particles.length; i++) { + for (let j = i + 1; j < particles.length; j++) { + const distance = Math.hypot(particles[i].x - particles[j].x, particles[i].y - particles[j].y); + if (distance < 150) { + ctx.beginPath(); + ctx.moveTo(particles[i].x, particles[i].y); + ctx.lineTo(particles[j].x, particles[j].y); + ctx.strokeStyle = `rgba(0, 255, 204, ${1 - distance / 150})`; + ctx.stroke(); + } + } + } +} + +function initParticles(num) { + for (let i = 0; i < num; i++) { + particles.push(new Particle(Math.random() * canvas.width, Math.random() * canvas.height)); + } +} + +function animate() { + ctx.clearRect(0, 0, canvas.width, canvas.height); + + particles.forEach(particle => { + particle.update(); + particle.draw(); + }); + + connectParticles(); + + requestAnimationFrame(animate); +} + +initParticles(100); +animate(); \ No newline at end of file diff --git a/core/http/views/explorer.html b/core/http/views/explorer.html index 1db3dc9b..9843b47b 100644 --- a/core/http/views/explorer.html +++ b/core/http/views/explorer.html @@ -155,54 +155,29 @@ right: 10px; color: #e2e8f0; } - .fa-circle-nodes { - /* font-size: 100px; /* Adjust the size as needed */ - animation: rotateCircleNodes 8s linear infinite; /* Slow and fluid rotation */ - display: inline-block; - } - - @keyframes rotateCircleNodes { - 0% { transform: rotate(0deg); } - 100% { transform: rotate(360deg); } - } - /* Animation for the warning box */ - .fa-flask { - /* font-size: 100px; /* Adjust the size as needed */ - animation: shakeFlask 3s ease-in-out infinite; /* Smooth easing and longer duration for fluidity */ - transform-origin: bottom center; - } - - @keyframes shakeFlask { - 0%, 10% { transform: rotate(0deg); } /* Start and end still */ - 20% { transform: rotate(-10deg); } /* Smooth transition to left */ - 30% { transform: rotate(10deg); } /* Smooth transition to right */ - 40% { transform: rotate(-8deg); } /* Smooth transition to left */ - 50% { transform: rotate(8deg); } /* Smooth transition to right */ - 60% { transform: rotate(-5deg); } /* Smooth transition to left */ - 70% { transform: rotate(5deg); } /* Smooth transition to right */ - 80% { transform: rotate(-2deg); } /* Smooth transition to left */ - 90% { transform: rotate(2deg); } /* Smooth transition to right */ - 100% { transform: rotate(0deg); } /* Return to center */ - }
{{template "views/partials/navbar_explorer" .}} - -
-

- Network Clusters Explorer - -

-

- View the clusters and workers available in each network. - - - -

- -
+
+ +
+
+

+ Network Clusters Explorer + +

+

+ View the clusters and workers available in each network. + + + +

+ +
+
+
@@ -395,6 +370,7 @@ } } + {{template "views/partials/footer" .}}
diff --git a/core/http/views/p2p.html b/core/http/views/p2p.html index a8c51310..80d8ee84 100644 --- a/core/http/views/p2p.html +++ b/core/http/views/p2p.html @@ -8,13 +8,23 @@ {{template "views/partials/navbar" .}}
- -

- Distributed inference with P2P - - - -

+
+ +
+
+

+ Distributed inference with P2P +

+

+ Distribute computation by sharing and loadbalancing instances or sharding model weights. + + + +

+ +
+
+
LocalAI uses P2P technologies to enable distribution of work between peers. It is possible to share an instance with Federation and/or split the weights of a model across peers (only available with llama.cpp models). You can now share computational resources between your devices or your friends!
{{ if and .IsP2PEnabled (eq .P2PToken "") }} @@ -144,7 +154,7 @@ {{template "views/partials/footer" .}}
- + + + + \ No newline at end of file diff --git a/embedded/webui_static.yaml b/embedded/webui_static.yaml index c65d64ee..6120ccb7 100644 --- a/embedded/webui_static.yaml +++ b/embedded/webui_static.yaml @@ -57,4 +57,6 @@ - filename: "KFOlCnqEu92Fr1MmYUtfBBc9.ttf" url: "https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmYUtfBBc9.ttf" sha: "361a50f8a6c816ba4306c5290b7e487a726e1b4dcc3d8d7e4acf1fc2dae9f551" - +- filename: "anime.js" + url: "https://raw.githubusercontent.com/juliangarnier/anime/master/lib/anime.min.js" + sha: "bceef94f964481f7680d95e7fbbe5a8c20d3945a926a754874898a578db7c7ab" \ No newline at end of file