代码之家  ›  专栏  ›  技术社区  ›  Jithin Raj P R

svg`<path>`javascript动画未按预期工作

  •  13
  • Jithin Raj P R  · 技术社区  · 6 年前

    我所取得的成就:

    // Get the id of the <path> element and the length of <path>
    var myline = document.getElementById("myline");
    var length = myline.getTotalLength();
    circle = document.getElementById("circle");
    // The start position of the drawing
    myline.style.strokeDasharray = length;
    
    // Hide the triangle by offsetting dash. Remove this line to show the triangle before scroll draw
    myline.style.strokeDashoffset = length;
    
    // Find scroll percentage on scroll (using cross-browser properties), and offset dash same amount as percentage scrolled
    window.addEventListener("scroll", myFunction);
    
    function myFunction() {
      // What % down is it?
      var scrollpercent = (document.body.scrollTop + document.documentElement.scrollTop) / (document.documentElement.scrollHeight - document.documentElement.clientHeight);
      // Length to offset the dashes
      var draw = length * scrollpercent;
    
      // Reverse the drawing (when scrolling upwards)
      myline.style.strokeDashoffset = length - draw;
    
      //get point at length
      endPoint = myline.getPointAtLength(draw);
      circle.setAttribute("cx", endPoint.x);
      circle.setAttribute("cy", endPoint.y);
    
    }
    body {
      height: 2000px;
      background: #f1f1f1;
    }
    
    #circle {
      fill: red;
    }
    
    #mySVG {
      position: absolute;
      top: 15%;
      width: 100%;
      height: 1000px;
      
    }
    
    .st1 {
      fill: none;
      stroke-dashoffset: 3px;
      stroke: grey;
      stroke-width: 4;
      stroke-miterlimit: 10;
      stroke-dasharray: 20;
    }
    .st0 {
      fill: none;
      stroke-dashoffset: 3px;
      stroke: red;
      stroke-width: 5;
      stroke-miterlimit: 10;
      stroke-dasharray: 20;
    }
    <svg id="mySVG" viewBox="0 0 60 55" preserveAspectRatio="xMidYMin slice" style="width: 6%; padding-bottom: 42%; height: 1px; overflow: visible">
      <path  class="st1" stroke-dasharray="10,9" d="M 20 0 v 20 a 30 30 0 0 0 30 30 h 600 a 40 40 0 0 1 0 80 h -140 a 30 30 0 0 0 0 60 h 200 a 40 40 0 0 1 0 80 h -100 a 30 30 0 0 0 -30 30 v 20" /> Sorry, your browser does not support inline SVG.
    </svg>
    
    <svg id="mySVG" viewBox="0 0 60 55" preserveAspectRatio="xMidYMin slice" style="width: 6%; padding-bottom: 42%; height: 1px; overflow: visible">
      <circle id="circle" cx="10" cy="10" r="10"/>
      <path id="myline" class="st0" stroke-dasharray="10,9" d="M 20 0 v 20 a 30 30 0 0 0 30 30 h 600 a 40 40 0 0 1 0 80 h -140 a 30 30 0 0 0 0 60 h 200 a 40 40 0 0 1 0 80 h -100 a 30 30 0 0 0 -30 30 v 20" /> Sorry, your browser does not support inline SVG.
    </svg>

    我想要的是不管 大小 形状 这个 SVG <path> 是 生长线应该在屏幕中间。

    我试着改变 myline.style.strokeDashoffset = length //+newvalue - draw; 它所做的一切只是破坏了一致性。有谁能帮我解决这个问题吗?

    任何帮助都是非常可观的。

    4 回复  |  直到 6 年前
        1
  •  8
  •   Devansh J    6 年前

    (更新/新答案)

    我想这正是你想要的…

    更新(根据操作需要添加宽松版):

    长度增加 #body 通过添加平滑 transition: stroke-dashoffset ease-in-out 0.2s; #身体

    运动 #head 不能通过添加 transition: cx ease-in-out 0.2s, cy ease-in-out 0.2s; #头部 因为那会使它跳跃而不是沿着路径移动。

    如果你愿意 #头部 要顺利地沿着轨道前进,您必须通过使用js手动实现一个easing来完成,这是一项大量的工作。所以跳过了那部分。

    let roadmapSvg = document.getElementById("roadmap-svg");
    let track = document.getElementById("track");
    let body = document.getElementById("body");
    let head = document.getElementById("head");
    
    let totalLength = track.getTotalLength();
    let trackPoints = [];
    let getTrackBounds = () => track.getBoundingClientRect();
    let scaleFactor;
    
    body.style.strokeDasharray = totalLength;
    body.style.strokeDashoffset = totalLength;
    
    function setScaleFactor(){
      scaleFactor = roadmapSvg.getBoundingClientRect().width / roadmapSvg.viewBox.baseVal.width;
    }   
    setScaleFactor();
    
    function setTrackPoints(){
      let divisions = 1000;
      let unitLength = totalLength / divisions;
      trackPoints = [];
      for(let i=0; i < divisions; i++){
        let length = unitLength * i;
        let {x,y} = track.getPointAtLength(length);
        trackPoints.push({x: x*scaleFactor, y: y*scaleFactor, length});
      }
    }
    setTrackPoints();
    
    
    function draw(){
      let currentLength = getCurrentLength();
      body.style.strokeDashoffset = totalLength - currentLength;
      headPos = track.getPointAtLength(currentLength);
      head.setAttribute("cx", headPos.x);
      head.setAttribute("cy", headPos.y);
    }
    
    function getCurrentLength(){
      let centreY = window.innerHeight / 2;
      let trackBounds = getTrackBounds();
      let currentY = centreY - trackBounds.y;
      if(currentY < 0) return 0;
      
      // if currentY is greater that track height, that means the user has scrolled pass the track (and the whole svg) in such case the animation should be completed i.e. the head should be at the final position i.e. at totalLength 
      if(currentY > trackBounds.height) return totalLength;
      
      for(let point of trackPoints){
        if(point.y >= currentY){
          return point.length;
        }
      }
      
      // (For safety) Sometimes none of the conditions match bcoz of low precision... Such situation only occurs a point very close to total length... Thus...
      return totalLength;
    }
    
    document.addEventListener("scroll", draw);
    
    window.addEventListener("resize", () => {
      setScaleFactor();
      setTrackPoints();
      draw();
    });
    body {
      background: #f1f1f1;
      margin: 0;
      padding: 0 20%;
      font-family: sans-serif;
    }
    
    #roadmap-svg{
      display: block;
      max-width: 600px;
      margin: 20px auto;
      overflow: visible;
    }
    
    #roadmap-svg #head{
      fill: red;
    }
    
    #roadmap-svg #track{
      fill: none;
      stroke-dashoffset: 3px;
      stroke: grey;
      stroke-width: 4;
      stroke-miterlimit: 10;
      stroke-dasharray: 20;
    }
    #roadmap-svg #body{
      fill: none;
      stroke-dashoffset: 3px;
      stroke: red;
      stroke-width: 5;
      stroke-miterlimit: 10;
      stroke-dasharray: 20;
      transition: stroke-dashoffset ease-in-out 0.2s;
    }
    
    .center-line{
      position: fixed;
      left: 0;
      right: 0;
      top: 50%;
      border-top: 1px solid red;
      background-color: rgba(255,255,255,0.9);
    }
    <div>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempora in eaque rem eligendi corrupti voluptate, maxime cum cumque, eius delectus minus neque, dolorem optio cupiditate ratione! Excepturi fugit culpa quo?
    Cum optio error ex voluptatem rerum eius sunt, nemo necessitatibus, exercitationem voluptatum illum, rem quibusdam accusamus deserunt sed. Iste odio obcaecati enim voluptate temporibus ab illo maxime et sit minima.
    Odio ut dignissimos sed dicta recusandae esse, at molestiae quibusdam, consequatur aspernatur facilis, perferendis voluptatum adipisci. Dolores molestiae quos, doloribus excepturi officiis laborum ex officia reprehenderit esse perspiciatis alias itaque.
    Delectus illum, asperiores at a ab quibusdam corporis necessitatibus. Libero eos vero blanditiis modi cum rem maxime delectus quisquam, facilis saepe sed eius corrupti nobis sunt, unde obcaecati commodi velit.
    Saepe adipisci consectetur blanditiis quos enim praesentium, at magnam quibusdam nisi! Dolore, esse beatae! Enim, quam cum, qui voluptates fugiat, nihil mollitia possimus doloremque porro aspernatur nesciunt velit. Cum, adipisci?
    Dolores doloribus nihil delectus consequuntur id assumenda tempora, illum, earum ab quasi quaerat sequi et hic veniam excepturi eligendi quod perspiciatis voluptatem ratione reprehenderit! Corrupti minima facilis soluta adipisci animi!
    Iure, sed exercitationem. Quidem assumenda omnis dicta ducimus sunt, quibusdam excepturi molestias cumque! Illum ipsum perferendis dicta optio eum consequuntur soluta, corrupti nostrum est sed quaerat voluptates dolores perspiciatis? Ex!
    Consequatur corporis ratione beatae. Magni amet doloribus deserunt, accusamus suscipit earum accusantium perferendis adipisci inventore, ab commodi odio necessitatibus aut omnis. Et quisquam esse deleniti, reprehenderit nihil optio aperiam fugit.
    Aliquid error voluptatibus, quis quo eveniet nulla corrupti veniam culpa voluptas possimus tenetur nisi recusandae quae modi, animi dolores. Provident saepe nobis quos tenetur, veritatis laborum cupiditate molestias fugit consectetur.
    A, perspiciatis illo sequi non eos facere temporibus dignissimos blanditiis ipsum harum eius culpa adipisci est ab nobis saepe mollitia quis laboriosam tenetur, repellat molestias. Quos ipsa magni dolores rerum.</div>
    <svg id="roadmap-svg" viewBox="0 0 760 300">
      <path  id="track" stroke-dasharray="10,9" d="M 20 0 v 20 a 30 30 0 0 0 30 30 h 600 a 40 40 0 0 1 0 80 h -140 a 30 30 0 0 0 0 60 h 200 a 40 40 0 0 1 0 80 h -100 a 30 30 0 0 0 -30 30 v 20" />
      <path id="body" stroke-dasharray="10,9" d="M 20 0 v 20 a 30 30 0 0 0 30 30 h 600 a 40 40 0 0 1 0 80 h -140 a 30 30 0 0 0 0 60 h 200 a 40 40 0 0 1 0 80 h -100 a 30 30 0 0 0 -30 30 v 20" />
      <circle id="head" cx="10" cy="10" r="10"/>
    </svg>
    <div class="center-line">Center Line</div>
    <div>Lorem ipsum dolor sit amet consectetur adipisicing elit. Sapiente officia saepe facilis? Cupiditate rem vel, quaerat ratione ipsam magnam fugiat praesentium incidunt! Eveniet cum officia impedit obcaecati id animi rerum?
    Non beatae inventore quos optio temporibus ratione doloremque ullam animi dolore reiciendis sint, esse consequatur asperiores assumenda repudiandae obcaecati ab quas molestias harum eveniet amet natus ea? Ipsum, dolore suscipit.
    Explicabo assumenda minus, reprehenderit modi, laboriosam placeat saepe at repudiandae perferendis fugit asperiores itaque. Vero fugiat voluptas asperiores dolores dolorum quis ipsa sapiente deleniti odio, deserunt, iure voluptates. Error, tempore.
    Doloribus nesciunt praesentium ad aut minus aliquam aspernatur quas qui incidunt sunt, maxime tempora facilis, cum assumenda. Dolorum a tempore itaque impedit, ad, corporis tenetur enim nulla quas, harum fuga!
    Quae repellat, obcaecati voluptate inventore quidem, labore quo corporis repudiandae, vel doloremque perferendis numquam aliquam nisi? Vel architecto ullam fugiat error corrupti? Cumque amet illo, possimus assumenda eos unde deleniti.
    Enim tenetur possimus a neque, voluptatum reprehenderit, cum magni blanditiis quam atque dolorum veniam eveniet repellendus. Modi quibusdam maxime corrupti harum! Ullam vitae assumenda laboriosam nam officia eaque. Totam, dolorem.
    Ad sapiente itaque blanditiis, sint iusto nemo laborum corrupti cupiditate obcaecati quam ipsa quis perferendis vitae enim atque ex a ratione. Doloribus aspernatur id ipsa recusandae labore aliquid, totam aperiam?
    Recusandae delectus quidem, aspernatur nulla expedita accusantium quod praesentium inventore qui, pariatur ullam maxime! Numquam, sed sequi rem voluptates asperiores qui, culpa nesciunt magnam, quas doloribus praesentium et adipisci tempora.
    Veniam, placeat vel nesciunt recusandae voluptates laboriosam totam doloremque saepe. Nam quo similique vero esse possimus architecto officiis harum ratione perspiciatis dolor ut, molestias odit consequatur quam asperiores? Id, quasi!
    Ex expedita impedit aliquam et commodi voluptatibus, consequatur voluptate ea explicabo deserunt. Sapiente quo consequuntur enim dolores ea officia. Inventore ipsa dignissimos iste qui magnam reiciendis eveniet optio laudantium fugiat!</div>
        2
  •  7
  •   mico Matt    6 年前

    我试了好几种方法来达到目的

    • 在盒子里
    • 直到最后才溜走
    • 对原稿的改动很小。

    我做了以下更改(下面的工作示例):

    • 我放入2000的百分比的分隔符(等于2000px,包含的体高)
    • 我将卷轴的数量从顶部乘以18(合适的值是一个折衷方案,无论顶部还是底部的行为变得更为严格)
    • 最后,我检查了百分比值不大于1(它开始从另一端吃掉“蠕虫”)。

    就这样!也许不是最花哨的,但有效。

    这里的问题是svg行自上而下不是线性的,所以不能选择直接的元素相关值,或者至少我没有找到一些。因此,我最终得到了一个简单的解决方案,并使用了参数。

    // Get the id of the <path> element and the length of <path>
    var myline = document.getElementById("myline");
    var length = myline.getTotalLength();
    circle = document.getElementById("circle");
    // The start position of the drawing
    myline.style.strokeDasharray = length;
    
    // Hide the triangle by offsetting dash. Remove this line to show the triangle before scroll draw
    myline.style.strokeDashoffset = length;
    
    // Find scroll percentage on scroll (using cross-browser properties), and offset dash same amount as percentage scrolled
    window.addEventListener("scroll", myFunction);
    
    function myFunction() {
      // What % down is it?
      var scrollpercent = (document.documentElement.scrollTop * 18) / 2000;
      if (scrollpercent > 1) scrollpercent = 1;
      var draw = length * scrollpercent;
    
      // Reverse the drawing (when scrolling upwards)
      myline.style.strokeDashoffset = length - draw;
    
      //get point at length
      endPoint = myline.getPointAtLength(draw);
      circle.setAttribute("cx", endPoint.x);
      circle.setAttribute("cy", endPoint.y);
    }
    body {
      height: 2000px;
      background: #f1f1f1;
    }
    
    #circle {
      fill: red;
    }
    
    #mySVG {
      position: absolute;
      top: 15%;
      width: 100%;
      height: 1000px;
      
    }
    
    .st1 {
      fill: none;
      stroke-dashoffset: 3px;
      stroke: grey;
      stroke-width: 4;
      stroke-miterlimit: 10;
      stroke-dasharray: 20;
    }
    .st0 {
      fill: none;
      stroke-dashoffset: 3px;
      stroke: red;
      stroke-width: 5;
      stroke-miterlimit: 10;
      stroke-dasharray: 20;
    }
    <svg id="mySVG" viewBox="0 0 60 55" preserveAspectRatio="xMidYMin slice" style="width: 6%; padding-bottom: 42%; height: 1px; overflow: visible">
      <path  class="st1" stroke-dasharray="10,9" d="M 20 0 v 20 a 30 30 0 0 0 30 30 h 600 a 40 40 0 0 1 0 80 h -140 a 30 30 0 0 0 0 60 h 200 a 40 40 0 0 1 0 80 h -100 a 30 30 0 0 0 -30 30 v 20" /> Sorry, your browser does not support inline SVG.
    </svg>
    
    <svg id="mySVG" viewBox="0 0 60 55" preserveAspectRatio="xMidYMin slice" style="width: 6%; padding-bottom: 42%; height: 1px; overflow: visible">
      <circle id="circle" cx="10" cy="10" r="10"/>
      <path id="myline" class="st0" stroke-dasharray="10,9" d="M 20 0 v 20 a 30 30 0 0 0 30 30 h 600 a 40 40 0 0 1 0 80 h -140 a 30 30 0 0 0 0 60 h 200 a 40 40 0 0 1 0 80 h -100 a 30 30 0 0 0 -30 30 v 20" /> Sorry, your browser does not support inline SVG.
    </svg>
        3
  •  3
  •   Girisha C    6 年前

    根据评论和对css和svg代码的少量修改,我能够将行放到页面的中心,请查看下面的工作示例:

    // Get the id of the <path> element and the length of <path>
    var myline = document.getElementById("myline");
    var length = myline.getTotalLength();
    circle = document.getElementById("circle");
    // The start position of the drawing
    myline.style.strokeDasharray = length;
    
    // Hide the triangle by offsetting dash. Remove this line to show the triangle before scroll draw
    myline.style.strokeDashoffset = length;
    
    // Find scroll percentage on scroll (using cross-browser properties), and offset dash same amount as percentage scrolled
    window.addEventListener("scroll", myFunction);
    
    function myFunction() {
      // What % down is it?
      var scrollpercent = (document.body.scrollTop + document.documentElement.scrollTop) / (document.documentElement.scrollHeight - document.documentElement.clientHeight);
      // Length to offset the dashes
      var draw = length * scrollpercent;
    
      // Reverse the drawing (when scrolling upwards)
      myline.style.strokeDashoffset = length - draw;
    
      //get point at length
      endPoint = myline.getPointAtLength(draw);
      circle.setAttribute("cx", endPoint.x);
      circle.setAttribute("cy", endPoint.y);
    }
    body {
      margin: 0;
      height: 1000px;
      background: #f1f1f1;
    }
    #circle {
      fill: red;
    }
    #mySVG {
      top: 15%;
      position: absolute;
      width: 100%;
    }
    .st1 {
      fill: none;
      stroke-dashoffset: 1;
      stroke: grey;
      stroke-width: .5;
      stroke-miterlimit: 1;
      stroke-dasharray: 2;
    }
    .st0 {
      fill: none;
      stroke-dashoffset: 3px;
      stroke: red;
      stroke-width: 1;
      stroke-miterlimit: 1;
      stroke-dasharray: 2;
    }
    .grid {
      position: fixed;
      width: 1px;
      height: 100%;
      background: blue;
      left: 50%;
      top: 0;
    }
    <div class="grid"></div>
    <svg id="mySVG" viewBox="0 0 200 72" preserveAspectRatio="xMidYMin slice">
      <path class="st1" stroke-dasharray="10,9" d="m 0,5 0,4 c 0,3 2,6 5,6 l 108,0 c 4,0 7,4 7,8 0,4 -3,7 -7,7 l -25,0 c -3,0 -6,3 -6,6 0,3 3,6 6,6 l 35,0 c 4,0 7,4 7,8 0,4 -3,7 -7,7 l -18,0 c -3,0 -5,3 -5,6 l 0,4" />
    </svg>
    
    <svg id="mySVG" viewBox="0 0 200 72" preserveAspectRatio="xMidYMin slice">
      <circle id="circle" cx="0" cy="3" r="2" />
      <path id="myline" class="st0" stroke-dasharray="10,9" d="m 0,5 0,4 c 0,3 2,6 5,6 l 108,0 c 4,0 7,4 7,8 0,4 -3,7 -7,7 l -25,0 c -3,0 -6,3 -6,6 0,3 3,6 6,6 l 35,0 c 4,0 7,4 7,8 0,4 -3,7 -7,7 l -18,0 c -3,0 -5,3 -5,6 l 0,4" />
    </svg>
        4
  •  -3
  •   ccprog    6 年前

    我会选择不同的方法。我知道你想在离屏幕中间最近的路径上找到点。让我们这样做:

    1. 找到屏幕中间的坐标并将其转换为路径的坐标系。svg api有两个功能: .getScreenCTM() SVGPoint.matrixTransform() 是的。
    2. 找到路径上最接近这些坐标的点(及其沿路径的距离)。要做到这一点需要一些数学和搜索算法。迈克·博斯托克 shown 这样的算法,在这里使用。注意,他的函数可以进行一些调整 precision 参数)。
    3. 使用这些数据绘制圆和虚线偏移。

    通过引入 throttle for the scroll events (第二种变体)然后设置 CSS transitions 以避免可见的跳跃。

    圆定位的转换仅适用于 CSS transform 财产。(我的解决方案不必在过渡期间沿路径移动圆。这是可能的,但远远超出了这个答案的范围。)

    var mySVG = document.getElementById("mySVG");
    // Get the id of the <path> element and the length of <path>
    var myline = document.getElementById("myline");
    var pathLength = myline.getTotalLength();
    circle = document.getElementById("circle");
    // The start position of the drawing
    myline.style.strokeDasharray = pathLength;
    
    // Hide the triangle by offsetting dash. Remove this line to show the triangle before scroll draw
    myline.style.strokeDashoffset = pathLength;
    
    // throttled scroll event listener
    function throttle(ms, callback) {
        var timer, lastCall=0;
    
        return function() {
            var now = new Date().getTime(),
                diff = now - lastCall;
            if (diff >= ms) {
                lastCall = now;
                callback();
            }
        };
    }
    
    window.addEventListener("scroll", throttle(100, myFunction));
    
    // one initial execution
    myFunction();
    
    function myFunction() {
      var center = mySVG.createSVGPoint();
      // middle of browser viewport
      center.x = window.innerWidth / 2;
      center.y = window.innerHeight / 2;
      // transform to path coordinate system
      var matrix = myline.getScreenCTM().inverse();
      center = center.matrixTransform(matrix);
    
      //find nearest length on path
      var draw = getNearestLength(center);
    
      // Reverse the drawing (when scrolling upwards)
      myline.style.strokeDashoffset = -draw - pathLength;
    
      //get point at length
      endPoint = myline.getPointAtLength(draw);
      circle.style.transform = "translate(" + endPoint.x + "px, " + endPoint.y + "px)";
    }
    
    function getNearestLength(point) {
      var precision = 8,
          best,
          bestLength,
          bestDistance = Infinity;
      // linear scan for coarse approximation
      for (var scan, scanLength = 0, scanDistance; scanLength <= pathLength; scanLength += precision) {
        if ((scanDistance = distance2(scan = myline.getPointAtLength(scanLength))) < bestDistance) {
          best = scan, bestLength = scanLength, bestDistance = scanDistance;
        }
      }
      // binary search for precise estimate
      precision /= 2;
      while (precision > 0.5) {
        var before,
            after,
            beforeLength,
            afterLength,
            beforeDistance,
            afterDistance;
        if ((beforeLength = bestLength - precision) >= 0 && (beforeDistance = distance2(before = myline.getPointAtLength(beforeLength))) < bestDistance) {
          best = before, bestLength = beforeLength, bestDistance = beforeDistance;
        } else if ((afterLength = bestLength + precision) <= pathLength && (afterDistance = distance2(after = myline.getPointAtLength(afterLength))) < bestDistance) {
          best = after, bestLength = afterLength, bestDistance = afterDistance;
        } else {
          precision /= 2;
        }
      }
      return bestLength;
    
      function distance2(p) {
        var dx = p.x - point.x,
            dy = p.y - point.y;
        return dx * dx + dy * dy;
      }
    }
    body {
      height: 2000px;
      background: #f1f1f1;
    }
    
    #circle {
      fill: red;
    }
    
    #mySVG {
      position: absolute;
      top: 15%;
      width: 100%;
      height: 1000px;
      
    }
    
    .st1 {
      fill: none;
      stroke-dashoffset: 3px;
      stroke: grey;
      stroke-width: 4;
      stroke-miterlimit: 10;
      stroke-dasharray: 20;
    }
    .st0 {
      fill: none;
      stroke-dashoffset: 3px;
      stroke: red;
      stroke-width: 5;
      stroke-miterlimit: 10;
      stroke-dasharray: 20;
      transition: stroke-dashoffset 0.2s;
    }
    
    #circle {
       transform: translate(10px, 10px);
       transition: transform 0.2s;
       }
    <svg id="mySVG" viewBox="0 0 60 55" preserveAspectRatio="xMidYMin slice" style="width: 6%; padding-bottom: 42%; height: 1px; overflow: visible">
      <path  class="st1" stroke-dasharray="10,9" d="M 20 0 v 20 a 30 30 0 0 0 30 30 h 600 a 40 40 0 0 1 0 80 h -140 a 30 30 0 0 0 0 60 h 200 a 40 40 0 0 1 0 80 h -100 a 30 30 0 0 0 -30 30 v 20" /> Sorry, your browser does not support inline SVG.
    </svg>
    
    <svg id="mySVG" viewBox="0 0 60 55" preserveAspectRatio="xMidYMin slice" style="width: 6%; padding-bottom: 42%; height: 1px; overflow: visible">
      <circle id="circle" cx="0" cy="0" r="10"/>
      <path id="myline" class="st0" stroke-dasharray="10,9" d="M 20 0 v 20 a 30 30 0 0 0 30 30 h 600 a 40 40 0 0 1 0 80 h -140 a 30 30 0 0 0 0 60 h 200 a 40 40 0 0 1 0 80 h -100 a 30 30 0 0 0 -30 30 v 20" /> Sorry, your browser does not support inline SVG.
    </svg>