Web-Animation und Prozessvisualisierung?

3 Antworten

Vom Beitragsersteller als hilfreich ausgezeichnet

Meiner Meinung nach wäre SVG definitiv die einfachste Lösung.

Die Zeichnung selbst kannst du mit einem Grafikprogramm (Inkscape, Adobe Illustrator, Gravit, o.ä.) umsetzen. Gerade bei komplexen Formen ersparst du dir auf diese Weise einigen Aufwand. Die Bereiche, die animiert werden sollen, sollten als eigenständige Elemente vorliegen (path, rectangle, ellipse, text, o.ä.).

Den SVG-Code bindest du anschließend inline (also direkt) in dein HTML-Dokument ein. Nicht als img-Element, denn so hast du keinen Zugriff auf die einzelnen Knoten. So wie bei HTML kannst du via CSS und JavaScript auf die einzelnen SVG-Elemente zugreifen. Lediglich einige Properties wie die zum Setzen der Hintergrundfarbe (fill) oder für eine Kontur (stroke) heißen anders.

Hilfreiche Quellen zum Nachschlagen:


AlephSam 
Beitragsersteller
 05.07.2023, 16:52

Hey, danke für die Antwort. Eine Frage zu SVG, ich selbst bin jetzt nicht so sehr bewandert bei dem Thema. Ist es möglich, diese SVG herunterzuladen, Bibliotheken offline einzubinden, wie man dies auch bei zB. JS machen kann?

So wie ich es verstanden habe, ist es bei SVG auch möglich, auf die Grafiken oder Teile der Grafik draufzuklicken, um damit direkt Aktionen einzubauen?

Ich werde mir die Tutorials ebenfalls mal ansehen und dann SVG evtl. in Betracht ziehen... weil ich von meinem aktuellen Standpunkt noch nicht wirklich eine Idee habe, wie ich da weiter mache bzw. das damit umsetzen kann.

0
regex9  05.07.2023, 17:23
@AlephSam
Ist es möglich, diese SVG herunterzuladen, (...)

Nach dem von mir vorgeschlagenen Fall wäre die SVG ein Bestandteil der Webseite, da die Animationen ja auch mit CSS/JS umgesetzt werden sollen.

Wenn sich jemand die Grafik herunterladen möchte, muss er die gesamte HTML-Seite herunterladen (sprich: Rechtsklick im Webbrowser > Seite speichern unter). Er kann sie sich anschließend auch offline in einem Webbrowser anzeigen lassen.

(...) Bibliotheken offline einzubinden, wie man dies auch bei zB. JS machen kann?

Was du damit genau meinst, ist mir gerade nicht verständlich.

SVG ist ein XML-Format. Es wird von den meisten / wichtigsten Browsern nativ unterstützt. Du brauchst also keine zusätzlichen Bibliotheken, um SVG nutzen zu können. Ganz platt ausgedrückt ist es wie HTML, doch mit einem Fokus auf der Beschreibung geometrischer Formen. Vielleicht beantwortet das schon den Teil deiner Frage.

So wie ich es verstanden habe, ist es bei SVG auch möglich, auf die Grafiken oder Teile der Grafik draufzuklicken, um damit direkt Aktionen einzubauen?

Ja.

Ein sehr einfaches Beispiel:

<!doctype html>
<head>
  <title>My SVG website</title>
  <style>
    svg { background: silver }
    .my-square { fill: red }
    .my-square:hover { fill: yellow; stroke: blue }
  </style>
</head>
<body>
  <h1>My SVG website</h1>
  <svg height="200" viewport="0 0 200 200" width="200">
    <rect class="my-square" height="150" x="25" width="150" y="25" />
    <rect class="part" fill="white" height="50" width="50" x="100" y="100" />
  </svg>
  <script>
    const part = document.querySelector(".part");
    part.addEventListener("click", () => {
      part.style.stroke = "orange";
      part.style.strokeWidth = 5;
    });
  </script>
</body>

Hier ist ein SVG in einem HTML-Dokument eingebettet.

Die Zeichenfläche (mit grausilberner Hintergrundfarbe) besteht aus zwei Rechtecken. Das erste Rechteck habe ich via CSS gestyled. Das zweite Rechteck habe ich über JS mit einem Event-Handler ausgestattet, welcher bei Klick dafür sorgt, dass eine Kontur um das Viereck gezogen wird.

1
AlephSam 
Beitragsersteller
 05.07.2023, 23:11
@regex9

Genial, danke schön!!! Da könnte ich sicher ein paar Templates erstellen und dann nach Bedarf anpassen. Allerdings stelle ich es mir gerade noch schwierig vor, die komplette Anlage mittels SVG zu zeichnen?

Gibt es da Möglichkeiten, JPEG und SVG irgendwie zu kombinieren?

0
regex9  06.07.2023, 15:46
@AlephSam

Du könntest auf der Webseite zwei Bilder übereinander platzieren. Einmal die JPEG-Grafik im Hintergrund und die Vektorgrafik im Vordergrund. Letztere beinhaltet nur die Flächen, die du animieren möchtest.

Dafür kann man entweder die Vektorgrafik in einem Container mit Hintergrundbild einsetzen:

<div style="background-image:url('image.jpg')">
  <!-- svg ... -->
</div>

oder via z-index beide Elemente übereinander platzieren.

HTML:

<div class="container">
  <img alt="..." src="image.jpg">
  <svg class="on-top"><!-- ... --></svg>
</div>

CSS:

.container { position: relative }

.on-top {
  left: 0;
  position: absolute;
  top: 0;
  z-index: 5
}

Der Nachteil dabei wäre allerdings, dass beide Bilder in ihrer Skalierung synchron gehalten werden müssen. Unabhängig von der Bildschirm-/Fenstergröße sollen die SVG-Flächen ja stets an der richtigen Stelle im Bild angezeigt werden.

Ich würde eine vollständige Umsetzung in SVG vorziehen. Du kannst ja einmal schauen, wie gut sich deine JPG-Datei/en via Grafikprogramm in das SVG-Format konvertieren lässt/lassen.

1
AlephSam 
Beitragsersteller
 08.07.2023, 02:26
@regex9

Gut, Danke! Ich habe den Vorschlag nun getestet und es funktioniert.

Eine weitere Frage noch, wie bekomme ich es hin, dass sich das dynamisch ändert, wenn ich am Prozess etwas ändere, sprich, wenn sich das Bild des Prozesses verändert. Das Problem ist, dass die aktuelle Implementierung mittels der Postionen arbeitet.

Ja, das mit der Skalierung stimmt, das hatte ich ebenfalls feststellen müssen.

Am liebsten wäre mir eine einfache Möglichkeit, bei der ich direkt im Bild, irgendwie durchsichtige Markierungen setzen könnte... und diese Markierungen dann mittels JS auslesen, um die Position zu finden, welche anschließend manipuliert werden.

<!DOCTYPE html>

<html>

<body>

   <div class="Process">

       <img src="0.jpg" alt="Process" class="process-image">

       <img id="overlay-image" src="1.jpg" alt="Overlay" style="display: none;"> <!-- Neuer Platzhalter für das überlagernde Bild -->

       <img id="invisible-button" src="transparent.png" alt="Invisible Button" style="display: block;">

   </div>

   <style>

       .Process {

           position: absolute;

           top: 40px;

           left: 160px;

       }

       .process-image, #overlay-image, #invisible-button {

           position: absolute;

           width: auto; 

           height: auto;

       }

       #overlay-image {

           top: 388.0px;   

           left: 197.0px; 

       }

       #invisible-button {

           top: 388px;   

           left: 197px; 

           cursor: pointer;

       }

   </style>

   <script>

       window.onload = function() {

           var overlayImage = document.getElementById('overlay-image');

           var invisibleButton = document.getElementById('invisible-button');

           var state_pic_1 = false;

           var state_pic_2 = false;

           var state_pic_3 = false;

           var state_pic_4 = false;

           async function updateImages() {

               overlayImage.style.display = state_pic_1 ? 'block' : 'none';

               console.log("tick_tack!")

           }

                      invisibleButton.onclick = async function() {

               state_pic_1 = !state_pic_1;

               await updateImages();

           }

           // Init

           async function init() {

               await updateImages();

           }

           init();

           setInterval(updateImages, 2500);

       };

   </script>

</body>

</html>

0
regex9  08.07.2023, 12:59
@AlephSam
(...) wie bekomme ich es hin, dass sich das dynamisch ändert, wenn (...) sich das Bild des Prozesses verändert.

Wenn sich das Bildverhältnis nicht ändert, die Objekte also prozentual ausgerichtet werden können, könntest du via JS oder CSS ihre Koordinaten berechnen lassen.

Beispiel: Rechteck A liegt stets bei P(25% / 50%), die tatsächlichen Koordinaten berechnen sich also via Dreisatz anhand der Bildgröße (Bildbreite / 100 * 25, Bildhöhe / 100 * 50).

HTML:

<div class="container">
  <!-- image ... -->
  <svg>
    <rect class="rect-a" height="50" width="50" />
  </svg>
</div>

CSS:

.container {
  height: /* image height */
  width: /* image width */
}

.container img,
.container svg { /* full scale */
  height: auto;
  width: 100%;
}

.rect-a {
  x: 25%;
  y: 50%;
}

Bei grundsätzlichen Änderungen des Bildes musst du das SVG so und so manuell anpassen.

Eine Anpassung, ohne die Koordinaten textuell selbst setzen zu müssen, könnte evt. via OCR (Bildanalyse) umgesetzt werden. Das heißt, Positionsmarker (z.B. einzelne farbige Pixel, jede Farbe repräsentiert ein SVG-Element) werden (manuell) in ein Bild eingebaut und das Bild später via JS (und bspw. Tesseract) geparst. Für die gefundenen Positionsmarker werden die Koordinaten gelesen und die den jeweiligen SVG-Elementen zugeordnet.

Meines Erachtens wäre das allerdings nur eine Verschiebung des benötigten Aufwands, der in Summe wohl auch noch ansteigt. Du hättest den Entwicklungsaufwand für das Analysetool und weitreichenderen Wartungsaufwand (Bild mit Positionsmarkern, SVG, Analyse-Skript).

Abschließend ein paar Anmerkungen zu deinem HTML/JS:

1) Der style-Knoten gehört ausschließlich in den head. Dort fehlt bei dir auch ein title-Element.

<!DOCTYPE html>
<html>
  <head>
    <title>...</title>
    <style>
      /* CSS ... */
    </style>
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

2) Überall wo du async/await schreibst, ist es ohne Sinn/Zweck. In updateImages wird doch auf gar keine asynchron ablaufende Operation gewartet.

1
AlephSam 
Beitragsersteller
 10.07.2023, 00:26
@regex9
Meines Erachtens wäre das allerdings nur eine Verschiebung des benötigten Aufwands, der in Summe wohl auch noch ansteigt. Du hättest den Entwicklungsaufwand für das Analysetool und weitreichenderen Wartungsaufwand (Bild mit Positionsmarkern, SVG, Analyse-Skript).

Ich denke, du hast recht, ich habe jetzt noch mal herumprobiert und habe es geschafft, mittels Inkscape mein Prozess Bild als SVG einzulesen, allerdings erhalte ich dann alles, als ein Pfad, also das gesamte Bild.

Das Ergebnis hat mich zwar irgendwie nicht überrascht, aber es stellt sich nun die Frage, wie ich es schaffe, die einzelnen Bereiche, bei welchen zB. Flächen farblich manipuliert werden sollen, in ein zusammenhängendes SVG, mit vielen verschiedenen Pfaden, zu einem gesamt SVG zusammenzufügen.

Ich habe von Grafikdesign so gut wie keine Ahnung, wo fange ich da am besten an... die professionelle Software Corel oder Adobe Illustrator sind mir im Moment zu teuer. Mit Inkscape hat es beim ersten Versuch nicht geklappt, bzw. da habe ich keinen blassen Schimmer wie ich das anstellen soll, selbst nach YT Tutorials...

Überall wo du async/await schreibst, ist es ohne Sinn/Zweck. In updateImages wird doch auf gar keine asynchron ablaufende Operation gewartet.
Der style-Knoten gehört ausschließlich in den head. Dort fehlt bei dir auch ein title-Element.

Du hast absolut recht, Danke für die Hinweise!

LG

0

Oder Lottiefiles - wohl die modernste Lösung für sowas aktuell.

Siehe https://lottiefiles.com/


AlephSam 
Beitragsersteller
 06.07.2023, 02:39

Im Moment bin ich gerade noch unentschlossen, ob ich canvas oder svg verwenden sollte.

Ehrlich gesagt sagt mir lottiefiles gerade eher weniger zu ... Das müsste ich mir dann noch mal genauer ansehen und mir Gedanken machen, ich verstehe auch nicht so recht wie das funktionieren soll mit meinem Projekt. Ah, man benötigt so etwas wie deren Editor, interessant, aber ich denke, für meinen Zweck ist SVG oder Canvas der bessere Ansatz, dennoch Danke für den Tipp!

0

Naja - vllt über <canvas> - ansonsten evtl via css clip-path (wenn die Formen nicht allzu kompliziert sind) - legst jedes Element in ein extra Div, was du absolut positionieren kannst um die gewünschte Anorndnung zu erhalten, defnierst die einzelnen Formen über css-clip-path. Farben kannst du dann seperat über JS ansteuern und ändern


AlephSam 
Beitragsersteller
 05.07.2023, 02:07

Hey, danke, das schaue ich mir die Tage mal an!

0
paaauleee  05.07.2023, 02:12
@AlephSam

Kein Problem und viel Erfolg - was du natürlich auch machen kannst, ist von den einzelnen Objekten jeden Zustand als extra Bild (nicht alle auf einmal) - erstellt dann auch für jedes Objekt ein extra Div - lädst das Bild als Hintergrundbild ein und änderst es via Javascript - ist zwar auch aufwendig, aber nicht mehr soviel Arbeit, als wenn du alles als ein Bild darstellt, da du die einzelnen Divs seperat auswählen und ändern kannst

1
AlephSam 
Beitragsersteller
 05.07.2023, 16:55
@paaauleee

Danke! Die Idee finde ich prinzipiell gut, daran habe ich selbst noch gar nicht gedacht. Ich werde mir mal näher anschauen und versuche, ob das mit dieser Methode funktioniert.

Von <canvas> habe ich auch schon gehört, aber noch keinerlei praktische Erfahrung damit. Hast du zufälligerweise ein gutes Tutorial zur Hand, was mir für meinen Fall schnell weiterhelfen könnte?

Das Standard-Tutorial hier: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial schaue ich mir gerade an, wird wohl einige Zeit dauern, bis ich darin fit bin.

0
AlephSam 
Beitragsersteller
 06.07.2023, 04:11
@paaauleee

Ich habe das mal mit einem statischen Bild und Canvas getestet, das ist relativ einfach zu implementieren und funktioniert straight forward...

ich werde noch ein wenig herumexperimentieren, auch mit der svg Methode, aber das sieht so weit gut aus... THX!

<!DOCTYPE html>

<html>

<body>

   <canvas id="myCanvas" width="800" height="600"></canvas>

   <button id="markButton1">Raum 1 markieren</button>

   <button id="markButton2">Raum 2 markieren</button>

   <script>

       var canvas = document.getElementById('myCanvas');

       var ctx = canvas.getContext('2d');

       var img = new Image();

       var rooms = [

           { id: '1', x: 300, y: 400, color: 'red', state: false, shape: 'rectangle' },

           { id: '2', x: 400, y: 500, color: 'blue', state: false, shape: 'triangle' }

           // Fügen Sie hier weitere Räume hinzu

       ];

       img.onload = function() {

           ctx.drawImage(img, 0, 0, canvas.width, canvas.height);

           drawRooms();

       };

       img.src = 'bgl_114_eg_2d_grundriss.jpg'; // ersetzen Sie 'YOUR_IMAGE_PATH.jpg' durch den Pfad zu Ihrem Bild

       function drawRooms() {

           rooms.forEach(function(room) {

               if (room.state) {

                   ctx.fillStyle = room.color;

                   if (room.shape === 'rectangle') {

                       ctx.fillRect(room.x, room.y, 100, 100); // Position und Größe des Rechtecks

                   } else if (room.shape === 'triangle') {

                       ctx.beginPath();

                       ctx.moveTo(room.x, room.y);

                       ctx.lineTo(room.x + 50, room.y + 100);

                       ctx.lineTo(room.x - 50, room.y + 100);

                       ctx.closePath();

                       ctx.fill();

                   }

               }

           });

       }

       document.getElementById('markButton1').addEventListener('click', function() {

           rooms.find(room => room.id === '1').state = true;

           drawRooms();

       });

       document.getElementById('markButton2').addEventListener('click', function() {

           rooms.find(room => room.id === '2').state = true;

           drawRooms();

       });

   </script>

</body>

</html>

0