Search code examples
cssanimationsvggraphicsgsap

How can I change the length, thickness and curvature of a simple oblong/line in the browser?


I've been working in the backend for the past six months, and it's years since I did graphic manipulation on the front, so I'm looking for guidance on this issue as I'm not even sure in which direction to head. I've done an hour of googling but I'm finding that none of the things that come up is what I'm looking for -- and it dawned on me that I'm not even sure what I'm looking for exactly.

Our clients want to have a page where a simple oblong image is modified by three sliders, each of which represents length, width and 'bend', (see attached images).

I am not sure how to do this -- my mind says 'SVG', although I haven't worked with SVG in the past. Can I modify an existing SVG image using CSS? Would the MorphSVGPlugin (https://greensock.com/docs/v2/Plugins/MorphSVGPlugin) from Greensock be my best bet? I've worked with Greensock in the past, but I don't now if it's overkill for what I'm trying to do.

Thanks for any clues!

enter image description here enter image description here enter image description here


Solution

  • Instead of using the L command for line I'm using the Q command for quadratic Bézier.

    Please read the comments in the code.

    let angle = 2.5;// line's angle
    let R,//line's length/2
    r;//line's curvature. In the begining r=0 (no curvature)
    
    
    
    R = ~~strokeLength.value/2;
    r = ~~itr.value;
    thePath.style.strokeWidth = strokeWidth.value
    thePath.setAttribute("d",getD(R,r));
    
    //set the stroke's width
    strokeWidth.addEventListener("input",()=>{
      thePath.style.strokeWidth = strokeWidth.value
    })
    //set the stroke's length
    strokeLength.addEventListener("input",()=>{
     R = ~~strokeLength.value/2;
     thePath.setAttribute("d",getD(R,r))
    })
    //set the stroke's curvature
    itr.addEventListener("input",()=>{
     r = ~~itr.value;
     thePath.setAttribute("d",getD(R,r))
    })
    
    //a function to calculate the new d attribute
    function getD(R,r){
      let p1 = {//move to this point
        x:R*Math.cos(angle),
        y:R*Math.sin(angle)
      }
      
      let p2 = {//end the curve in this point
        x:R*Math.cos(angle + Math.PI),
        y:R*Math.sin(angle + Math.PI)
      }
      
      let pc = {//calculate the control point for the bézier
        x:r*Math.cos(angle + Math.PI/2),
        y:r*Math.sin(angle + Math.PI/2)
      }
      
      let d = `M${p1.x},${p1.y}Q${pc.x},${pc.y} ${p2.x},${p2.y}`;
      return d;
    }
    svg{border:solid; float:left; margin:10px}
    span{display:inline-block; width:130px;}
    <svg viewBox="-100 -100 200 200" width="200">
      <path id="thePath" d="M-80,80L80,-80" stroke="skyBlue" stroke-width="10" stroke-linecap="round" fill="none" />
    </svg>
    <p><span>stroke's width</span><input id="strokeWidth" type="range" min="1" max="30" value="10"/></p>
    <p><span>stroke's length</span><input id="strokeLength" type="range" min="0" max="200" value="50"/></p>
    <p><span>stroke's curvature</span><input id="itr" type="range" min="-200" max="200" value="0"/></p>