【问题标题】:SVG Slider - Move dot only along SVG pathSVG 滑块 - 仅沿 SVG 路径移动点
【发布时间】:2026-01-06 17:20:04
【问题描述】:

我创建了一个圆形 SVG 滑块,但在正确定位点时仍然存在问题。 在 Codepen 上查看当前结果:

HTML:

    <svg version="1.1" id="slider" width="300px" height="150px"> 
       <path id="sliderPath" stroke="red" stroke-width="5" d="M10,100a147,147,0,1,1,280,1"/>
       <circle id="dot" fill="white" cx="10" cy="100" r="14" /> 
    </svg>

JS:

var sliderPath = document.getElementById("sliderPath"),
box = sliderPath.getBBox(),
dot = document.getElementById("dot"),
W = box.width,
pathLength = sliderPath.getTotalLength();

Draggable.create(
    document.createElement('div'),
      { 
        type:'x',
        throwProps:true,
        bounds: { minX:0, maxX:W },
        trigger:dot,
        overshootTolerance:0,
        onDrag:update,
        onThrowUpdate:update
});

function update(){ 
  // Get x and y for dot.
  var P = sliderPath.getPointAtLength(this.x / W * pathLength);
  // Set dot.
  TweenLite.set(dot,{attr:{cx:P.x,cy:P.y}});
};

http://codepen.io/Yheeky/pen/xEbAbR

您可以开始拖动点并将鼠标从左向右移动。这很好用,但我需要更直接地设置点位置,使点位置等于鼠标位置,但仅沿路径。 我需要改变什么才能得到这种结果?

提前致谢!

【问题讨论】:

    标签: javascript html svg


    【解决方案1】:

    下面的示例显示了水平条路径。 bar的路径长度和sliderPath的路径长度比率用于沿着sliderPath移动点。

    这个例子有点古怪,因为我移动了 svg,所以它完全可见,但你应该知道它是如何工作的。

    <!DOCTYPE HTML>
    <html>
    <head>
      <title>Slider@Semi Circle</title>
    </head>
    <body>
    <div style='position:absolute;top:200px;left:200px;'>
    <svg overflow=visible version="1.1" id="slider" width="300px" height="150px">
    <path onmousedown=moveDotStart(evt) onmousemove=moveDot(evt) onmouseup=moveDotEnd(evt) onmouseout=moveDotEnd(evt) id="slideBar" stroke=lime opacity=.3 stroke-width=30 d="M10,100 L290,100" />
    <path id="sliderPath" stroke="red" fill="none" stroke-width="5" d="M10,100a147,147,0,1,1,280,1"/>
    <circle pointer-events="none"  id="dot" fill="blue" cx="10" cy="100" r="14" />
    </svg>
    </div>
    
    <script>
    var MoveDot=false
    function moveDotStart(evt)
    {
       MoveDot=true
    }
    function moveDot(evt)
    {
        if(MoveDot==true)
        {
            var pathLength=sliderPath.getTotalLength()
            var barLength=slideBar.getTotalLength()
            var xCursor=evt.clientX-10-200
            var moveRatio=xCursor/barLength
            var dotPathLength=moveRatio*pathLength
            var dotPnt=sliderPath.getPointAtLength(dotPathLength)
            dot.setAttribute("cx",dotPnt.x)
            dot.setAttribute("cy",dotPnt.y)
        }
    
    }
    
    function moveDotEnd(evt)
    {
      MoveDot=false
    }
    </script>
    </body>
    </html>

    【讨论】: