Search code examples
csssvgcss-animationssvg-animate

Close lids of a SVG Box with CSS animation


I have been looking at the tutorials and documentation for CSS animations but I cannot figure out how to flip a box lid along a specific axis using CSS on SVG. My goal is to make the lid close one after another on the box. Here are my SVG snippets

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="160.93758mm"
   height="125.50214mm"
   viewBox="0 0 160.93758 125.50215"
   version="1.1"
   id="svg5227"
   inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
   sodipodi:docname="box.svg">
  <defs
     id="defs5221">
    <inkscape:path-effect
       effect="simplify"
       id="path-effect6614"
       is_visible="true"
       steps="1"
       threshold="0.000859316"
       smooth_angles="360"
       helper_size="0"
       simplify_individual_paths="false"
       simplify_just_coalesce="false"
       simplifyindividualpaths="false"
       simplifyJustCoalesce="false" />
    <inkscape:path-effect
       effect="simplify"
       id="path-effect5176"
       is_visible="true"
       steps="1"
       threshold="0.000859316"
       smooth_angles="360"
       helper_size="0"
       simplify_individual_paths="false"
       simplify_just_coalesce="false"
       simplifyindividualpaths="false"
       simplifyJustCoalesce="false" />
    <inkscape:path-effect
       effect="simplify"
       id="path-effect5176-5"
       is_visible="true"
       steps="1"
       threshold="0.000859316"
       smooth_angles="360"
       helper_size="0"
       simplify_individual_paths="false"
       simplify_just_coalesce="false"
       simplifyindividualpaths="false"
       simplifyJustCoalesce="false" />
    <inkscape:path-effect
       effect="simplify"
       id="path-effect5176-9"
       is_visible="true"
       steps="1"
       threshold="0.000859316"
       smooth_angles="360"
       helper_size="0"
       simplify_individual_paths="false"
       simplify_just_coalesce="false"
       simplifyindividualpaths="false"
       simplifyJustCoalesce="false" />
    <inkscape:path-effect
       effect="simplify"
       id="path-effect6614-4"
       is_visible="true"
       steps="1"
       threshold="0.000859316"
       smooth_angles="360"
       helper_size="0"
       simplify_individual_paths="false"
       simplify_just_coalesce="false"
       simplifyindividualpaths="false"
       simplifyJustCoalesce="false" />
    <inkscape:path-effect
       effect="simplify"
       id="path-effect6614-5"
       is_visible="true"
       steps="1"
       threshold="0.000859316"
       smooth_angles="360"
       helper_size="0"
       simplify_individual_paths="false"
       simplify_just_coalesce="false"
       simplifyindividualpaths="false"
       simplifyJustCoalesce="false" />
  </defs>
  <sodipodi:namedview
     id="base"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageopacity="0.0"
     inkscape:pageshadow="2"
     inkscape:zoom="0.7"
     inkscape:cx="269.49536"
     inkscape:cy="253.67959"
     inkscape:document-units="mm"
     inkscape:current-layer="layer1"
     showgrid="false"
     fit-margin-top="0"
     fit-margin-left="0"
     fit-margin-right="0"
     fit-margin-bottom="0"
     inkscape:window-width="960"
     inkscape:window-height="1017"
     inkscape:window-x="952"
     inkscape:window-y="-8"
     inkscape:window-maximized="0" />
  <metadata
     id="metadata5224">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     inkscape:label="Layer 1"
     inkscape:groupmode="layer"
     id="layer1"
     transform="translate(-18.466661,-171.67717)">
    <rect
       style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.59225053;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
       id="rect5538"
       width="59.658813"
       height="59.658813"
       x="262.90607"
       y="152.26492"
       transform="matrix(0.89505329,0.4459592,-0.89505329,0.4459592,0,0)" />
    <path
       style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.5291667;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
       d="m 152.72032,270.24236 -53.6256,26.67238 -0.065,-58.55462 53.3978,-26.60539 z"
       id="rect5538-0"
       inkscape:connector-curvature="0"
       sodipodi:nodetypes="ccccc" />
    <path
       style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.5291667;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
       d="m 45.338711,270.24235 53.6256,26.67238 0.065,-58.55462 -53.3978,-26.60539 z"
       id="rect5538-0-2"
       inkscape:connector-curvature="0"
       sodipodi:nodetypes="ccccc" />
    <path
       style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       d="m 99.029711,185.14932 v 53.21079"
       id="path5765"
       inkscape:connector-curvature="0" />
    <rect
       style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.59246069;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
       id="rect5565-2"
       width="29.819016"
       height="59.539631"
       class="south box-lid"
       x="322.62885"
       y="152.47447"
       transform="matrix(0.89526273,0.4455386,-0.89526273,0.4455386,0,0)" />
    <rect
       style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.59246069;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
       id="rect5565-2-6"
       width="29.819016"
       height="59.539631"
       class="west box-lid"
       x="212.15384"
       y="263.12427"
       transform="matrix(-0.89526273,0.44553859,0.89526273,0.44553859,0,0)" />
    <rect
       style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.59246069;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
       id="rect5565-2-3"
       width="29.819016"
       height="59.539631"
       class="north box-lid"
       x="233.16525"
       y="152.57962"
       transform="matrix(0.89526273,0.44553859,-0.89526273,0.44553859,0,0)" />
    <rect
       style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.59246069;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
       id="rect5565-2-4"
       width="29.819016"
       height="59.539631"
       class="east box-lid"
       x="122.65482"
       y="263.08911"
       transform="matrix(-0.89526273,0.44553859,0.89526273,0.44553859,0,0)" />
    <path
       style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       d="m 152.3244,250.8869 c -6.42559,2.96081 -12.85119,5.92163 -19.27678,8.88244"
       id="path6612"
       inkscape:connector-curvature="0"
       inkscape:path-effect="#path-effect6614"
       inkscape:original-d="m 152.3244,250.8869 -19.27678,8.88244" />
    <path
       transform="translate(2.0533333e-6,9.5439038)"
       style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       d="m 152.3244,250.8869 c -6.42559,2.96081 -12.85119,5.92163 -19.27678,8.88244"
       id="path6612-7"
       inkscape:connector-curvature="0"
       inkscape:path-effect="#path-effect6614-4"
       inkscape:original-d="m 152.3244,250.8869 -19.27678,8.88244" />
    <path
       transform="translate(0.03779967,4.7436062)"
       style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       d="m 152.3244,250.8869 c -6.42559,2.96081 -12.85119,5.92163 -19.27678,8.88244"
       id="path6612-5"
       inkscape:connector-curvature="0"
       inkscape:path-effect="#path-effect6614-5"
       inkscape:original-d="m 152.3244,250.8869 -19.27678,8.88244" />
  </g>
</svg>

Each lid is a path element whose class is "box-lid" with the respective directional class name. The lids in the north and south lids, at the same time, close before the west and east ones. Furthermore, The lid should be rotated 180 deg along the diagonal axes which are the side of the top of the box. I have looked at the rotate3D function but I could not animate the lids to the desired result. So I am looking forward to the tips and advice and please excuse my bad English.


Solution

  • I tried doing path morphing with anime.js and it worked 80% but the layers orders turned out to be a problem. You can see the lid on the south as it closes, the lid is underneath the east lid in the SVG code so the closing looks pretty odd unless I make the animation finish quickly. Is there a way to manipulate SVG layer orders? Here are my codes

       const lidN = {
          path2:"m 98.792632,171.86423 0.04854,13.28552 -53.303611,26.5272 -0.04854,-13.28552 z",
          path3:"m 123.36108,197.37762 -24.519912,-12.22787 -53.303611,26.5272 24.519916,12.22787 z"
       }
       const lidS = {
          path2: "m 152.33287,211.67687 0.0485,-13.73978 -53.303611,26.5272 -0.04853,13.73978 z",
          path3: "m 152.33287,211.67687 -27.54373,-13.73978 -53.303613,26.5272 27.543736,13.73978 z"
       }
       const lidE = {
          path2: "m 99.078269,171.86381 -0.04854,13.28552 53.303611,26.5272 0.0485,-13.28552 z",
          path3: "m 72.419749,198.39294 26.60998,-13.24361 53.303611,26.5272 -26.61002,13.24361 z"
       }
       const lidW = {
          path2: "m 45.631926,211.75474 -0.04853,-16.5746 53.303612,26.5272 0.04853,16.5746 z",
          path3: "m 45.631926,211.75474 26.787779,-13.3618 53.303615,26.5272 -26.787782,13.3618 z"
       }
       window.addEventListener("click",()=>{
          const timeline1 = anime.timeline({
          autoplay: true,
          duration: 500,
       })
       const timeline2 = anime.timeline({
          autoplay: true,
          duration: 500,
       })
        timeline1.add({
           targets: '.lidn',
           d:[
             
             {value: lidN.path2},
             {value: lidN.path3}
           ],
           easing: "linear",
        }).add({
          targets: '.lide',
           d:[
             
             {value: lidE.path2},
             {value: lidE.path3}
           ],
           easing: "linear",
        })
        timeline2.add({
           targets: ".lids",
           d:[
       
             {value: lidS.path2},
             {value: lidS.path3}
           ],
           easing: "linear",
        }).add({
          targets: '.lidw',
           d:[
             
             {value: lidW.path2},
             {value: lidW.path3}
           ],
           easing: "linear",
        })
       })
      
    <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.0/anime.min.js"></script>
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="anime.min.js"></script>
       </head>
    <body>
    
       <svg width="160.93758" height="125.50215" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
    
          <metadata id="metadata5224">image/svg+xml</metadata>
          <g class="layer">
           <title>Layer 1</title>
           <g id="layer1" transform="translate(-18.466661,-171.67717)">
            <path d="m99.02972,185.14932c17.79928,8.86847 35.59855,17.73693 53.39782,26.6054c-17.79927,8.86846 -35.59855,17.73693 -53.39782,26.6054c-17.79928,-8.86847 -35.59855,-17.73693 -53.39782,-26.6054c17.79927,-8.86846 35.59855,-17.73693 53.39782,-26.6054z" fill="#ffffff" fill-rule="evenodd" id="rect5538" stroke="#000000" stroke-dashoffset="0" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-width="0.52917"/>
            <path d="m152.72032,270.24236c-17.8752,8.89079 -35.7504,17.78159 -53.6256,26.67238c-0.02167,-19.51821 -0.04333,-39.03641 -0.065,-58.55462c17.79927,-8.86846 35.59853,-17.73693 53.3978,-26.60539c0.0976,19.49588 0.1952,38.99175 0.2928,58.48763z" fill="#ffffff" fill-rule="evenodd" id="rect5538-0" stroke="#000000" stroke-dashoffset="0" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-width="0.52917"/>
            <path d="m45.33871,270.24235c17.8752,8.89079 35.7504,17.78159 53.6256,26.67238c0.02167,-19.51821 0.04333,-39.03641 0.065,-58.55462c-17.79927,-8.86846 -35.59853,-17.73693 -53.3978,-26.60539c-0.0976,19.49588 -0.1952,38.99175 -0.2928,58.48763z" fill="#ffffff" fill-rule="evenodd" id="rect5538-0-2" stroke="#000000" stroke-dashoffset="0" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-width="0.52917"/>
            <path d="m99.02971,185.14932c0,17.73693 0,35.47386 0,53.21079" fill="none" id="path5765" stroke="#000000" stroke-miterlimit="4" stroke-width="0.52917"/>
            <path d="m72.14531,171.86423l26.69586,13.28552l-53.30361,26.5272l-26.69586,-13.28552l53.30361,-26.5272z" fill="#ffffff" fill-rule="evenodd" id="rect5565-2-3" class="lidn" stroke="#000000" stroke-dashoffset="0" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-width="0.52917"/>
            <path d="m152.33287,211.67687l26.69585,13.28552l-53.30361,26.5272l-26.69585,-13.28552l53.30361,-26.5272z" fill="#ffffff" fill-rule="evenodd" id="rect5565-2" class="lids" stroke="#000000" stroke-dashoffset="0" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-width="0.52917"/>
            <path d="m45.63193,211.75474l-26.69585,13.28552l53.30361,26.5272l26.69585,-13.28552l-53.30361,-26.5272z" fill="#ffffff" fill-rule="evenodd" id="rect5565-2-6" class="lidw" stroke="#000000" stroke-dashoffset="0" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-width="0.52917"/>
            <path d="m125.72559,171.86381l-26.69586,13.28552l53.30361,26.5272l26.69586,-13.28552l-53.30361,-26.5272z" fill="#ffffff" fill-rule="evenodd" id="rect5565-2-4" class="lide" stroke="#000000" stroke-dashoffset="0" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-width="0.52917"/>
    
            <path d="m152.3244,250.8869c-6.42559,2.96081 -12.85119,5.92163 -19.27678,8.88244" fill="none" id="path6612" stroke="#000000" stroke-linecap="round" stroke-miterlimit="4" stroke-width="0.52917"/>
            <path d="m152.3244,250.8869c-6.42559,2.96081 -12.85119,5.92163 -19.27678,8.88244" fill="none" id="path6612-7" stroke="#000000" stroke-linecap="round" stroke-miterlimit="4" stroke-width="0.52917" transform="translate(2.0533333e-6,9.5439038)"/>
            <path d="m152.3244,250.8869c-6.42559,2.96081 -12.85119,5.92163 -19.27678,8.88244" fill="none" id="path6612-5" stroke="#000000" stroke-linecap="round" stroke-miterlimit="4" stroke-width="0.52917" transform="translate(0.03779967,4.7436062)"/>
           </g>
          </g>
         </svg>
    
    
    </body>
    
    </html>

    I used Inkscape to edit the path into two stages, then I copied the values in the d attributes in each stage of the path shape and morph the lid.