Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript mousedown事件到鼠标点击点的SVG路径移动_Javascript_Html_D3.js - Fatal编程技术网

Javascript mousedown事件到鼠标点击点的SVG路径移动

Javascript mousedown事件到鼠标点击点的SVG路径移动,javascript,html,d3.js,Javascript,Html,D3.js,我需要创建一个圆,并在mousedown事件中平滑地将其移动到SVG路径中最近的点 检查: 守则: var points = [[180,300],[234,335],[288,310],[350,290],[405,300],[430,305],[475,310],[513,300],[550,280]]; var width = 1000, height = 600; var line = d3.svg.line().interpolate("cardinal"); var svg = d3

我需要创建一个圆,并在mousedown事件中平滑地将其移动到SVG路径中最近的点

检查:

守则:

var points = [[180,300],[234,335],[288,310],[350,290],[405,300],[430,305],[475,310],[513,300],[550,280]];
var width = 1000, height = 600;
var line = d3.svg.line().interpolate("cardinal");
var svg = d3.select("#Con").append("svg").attr("width", width).attr("height", height);
var path = svg.append("path").datum(points).attr("d", line);
var line = svg.append("line");
var circle = svg.append("circle").attr("cx", -10).attr("cy", -10).attr("r", 3.5);
svg.append("rect").attr("width", width).attr("height", height).on("mousedown", mouseclick);
var lastIndex = 0;
function mouseclick() {
    let m = d3.mouse(this);
    let p = closestPoint(path.node(), m);
    let forward = true;
    let currentPoint = path.node().getPointAtLength(lastIndex);                  
    if (p[0] < currentPoint.x){
        forward = false;
    }
    let pathLength = path.node().getTotalLength();
    getAnimate(pathLength, path, lastIndex, p[0], forward)();
}

function getAnimate(pLength, path, currentIndex, finishPos, forward){
            document.getElementById('test').innerHTML = forward;
     let animate = function (){
          let scan = path.node().getPointAtLength(currentIndex);
          if (scan.x < finishPos || !forward && scan.x > finishPos){
              circle.attr("cx", scan.x).attr("cy", scan.y);
           }
           if (forward){
               currentIndex += 1;
               lastIndex = currentIndex;
               if (scan.x < finishPos){
                   setTimeout(animate, 3);
               }
            } else {
                currentIndex -= 1;
                lastIndex = currentIndex;
                if (scan.x > finishPos){
                    setTimeout(animate, 3);
                }
            }
       }
            return animate;
        }

            function closestPoint(pathNode, point) {
                var pathLength = pathNode.getTotalLength(),precision = 8,best,bestLength,bestDistance = Infinity;
                for (var scan, scanLength = 0, scanDistance; scanLength <= pathLength; scanLength += precision) {
                    if ((scanDistance = distance2(scan = pathNode.getPointAtLength(scanLength))) < bestDistance) {
                        best = scan, bestLength = scanLength, bestDistance = scanDistance;
                    }
                }
                precision /= 2;
                while (precision > 0.5) {
                    var before,after,beforeLength,afterLength,beforeDistance,afterDistance;
                    if ((beforeLength = bestLength - precision) >= 0 && (beforeDistance = distance2(before = pathNode.getPointAtLength(beforeLength))) < bestDistance) {
                        best = before, bestLength = beforeLength, bestDistance = beforeDistance;
                    } else if ((afterLength = bestLength + precision) <= pathLength && (afterDistance = distance2(after = pathNode.getPointAtLength(afterLength))) < bestDistance) {
                        best = after, bestLength = afterLength, bestDistance = afterDistance;
                    } else {
                        precision /= 2;
                    }
                }
                best = [best.x, best.y];
                best.distance = Math.sqrt(bestDistance);
                return best;
                function distance2(p) {
                    var dx = p.x - point[0],dy = p.y - point[1];
                    return dx * dx + dy * dy;
                }
            }
var points=[[180300]、[234335]、[288310]、[350290]、[405300]、[430305]、[475310]、[513300]、[550280];
变量宽度=1000,高度=600;
var line=d3.svg.line().interpolate(“基数”);
var svg=d3.select(“#Con”).append(“svg”).attr(“width”,width).attr(“height”,height);
var path=svg.append(“path”).datum(points).attr(“d”,line);
var line=svg.append(“line”);
var circle=svg.append(“circle”).attr(“cx”、-10).attr(“cy”、-10).attr(“r”,3.5);
svg.append(“rect”).attr(“width”,width).attr(“height”,height).on(“mousedown”,mouseclick);
var lastIndex=0;
函数mouseclick(){
设m=d3.鼠标(this);
设p=closestPoint(path.node(),m);
向前看=正确;
让currentPoint=path.node().getPointAtLength(lastIndex);
if(p[0]finishPos){
圆圈.attr(“cx”,scan.x).attr(“cy”,scan.y);
}
如果(转发){
currentIndex+=1;
lastIndex=当前索引;
如果(扫描x完成POS){
设置超时(动画,3);
}
}
}
返回动画;
}
函数闭合点(路径节点,点){
var pathLength=pathNode.getTotalLength(),精度=8,最佳,最佳长度,最佳距离=无穷大;
对于(变量扫描,扫描长度=0,扫描距离;扫描长度0.5){
变量前、后、前长度、后长度、前距离、后距离;
如果((beforeLength=bestLength-precision)>=0&&(beforeDistance=distance2(before=pathNode.getPointAtLength(beforeLength))setTimeout
。例如:

let timer;

function getAnimate(pLength, path, currentIndex, finishPos, forward) {
  let animate = function() {
    clearTimeout(timer);
    //etc...
    if (forward) {
      if (scan.x < finishPos) {
        timer = setTimeout(animate, 50);
      }
    } else {
      if (scan.x > finishPos) {
        timer = setTimeout(animate, 50);
      }
    }
  }
  return animate;
}

最简单的解决方案(无需过多重构代码)是清除当前的
设置超时时间。例如:

let timer;

function getAnimate(pLength, path, currentIndex, finishPos, forward) {
  let animate = function() {
    clearTimeout(timer);
    //etc...
    if (forward) {
      if (scan.x < finishPos) {
        timer = setTimeout(animate, 50);
      }
    } else {
      if (scan.x > finishPos) {
        timer = setTimeout(animate, 50);
      }
    }
  }
  return animate;
}