crank motion with svg

Viewed 129

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
  <svg version="1.1"
    baseProfile="full"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns:ev="http://www.w3.org/2001/xml-events"
    width="1100"
    height="600">

  <title>  Slider-Crank </title>

  <defs>
    <rect
                id="Slidebar"
      stroke-width="1"
            stroke="black"
              fill="silver"
      fill-opacity="1"
                 x="0"
                 y="-12"
             width="300"
            height="24"
    />
    <g id="Crosshead" stroke-width="1" stroke="black" fill-opacity="1">
      <rect
           fill="gold"
              x="-50"
              y="-25"
          width="100"
         height="50"
      />
      <circle cx="0" cy="0" r="15" fill="white"/>
    </g>
    <g id="Crank" stroke-width="1" stroke="black" fill-opacity="1">
      <path fill="silver"
             d="M -99.959 40.000
                A  40  40 0 0 1 -99.959, -40.000
                A 450 450 0 0 0  -9.950, -49.000
                A  50  50 0 1 1  -9.950,  49.000
                A 450 450 0 0 0 -99.959,  40.000
                z"/>
      <circle cx="-100" cy="0" r="25" fill="white"/>
      <circle cx="0"    cy="0" r="30" fill="lightgrey"/>
    </g>
    <g id="ConRod" stroke-width="1" stroke="black" fill-opacity="0.7">
      <path fill="silver"
             d="M  12.387  21.715
                A 30 30 0 0 1  27.551  17.776
                L 453.475  22.035
                A 30 30 0 0 1 473.243  29.733
                A 40 40 0 0 1 473.243 -29.733
                A 30 30 0 0 1 453.475 -22.035
                L  27.551 -17.776
                A 30 30 0 0 1 12.387  -21.715
                A 25 25 0 0 1 12.387   21.715
                z"/>
      <circle cx="0"   cy="0" r="25" fill="silver"/>
      <circle cx="0"   cy="0" r="15" fill="white"/>
      <circle cx="500" cy="0" r="40" fill="silver"/>
      <circle cx="500" cy="0" r="25" fill="white"/>
    </g>

  </defs>

  <use xlink:href="#Slidebar"  x="150" y="263"/>
  <use xlink:href="#Slidebar"  x="150" y="337"/>
  <use xlink:href="#Crosshead" x="200" y="300">
    <animate
      attributeName="x"
            dur="3s"
            values="  200.000;
                      207.202;
                      227.545;
                      257.557;
                      292.430;
                      327.159;
                      357.557;
                      380.753;
                      395.140;
                      400.000;
                      395.140;
                      380.753;
                      357.557;
                      327.159;
                      292.430;
                      257.557;
                      227.545;
                      207.202;
                      200.000"
        repeatCount="indefinite"/>
  </use>

  <use xlink:href="#Crank" x="800" y="300">
    <animateTransform
      attributeName="transform" type="rotate" from="0,800,300"
         by="360" dur="3s" repeatCount="indefinite"/>
  </use>
  <use xlink:href="#ConRod" x="200" y="300">
    <animate
      attributeName="x"
            dur="3s"
            values="  200.000;
                      207.202;
                      227.545;
                      257.557;
                      292.430;
                      327.159;
                      357.557;
                      380.753;
                      395.140;
                      400.000;
                      395.140;
                      380.753;
                      357.557;
                      327.159;
                      292.430;
                      257.557;
                      227.545;
                      207.202;
                      200.000"

        repeatCount="indefinite"/>
    <animateTransform
      attributeName="transform" type="rotate" from="0,200,300"
         repeatCount="indefinite" dur="3s"
         values="  0.000, 200.000, 300;
                  -3.922, 207.202, 300;
                  -7.386, 227.545, 300;
                  -9.974, 257.557, 300;
                 -11.359, 292.430, 300;
                 -11.359, 327.159, 300;
                  -9.974, 357.557, 300;
                  -7.386, 380.753, 300;
                  -3.922, 395.140, 300;
                   0.000, 400.000, 300;
                   3.922, 395.140, 300;
                   7.386, 380.753, 300;
                   9.974, 357.557, 300;
                  11.359, 327.159, 300;
                  11.359, 292.430, 300;
                   9.974, 257.557, 300;
                   7.386, 227.545, 300;
                   3.922, 207.202, 300;
                   0.000, 200.000, 300"/>
  </use>

</svg>

Hi I'm trying to reproduce this crank motion animation with svg and javascript. The Crosshead need a translate animation and the Crank a rotation animation but how could I get the ConRod animation ? In the svg there is values given to animate and animateTransform but is there an equation which allow us to reproduce this ? Does anyone have an idea

1 Answers

{
    const svg = document.querySelector('svg');
    const crank = svg.querySelector('#crank');
    const crosshead = svg.querySelector('#crosshead');
    const conrod = svg.querySelector('#conrod');
    const bar_rect = svg.querySelector('#slidebar');
    
    const bar1 = svg.querySelector('#bar1');
    const bar2 = svg.querySelector('#bar2');
    
    // You can change those a bit
    const center = [800,150];
    const crank_len = 100;
    const conrod_len = 500;
    const crosshead_len = 100;
    const rotation_speed = 1;
        
    bar_rect.setAttribute('width', crank_len*2 + crosshead_len);
    bar1.setAttribute('y', center[1] - 37.5);
    bar1.setAttribute('x', center[0] - crank_len - conrod_len - crosshead_len/2);
    bar2.setAttribute('y', center[1] + 37.5);
    bar2.setAttribute('x', center[0] - crank_len - conrod_len - crosshead_len/2);
    
    crosshead.querySelector('rect').setAttribute('x', -crosshead_len/2);
    crosshead.querySelector('rect').setAttribute('width', crosshead_len);
    
    let angle = 0;
    
    draw();

    function draw(){
    
        crank.setAttribute('transform', `translate(${center[0]},${center[1]}) rotate(${angle+180}, 0, 0) scale(${crank_len/100})`);
        
        let crank_x = center[0] + Math.cos(angle*(Math.PI/180))*crank_len;
        let crank_y = center[1] + Math.sin(angle*(Math.PI/180))*crank_len;
        
        let crosshead_x = crank_x - Math.sqrt(conrod_len**2 - (crank_y-center[1])**2);
        let crosshead_y = center[1];
        
        crosshead.setAttribute('transform', `translate(${crosshead_x},${crosshead_y})`);
        
        let conrod_angle = Math.acos((crank_x-crosshead_x)/conrod_len)*(180/Math.PI);
        
        conrod_angle = (crank_y > center[1])? conrod_angle : -conrod_angle;
        
        conrod.setAttribute('transform', `translate(${crosshead_x},${crosshead_y}) rotate(${conrod_angle},0,0) scale(${conrod_len/500})`);

                
        angle = angle%(360) + rotation_speed;
        
        requestAnimationFrame(draw);        
    }

}
<svg viewBox="0 0 1100 600">
    <defs>
        <rect
            id="slidebar"
            stroke-width="1"
            stroke="black"
            fill="silver"
            fill-opacity="1"
            x="0"
            y="-12"
            width="300"
            height="24"
        />

    </defs>

    <use id="bar1" xlink:href="#slidebar"/>
    <use id="bar2" xlink:href="#slidebar"/>

    <g id="crosshead" stroke-width="1" stroke="black" fill-opacity="1">
        <rect
            fill="gold"
            x="-50"
            y="-25"
            width="100"
            height="50"
        />
        <circle cx="0" cy="0" r="15" fill="white"/>
    </g>

    <g id="crank" stroke-width="1" stroke="black" fill-opacity="1">
        <path fill="silver"
            d="M -99.959 40.000
                A  40  40 0 0 1 -99.959, -40.000
                A 450 450 0 0 0  -9.950, -49.000
                A  50  50 0 1 1  -9.950,  49.000
                A 450 450 0 0 0 -99.959,  40.000
                z"/>
        <circle cx="-100" cy="0" r="25" fill="white"/>
        <circle cx="0"    cy="0" r="30" fill="lightgrey"/>
    </g>
    <g id="conrod" stroke-width="1" stroke="black" fill-opacity="0.7">
        <path fill="silver"
                d="M  12.387  21.715
                    A 30 30 0 0 1  27.551  17.776
                    L 453.475  22.035
                    A 30 30 0 0 1 473.243  29.733
                    A 40 40 0 0 1 473.243 -29.733
                    A 30 30 0 0 1 453.475 -22.035
                    L  27.551 -17.776
                    A 30 30 0 0 1 12.387  -21.715
                    A 25 25 0 0 1 12.387   21.715
                    z"/>
        <circle cx="0"   cy="0" r="25" fill="silver"/>
        <circle cx="0"   cy="0" r="15" fill="white"/>
        <circle cx="500" cy="0" r="40" fill="silver"/>
        <circle cx="500" cy="0" r="25" fill="white"/>
    </g>
</svg>

Related