Bitte warten

JavaScript: SVG-Animationen

Mit JavaScript lassen sich SVGrafiken auch animieren. Dazu müssen diese in den HTML-Quelltext eingebunden sein.

Code kopieren
<svg width='320px' height='320px'>
  <!-- Hauptachsen; umlaufende Strecke; Endpunkte; -->
  <line class='line2c' x1='0' y1='160.5' x2='320' y2='160.5' />
  <line class='line2c' x1='160.5' y1='0' x2='160.5' y2='320' />
  <line id='l1_0' class='line2' x1='320.5' y1='160.5' x2='160.5' y2='160.5' />
  <circle id='c1_0' class='line2' cx='320.5' cy='160.5' r='1' />
  <circle id='c2_0' class='line2' cx='160.5' cy='160.5' r='1' />
  
  <!-- Ellipse; Brennpunkte; Strecken PF1, PF2 -->
  <ellipse class='line1' cx='160.5' cy='160.5' rx='100' ry='60' />
  <circle class='line1b' cx='80.5' cy='160.5' r='2' />
  <circle class='line1b' cx='240.5' cy='160.5' r='2' />
  <line id='l2_0' class='line1c' x1='260.5' y1='160.5' x2='80.5' y2='160.5' />
  <line id='l3_0' class='line1c' x1='260.5' y1='160.5' x2='240.5' y2='160.5' />
  
  <!-- Schnittpunkt; Mittelpunkt; -->
  <circle id='c3_0' cx='260.5' cy='160.5' r='3' />
  <circle class='line2b' cx='160.5' cy='160.5' r='2' />
</svg>

<script>
  var a_0 = 100;
  var b_0 = 60;
  var tu_0 = 360;
  var t_0 = 0;
  doAnimation_0 = function() {
    alpha_0 = t_0 / tu_0 * 2 * Math.PI;
    var x1_0 = Math.cos(alpha_0) * (a_0 + b_0);
    var y2_0 = Math.sin(alpha_0) * (a_0 + b_0);
    var px_0 = Math.cos(alpha_0) * a_0;
    var py_0 = Math.sin(alpha_0) * b_0;
    document.getElementById('l1_0').setAttribute('x1', 160.5 + x1_0);
    document.getElementById('l1_0').setAttribute('y2', 160.5 - y2_0);
    document.getElementById('l2_0').setAttribute('x1', 160.5 + px_0);
    document.getElementById('l2_0').setAttribute('y1', 160.5 - py_0);
    document.getElementById('l3_0').setAttribute('x1', 160.5 + px_0);
    document.getElementById('l3_0').setAttribute('y1', 160.5 - py_0);
    document.getElementById('c1_0').setAttribute('cx', 160.5 + x1_0);
    document.getElementById('c2_0').setAttribute('cy', 160.5 - y2_0);
    document.getElementById('c3_0').setAttribute('cx', 160.5 + px_0);
    document.getElementById('c3_0').setAttribute('cy', 160.5 - py_0);
    t_0++;
  }
  setInterval(doAnimation_0, 50);
</script>

Oder eine „analoge“ Uhr:

Code kopieren
<svg id='clock' width='225' height='225'>
  <defs>
    <filter id='shadow' filterUnits='userSpaceOnUse'>
      <feGaussianBlur in='SourceAlpha' stdDeviation='1' />
      <feOffset dx='2' dy='2' result='offsetblur' />
      <feComponentTransfer>
        <feFuncA type='linear' slope='.8'/>
      </feComponentTransfer>
      <feMerge> 
        <feMergeNode />
        <feMergeNode in='SourceGraphic' />
      </feMerge>
    </filter>
    <radialGradient id='grad1' r='100%' cx='51.077062133199%' cy='51.077062133199%' spreadMethod='pad'>
      <stop offset='46.238402061856%' stop-color='hsl(220,35%,30%)' />
      <stop offset='47.738402061856%' stop-color='hsl(220,35%,10%)' />
      <stop offset='49.261597938144%' stop-color='hsl(220,35%,10%)' />
      <stop offset='50.761597938144%' stop-color='hsl(220,35%,30%)' />
    </radialGradient>
  </defs>
  <circle id='c1' cx='50%' cy='50%' r='50%' fill='url(#grad1)' />
  <circle id='c2' cx='50%' cy='50%' r='47%' fill='hsl(220,10%,50%)' />
  <g id='scales'></g>
  <line stroke='hsl(220,10%,10%)' stroke-width='7.5' filter='url(#shadow)' />
  <line stroke='hsl(220,10%,10%)' stroke-width='5.625' filter='url(#shadow)' />
  <line stroke='hsl(0,85%,32%)' stroke-width='2.25' filter='url(#shadow)' />
</svg>
  
<script>
  r = document.getElementById('clock').getAttribute('width') / 2;
  out = '';
  for (i = 0; i < 60; i++) {
    out += '<line stroke=\'hsl(23,35%,10%)\' />';
  }
  document.getElementById('scales').innerHTML = out;
  lines = document.getElementById('clock').getElementsByTagName('line');
  d = [
    [r * .05, r * .91, r * .76],
    [r * .01, r * .90, r * .83]
  ];
  for (i = 0; i < 60; i++) {
    if (i % 5) e = 1; else e = 0;
    lines[i].setAttribute('stroke-width', d[e][0]);
    rad = i * Math.PI / 30;
    lines[i].setAttribute('x1', r + d[e][1] * Math.cos(rad));
    lines[i].setAttribute('y1', r + d[e][1] * Math.sin(rad));
    lines[i].setAttribute('x2', r + d[e][2] * Math.cos(rad));
    lines[i].setAttribute('y2', r + d[e][2] * Math.sin(rad));
  }
  function setNeedle(id, l, rad) {
    lines[id].setAttribute('x1', r + l * Math.cos(rad));
    lines[id].setAttribute('y1', r + l * Math.sin(rad));
    lines[id].setAttribute('x2', r - r * .1 * Math.cos(rad));
    lines[id].setAttribute('y2', r - r * .1 * Math.sin(rad));
  }
  function setClock() {
    dateObject = new Date();
    hours   = dateObject.getHours();
    minutes = dateObject.getMinutes();
    seconds = dateObject.getSeconds();
    setNeedle(60, r * .5, (hours + minutes / 60 + seconds / 3600) * Math.PI / 6 - Math.PI / 2);  // needle for hours
    setNeedle(61, r * .71, (minutes + seconds / 60) * Math.PI / 30 - Math.PI / 2);  // needle for minutes
    setNeedle(62, r * .71, seconds * Math.PI / 30 - Math.PI / 2);  // needle for seconds
  }
  setInterval(setClock, 100);
</script>

Oder eine Uhr mit 7-Segmente-LCD-Anzeige:

Code kopieren
<svg id='digiclock'></svg>
  
<script>
  scale = 1.5;  /// scale factor
  m = 20;  // outer margin
  u = scale * 10;  // base unit (segment width)
  width  = 2 * m + u * 34;
  height = 2 * m + u *  8;
  segs = [
    "M-1,-2 L2,-5 L33,-5 L36,-2 L29,5 L6,5 Z",
    "M-2,-1 L5,6 L5,29 L0,34 L-5,29 L-5,2 Z",
    "M37,-1 L40,2 L40,29 L35,34 L30,29 L30,6 Z",
    "M1,35 L6,30 L29,30 L34,35 L29,40 L6,40 Z",
    "M0,36 L5,41 L5,64 L-2,71 L-5,68 L-5,41 Z",
    "M35,36 L40,41 L40,68 L37,71 L30,64 L30,41 Z",
    "M-1,72 L6,65 L29,65 L36,72 L33,75 L2,75 Z"
  ];
  out = "<rect fill='hsl(80,10%,40%)' x='0' y='0' width='" + width + "' height='" + height + "' />";
  out += "<g transform='translate(" + (u * .6 + m + u / 2) + " " + (m + u / 2) + ") skewX(-5) scale(" + scale + ")'>";
  for (d = 0; d < 6; d++) {
    out += "<g transform='translate(" + ([0, 55, 130, 185, 254, 298][d]) + " " + (d > 3 ? 15 : 0) + ")" + (d > 3 ? " scale(.8)" : "") + "'>";
    for (s = 0; s < 7; s++) out += "<path id='seg" + d.toString() + s.toString() + "' d='" + segs[s] + "' fill='hsl(80,10%,17%)' opacity='0' />";
    out += "</g>";
  }
  out += "<circle id='ci1' fill='hsl(80,10%,17%)' opacity='0' cx='110' cy='20' r='6' />";
  out += "<circle id='ci2' fill='hsl(80,10%,17%)' opacity='0' cx='110' cy='55' r='6' />";
  out += "</g>";
  svg = document.getElementById('digiclock');
  svg.setAttribute("width",  width );
  svg.setAttribute("height", height);
  svg.innerHTML = out;
  b = [
    "1110111", "0010010", "1011101", "1011011", "0111010",
    "1101011", "1101111", "1010010", "1111111", "1111011"
  ];
  function digiclock() {
    now = new Date(Date.now());
    hrs = now.getHours();
    min = now.getMinutes();
    sec = now.getSeconds();
    digits = hrs.toString().padStart(2, "0") + min.toString().padStart(2, "0") + sec.toString().padStart(2, "0");
    for (d = 0; d < 6; d++) for (s = 0; s < 7; s++) document.getElementById("seg" + d.toString() + s.toString()).setAttribute("opacity", b[digits[d]][s]);
    document.getElementById("ci1").setAttribute("opacity", sec % 2 ? 0 : 1);
    document.getElementById("ci2").setAttribute("opacity", sec % 2 ? 0 : 1);
    requestAnimationFrame(digiclock);
  }
  requestAnimationFrame(digiclock);
</script>

Oder die Berlin-Uhr:

Code kopieren
<div class='center'><svg id='berlinuhr'></svg></div>
<script>
  function initClock() {
    u = 8;  // this value controls the size of the clock (width of segment border)
    g = u * 1.5;  // gap between rows
    sw1 = u * 6.5;  // width of wide segments
    sw2 = (4 * sw1 - 7 * u) / 11; // width of narrow segments
    h = u * 4.8;  // height of segments
    offset = 2 * (h + u) + g;  // y-pos of top row
    width  = 4 * sw1 + 5 * u;  // overall width
    height = offset + 4 * (h + 2 * u) - u + 3 * g;  // overall height
    cx = width / 2;  // horizontal center of top light
    cy = h + u / 2;  // vertical center of top light
    yellow = "hsl(45,100%,20%)";
    red    = "hsl(10,100%,20%)";
    
    defs  = "<defs>";
    for (i = 0; i < 3; i++) {
      defs += "<radialGradient id='yellow" + i + "' r='50%' cx='50%' cy='50%' fx='50%' fy='50%' spreadMethod='pad'>";
      defs += "<stop offset='0%'   stop-color='hsl(45,100%,75%)' />";
      defs += "<stop offset='100%' stop-color='hsl(45,100%,50%)' />";
      defs += "</radialGradient>";
    }
    for (i = 1; i < 3; i++) {
      defs += "<radialGradient id='red" + i + "' r='50%' cx='50%' cy='50%' fx='50%' fy='50%' spreadMethod='pad'>";
      defs += "<stop offset='0%'   stop-color='hsl(40,100%,65%)' />";
      defs += "<stop offset='100%' stop-color='hsl(10,100%,45%)' />";
      defs += "</radialGradient>";
    }
    defs += "</defs>";
    
    out  = "<circle id='seg1' fill='" + yellow + "' cx='" + (cx) + "' cy='" + (cy) + "' r='" + (h) + "' />";
    out2 = "<circle stroke='silver' stroke-width='" + (u) + "' fill='none' cx='" + (cx) + "' cy='" + (cy) + "' r='" + (h) + "' />";
    out3 = "<path fill='gray' d='M" + (12.5 * u) + "," + (offset - u) + " A" + (g / 2) + "," + (g / 2) + " 0 0,0 " + (12.5 * u) + "," + (offset - 3.2 * u) + " L" + (width - 12.5 * u) + "," + (offset - 3.2 * u) + " A" + (g / 2) + "," + (g / 2) + " 0 0,0 " + (width - 12.5 * u) + "," + (offset - u) + " Z' />";
    for (y = 0; y < 4; y++) {
      for (x = 0; x < (y == 2 ? 11 : 4); x++) {
        w = (y == 2 ? sw2 : sw1);
        xpos = u + x * (w + u);
        ypos = offset + y * (h + 2 * u + g);
        fill = (y < 2 || (y == 2 && !((x + 1) % 3)) ? red : yellow);
        out += "<rect id='seg" + (y + 2) + "_" + (x) + "' fill='" + fill + "' x='" + (xpos) + "' y='" + (ypos) + "' width='" + (w) + "' height='" + (h) + "' />";
        xpos -= u / 2;
        if (x) out2 += "<line stroke='silver' stroke-width='" + (u) + "' stroke-linecap='square' x1='" + (xpos) + "' y1='" + (ypos) + "' x2='" + (xpos) + "' y2='" + (ypos + h) + "' />";
      }
      out2 += "<rect stroke='silver' stroke-width='" + (u) + "' fill='none' x='" + (u / 2) + "' y='" + (offset + y * (h + 2 * u + g) - u / 2) + "' width='" + (4 * (sw1 + u)) + "' height='" + (h + u) + "' rx='" + (u * 1.75) + "' />";
      if (y) {
        for (i = 0; i < 2; i++) {
          xs = u + 2 * i * (u + sw1);
          out3 += "<path fill='gray' d='M" + (xs + .5 * sw1 - g / 4) + "," + (ypos - u) + " A" + (g / 2) + "," + (g / 2) + " 0 0,0 " + (xs + .5 * sw1 - g / 4) + "," + (ypos - u - g) + " L" + (xs + u + 1.5 * sw1 + g / 4) + "," + (ypos - u - g) + " A" + (g / 2) + "," + (g / 2) + " 0 0,0 " + (xs + u + 1.5 * sw1 + g / 4) + "," + (ypos - u) + " Z' />";
        }
      }
    }
    svg = document.getElementById("berlinuhr");
    svg.setAttribute("width", width);
    svg.setAttribute("height", height);
    svg.innerHTML = defs + out + out3 + out2;
    document.getElementById("yellow0").setAttribute("r", "30%");
    document.getElementById("yellow1").setAttribute("gradientTransform", "scale(1, .4) translate(0, .7)");
    document.getElementById("yellow2").setAttribute("gradientTransform", "scale(.7, 1) translate(.22, 0)");
    document.getElementById("red1").setAttribute("gradientTransform", "scale(1, .4) translate(0, .7)");
    document.getElementById("red2").setAttribute("gradientTransform", "scale(.7, 1) translate(.22, 0)");
  }
  function setClock2() {
    dObj = new Date();
    hours   = dObj.getHours();
    minutes = dObj.getMinutes();
    seconds = dObj.getSeconds();
    tests = [hours / 5, hours % 5, minutes / 5, minutes % 5];
    document.getElementById("seg1").setAttribute("fill", (seconds % 2 ? yellow : "url(#yellow0)"));
    for (y = 0; y < 4; y++) {
      n = +(y != 2) + 1;
      for (x = 0; x < (y == 2 ? 11 : 4); x++) {
        cond = +(Math.floor(tests[y]) > x);
        fill = (
          y < 2 || (y == 2 && !((x + 1) % 3)) ?
          [red,    "url(#red"    + n + ")"][cond] :
          [yellow, "url(#yellow" + n + ")"][cond]
        );
        document.getElementById("seg" + (y + 2) + "_" + x).setAttribute("fill", fill);
      }
    }
  }
  initClock();
  setInterval(setClock2, 100);
</script>