SVG/Tutorials/Rube-Goldberg-Maschinen
- 30min
- mittel
- * SVG
Der Ausdruck Rube-Goldberg-Maschine geht auf den US-amerikanischen Cartoonisten Reuben „Rube“ L. Goldberg zurück, der Comics über einen Professor Lucifer Gorgonzola Butts zeichnete, der unnötig komplizierte Maschinen konstruierte, bei denen eine eigentlich triviale Aktion durch eine Kette nacheinander ablaufender Aktionen ausgelöst wird.[1]
Auch im Film "Zurück in die Zukunft" gibt es in der Eingangsszene einen solchen Mechanismus, mit dem Doc Emmet Brown seinen Hund während seiner Abwesenheit allmorgendlich mit Futter versorgt.
Inhaltsverzeichnis
Das Vorbild
2007 stellte Alberto Pacheco vom Chihuahua Institute of Technology den Interpreter SLOGO vor, der aus PHP SVG-Markup ausgab. Berühmtestes Beispiel war die SVG-Animation einer Rube-Goldberg-Maschine.[2]
Ursprünglich in SMIL realisiert, funkioniert diese Variante mit CSS-Animations:
<rect x='0' y='0' width='8' height='28' rx='3' ry='3' fill='#444444' transform='translate(130,480),rotate(180)' stroke='black' stroke-width='1px'>
<animateTransform attributeName='transform' type='rotate' fill='freeze' begin='6.8s' dur='0.2s' from='0' to='70' additive='sum' />
</rect>
<!-- Error: %% Ficha 5 -->
<rect x='0' y='0' width='8' height='28' rx='3' ry='3' fill='#444444' transform='translate(150,480),rotate(180)' stroke='black' stroke-width='1px'>
<animateTransform attributeName='transform' type='rotate' fill='freeze' begin='6.9s' dur='0.2s' from='0' to='70' additive='sum' />
</rect>
<!-- Error: %% Ficha 6 -->
<rect x='0' y='0' width='8' height='28' rx='3' ry='3' fill='#444444' transform='translate(170,480),rotate(180)' stroke='black' stroke-width='1px'>
<animateTransform attributeName='transform' type='rotate' fill='freeze' begin='7s' dur='0.25s' from='0' to='90' additive='sum' />
</rect>
<!-- Error: %% Ficha 7 -->
<rect x='0' y='0' width='8' height='28' rx='3' ry='3' fill='#999999' transform='translate(190,480),rotate(180)' stroke='black' stroke-width='1px'>
<animateTransform attributeName='transform' type='translate' fill='freeze' begin='7.1s' dur='0.2s' from='0,0' to='-10,-5' additive='sum' />
<animateTransform attributeName='transform' type='rotate' fill='freeze' begin='7.1s' dur='0.2s' from='0' to='180' additive='sum' />
<animate attributeName='y' fill='freeze' begin='7.4s' dur='0.2s' from='0' to='46' />
</rect>
ToDo (weitere ToDos)
Warum CSS-Animations???
- Trennung von Inhalt (SVG-Markup) und Präsentation (CSS)
- CSS-Animations lassen sich mehrfach verwenden (z. B. bei Dominosteinen)
- CSS-Animations können mit einer Animation mehrere Eigenschaften gleichzeitig verändern (z.B: x- und y-Werte einer schiefen Ebene)
- CSS-Animations lassen sich zwar nicht so einfach wie in SMIL verknüpfen, über animation-delay, bzw. mit ein wenig JavaScript und animationend klappt dies genauso gut.
Einfache Maschinen
Hinter der Idee der Rube-Goldberg-Maschinen steckt die Anwendung Einfacher Maschinen[3], die zur Umwandlung einer Kraft dienen, um diese möglichst zweckmäßig zur Verrichtung von Arbeit einzusetzen. Beispiele für einfache Maschinen sind das Seil, der Hebel, die Rolle und die schiefe Ebene (Keil), die in irgendeiner Kombination in fast jeder Kraftmaschine vorkommen.
Die schiefe Ebene
Eine schiefe, schräge oder geneigte Ebene ist in der Mechanik eine ebene Fläche, die gegen die Horizontale geneigt ist. Sie wird verwendet, um den Kraftaufwand zur Höhenveränderung einer Masse zu verringern – der Arbeitsaufwand bleibt jedoch unverändert.
Bei Kugelbahnen und Rube-Goldberg-Maschinen wird sie meist zum Herabrollen verwendet.
@keyframes roll {
0% {transform: translate(0,0);}
75% {transform: translate(600px,-200px);}
100% {transform: translate(0,0);}
}
circle {
animation: roll 5s infinite ease-in;
}
In diesem Beispiel wird die Kugel (ein circle-Element) zuerst langsam hochgeschoben und rollt dann von oben schnell nach unten. Dies wird über eine Verschiebung der Kugel mit transform:translate() erreicht.
Hebel
Ein Hebel ist in der Physik und Technik ein mechanischer Kraftwandler bestehend aus einem starren Körper, der um einen Drehpunkt drehbar ist.
Da die folgende Animation aus vier Teilschritten besteht, müssen die einzelnen Schritte getaktet werden. Mit custom properties kann die Dauer und auch der Start (bzw. die Verzögerung gegenüber dem Laden der Seite) der einzelnen Schritte zentral festgelegt werden.
- die Box fliegt von oben auf die Wippe
- Die Wippe senkt sich
- sobald die Box auf dem Hebel liegt, macht sie eine Kreisbewegung mit dem Drehpunkt der Wippe als Zentrum
- die rechte Box fliegt nach oben
Dabei starten die letzten drei Animations-Schritte gleichzeitig.
#box1{
transform: translate(50px,0px) rotate(0deg);
animation: fall var(--step1-duration) linear forwards;
}
@keyframes fall {
0% {transform: translate(84px,0) rotate(20deg);}
50% {transform:translate(100px,199px) rotate(20deg); }
75% {transform:translate(75px,274px) rotate(0deg); }
100% {transform:translate(80px,353px) rotate(-20deg);}
}
#board {
transform: rotate(20deg);
animation: turn var(--step2-duration) linear forwards var(--step2-delay);
}
@keyframes turn {
0% {transform: rotate(20deg);}
100% {transform: rotate(-20deg);}
}
#box2 {
fill: var(--accent2color);
transform: translate(473px,337px) rotate(20deg);
animation: fall2 var(--step3-duration) ease-in forwards var(--step2-delay);
}
@keyframes fall2 {
0% {transform: translate(473px,337px) rotate(20deg);}
100% {transform: translate(600px,-100px) rotate(-20deg);}
}
ToDo (weitere ToDos)
Pendel
Eine andere Form der Rotation sind Pendel.
@keyframes swing {
0% {transform: rotate(-30deg);}
100% {transform: rotate(30deg);}
}
#pendulum {
animation: swing 2s infinite alternate ease-in;
transform: rotate(-30deg);
}
Das Pendel besteht aus einer Gruppierung mit einem Ball, der an einem Faden hängt. Auf einen externen Drehpunkt wird verzichtet, das Pendel rotiert um die Aufhängung des Fadens, dem Ursprung (0|0).
<g id="pendulum">
<line id="thread" y2="200"/>
<circle id="ball" cx="0" cy="200" r="30" />
</g>
Information: CSS oder XML-Attribute
Dafür gibt es keine feste Regel. Ich halte es so, dass für alle Einstellungen, die mehrfach verwendet werden können, CSS und für einmalig angewandte Formatierungen XML-Attribute benutze.
--Matthias Scharwies (Diskussion) 07:51, 11. Okt. 2020 (CEST)
Das line-Element enthält nur ein Attribut für den Y-Wert des Endpunkts, für alle anderen Werte wird 0 angenommen.
Das Pendel wird von einer weiteren Gruppierung umschlossen, um es mit einem transform-Attribut an den richtigen Platz zu verschieben.
Kugelstoßpendel
Ein Kugelstoßpendel ist eine Anordnung von identischen elastischen Kugeln, die in einer Reihe aufgehängt sind.Wenn eine der äußeren Kugeln abgehoben wird und gegen die Reihe der anderen Kugeln zurückfällt, bewirkt der Anprall, dass genau eine Kugel gegenüberliegend abgestoßen wird, während die anderen Kugeln in Ruhe bleiben. Pendelt diese Kugel zurück und prallt auf, wird durch den Stoß wieder die äußerste Kugel auf der anderen Seite abgestoßen – das System „schwingt“.
Auch dies lässt sich mit CSS animieren:
@keyframes swing {
}
Pendel
Eine andere Form der Rotation sind Pendel.
@keyframes swing {
0% {transform: rotate(-30deg);}
100% {transform: rotate(30deg);}
}
#pendulum {
animation: swing 2s infinite alternate ease-in;
transform: rotate(-30deg);
}
Das Pendel besteht aus einer Gruppierung mit einem Ball, der an einem Faden hängt. Auf einen externen Drehpunkt wird verzichtet, das Pendel rotiert um die Aufhängung des Fadens, dem Ursprung (0|0).
<g id="pendulum">
<line id="thread" y2="200"/>
<circle id="ball" cx="0" cy="200" r="30" />
</g>
Information: CSS oder XML-Attribute
Dafür gibt es keine feste Regel. Ich halte es so, dass für alle Einstellungen, die mehrfach verwendet werden können, CSS und für einmalig angewandte Formatierungen XML-Attribute benutze.
--Matthias Scharwies (Diskussion) 07:51, 11. Okt. 2020 (CEST)
Das line-Element enthält nur ein Attribut für den Y-Wert des Endpunkts, für alle anderen Werte wird 0 angenommen.
Das Pendel wird von einer weiteren Gruppierung umschlossen, um es mit einem transform-Attribut an den richtigen Platz zu verschieben.
Kugelstoßpendel
Ein Kugelstoßpendel ist eine Anordnung von identischen elastischen Kugeln, die in einer Reihe aufgehängt sind.Wenn eine der äußeren Kugeln abgehoben wird und gegen die Reihe der anderen Kugeln zurückfällt, bewirkt der Anprall, dass genau eine Kugel gegenüberliegend abgestoßen wird, während die anderen Kugeln in Ruhe bleiben. Pendelt diese Kugel zurück und prallt auf, wird durch den Stoß wieder die äußerste Kugel auf der anderen Seite abgestoßen – das System „schwingt“.
Auch dies lässt sich mit CSS animieren:
@keyframes swing {
0% {transform: rotate(-30deg);}
100% {transform: rotate(30deg);}
}
</syntaxhighlight>}}}}
Flaschenzug
- Gewicht an Seil
- Schere schneidet Seil
- Kerze brennt (https://codepen.io/akhil_001/pen/mzNQoM)
ToDo (weitere ToDos)
Zahnräder
Zahnräder (englisch: cog wheels) sorgen ähnlich wie Flaschenzüge für die Über- oder Untersetzung von Bewegung. Mit SVG lässt sich der Effekt eines drehenden Zahnrads leicht erzeugen:[4]
<circle cx="140" cy="100" r="50" stroke-dasharray="12,12">
<animate attributeName="stroke-dashoffset" repeatCount="indefinite" values="24;1" dur="0.5s" />
</circle>
<circle cx="250" cy="100" r="50" stroke-dasharray="12,12" >
<animate attributeName="stroke-dashoffset" repeatCount="indefinite" values="12;36" dur="0.5s" />
</circle>
In diesem Beispiel drehen sich aber nicht die Räder selbst, sondern nur die Randlinie (stroke). Selbst diese wird nicht rotiert, sondern verändert nur ihre Strichelung. Besser wäre es natürlich, wenn sich das gesamte Zahnrad drehen würde.
Peter Collingridge schuf Zahnräder, die er dann mit animateTransform um sich selbst rotieren ließ.[5]. Wir nehmen seine Idee auf, zentrieren jedoch alle Zahnräder um den Ursprung (0|0), was eine spätere Drehung vereinfacht und verschieben sie erst nach der Rotation:
svg {
--ani-duration:20s;
}
svg:hover .animated {
animation: turn var(--ani-duration) infinite linear;
}
@keyframes turn {
0% {transform: rotate(0deg);}
100% {transform: rotate(360deg);}
}
#gear2 .animated {
animation-duration: calc(var(--ani-duration) * 0.25);
animation-direction: reverse;
}
Jedes Zahnrad besteht aus einer Gruppierung, die das um den Ursprung zentrierte Zahnrad als path-Element und ein circle als Radnabe enthält. Diese Gruppierung wird dann mit einer SVG-Transformation an die passende Stelle verschoben.
Über Klassen werden die path-Elemente der Zahnräder farbig formatiert und animiert. Für jedes rotierende Element muss die richtige Umdrehungsdauer festgelegt werden. Hier wird die Variable --ani-duration
verwendet und mit der calc()-Funktion passend berechnet.
Es wäre zu überlegen, mit JavaScript einen gegebenen Zahnrad-Radius mit passenden Zähnen zu berechenen und ein path-Element zu generieren. Über den Radius kann dann der Umfang und so die nötige Drehgeschwindigkeit für jedes Zahnrad berechnet werden.[6]
Ideen
- Becher – Wasser – Gewicht
- Blasebalg – Segelboot / Ball
- Archimedische Schraube
- Gaußsche Kanone / Impulskanone
- Mausefalle / Katapult
Anwendungsbeispiele
Während des SELF-Treffens 2020 wurden in einem Workshop verschiedene Rube-Goldberg-Maschinen entworfen, die hier präsentiert werden:
ToDo (weitere ToDos)
Weblinks
- ↑ Wikipedia: Rube-Goldberg-Maschine
- ↑ SLOGO: A Vector Graphic Application Prototyping Language von Alberto Pacheco, Instituto Tecnológico de Chihuahua
- ↑ Wikipedia: Einfache Maschine
- ↑ cs.sru.edu: Timing von David Dailey, 2011
- ↑ Peter Collingridge: SVG animation: Rotating elements Zahnräder erzeugen und rotieren
- ↑ MSDN SVG-Animation für Anfänger
- Example 5 - Two Gears interessantes, aber veraltetes Tutorial, in dem SVG-Elemente (erst 2, dann 17 Zahnräder) mit requestAnimationFrame animiert werden.
Die Live-Beispiele sind leider nicht mehr vorhanden.
- Example 5 - Two Gears interessantes, aber veraltetes Tutorial, in dem SVG-Elemente (erst 2, dann 17 Zahnräder) mit requestAnimationFrame animiert werden.
- cloudfour: CSS Animation Timelines: Building a Rube Goldberg Machine Paul Hebert, 13.April 2020