2017-09-02 20 views
0

我是使用D3和JavaScript的新手,所以希望這是一個簡單的點,有人可以爲我清理。使用數組和數組對數組的拖拽時的不同行爲

我正在製作一個可拖動點的散點圖,使用與this堆棧溢出問題非常相似的代碼。當我將數據集作爲[x, y]對的數組並將它們稱爲d[0]d[1]時,代碼將按預期工作。然而,當我就與屬性xy對象的數組,提到他們作爲d.xd.y,劇情出現過,但工作 - 被點擊的點擊落低於x軸拖動行爲

所以此代碼的工作:

<!DOCTYPE html> 
 
<svg width="500" height="350"></svg> 
 
<script src="https://d3js.org/d3.v4.min.js"></script> 
 
<script> 
 

 
    let svg = d3.select("svg"), 
 
     margin = {top: 20, right: 20, bottom: 30, left: 50}, 
 
     width = +svg.attr("width") - margin.left - margin.right, 
 
     height = +svg.attr("height") - margin.top - margin.bottom; 
 
    //Make the fake data as an array of [x, y] pairs 
 
    let m=3.0, c=15.0; 
 
    let points = d3.range(1, 10).map(function(i) { 
 
     let x=i * width/10; 
 
     let noise=Math.random()*500; 
 
     let y=m*x+c + noise; 
 
     return [x, y]; 
 
    }); 
 

 

 

 

 

 

 
    let x = d3.scaleLinear() 
 
     .rangeRound([0, width]); 
 

 
    let y = d3.scaleLinear() 
 
     .rangeRound([height, 0]); 
 

 
    let xAxis = d3.axisBottom(x), 
 
     yAxis = d3.axisLeft(y); 
 

 
    let line = d3.line() 
 
     .x(function(d) { return x(d[0]); }) 
 
     .y(function(d) { return y(d[1]); }); 
 

 
    let drag = d3.drag() 
 
     .on('start', dragstarted) 
 
     .on('drag', dragged) 
 
     .on('end', dragended); 
 

 
    svg.append('rect') 
 
     .attr('class', 'zoom') 
 
     .attr('cursor', 'move') 
 
     .attr('fill', 'none') 
 
     .attr('pointer-events', 'all') 
 
     .attr('width', width) 
 
     .attr('height', height) 
 
     .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')') 
 

 
    let focus = svg.append("g") 
 
     .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 
 

 
    x.domain(d3.extent(points, function(d) { return d[0]; })); 
 
    y.domain(d3.extent(points, function(d) { return d[1]; })); 
 

 
    focus.append("path") 
 
     .datum(points) 
 
     .attr("fill", "none") 
 
     .attr("stroke", "steelblue") 
 
     .attr("stroke-linejoin", "round") 
 
     .attr("stroke-linecap", "round") 
 
     .attr("stroke-width", 1.5) 
 
     .attr("d", line); 
 

 
    focus.selectAll('circle') 
 
     .data(points) 
 
     .enter() 
 
     .append('circle') 
 
     .attr('r', 5.0) 
 
     .attr('cx', function(d) { return x(d[0]); }) 
 
     .attr('cy', function(d) { return y(d[1]); }) 
 
     .style('cursor', 'pointer') 
 
     .style('fill', 'steelblue'); 
 

 
    focus.selectAll('circle') 
 
     .call(drag); 
 

 
    focus.append('g') 
 
     .attr('class', 'axis axis--x') 
 
     .attr('transform', 'translate(0,' + height + ')') 
 
     .call(xAxis); 
 

 
    focus.append('g') 
 
     .attr('class', 'axis axis--y') 
 
     .call(yAxis); 
 

 
    function dragstarted(d) { 
 
     d3.select(this).raise().classed('active', true); 
 
    } 
 

 
    function dragged(d) { 
 
     d[0] = x.invert(d3.event.x); 
 
     d[1] = y.invert(d3.event.y); 
 
     d3.select(this) 
 
      .attr('cx', x(d[0])) 
 
      .attr('cy', y(d[1])) 
 
     focus.select('path').attr('d', line); 
 
    } 
 

 
    function dragended(d) { 
 
     d3.select(this).classed('active', false); 
 
    } 
 

 
</script>

但拖動點時,該代碼給出了怪異的行爲:

<!DOCTYPE html> 
 
<svg width="500" height="350"></svg> 
 
<script src="https://d3js.org/d3.v4.min.js"></script> 
 
<script> 
 

 
    let svg = d3.select("svg"), 
 
     margin = {top: 20, right: 20, bottom: 30, left: 50}, 
 
     width = +svg.attr("width") - margin.left - margin.right, 
 
     height = +svg.attr("height") - margin.top - margin.bottom; 
 
    //Make the fake data as an array of objects, with attributes x and y 
 
    let m=3.0, c=15.0; 
 
    let points = d3.range(1, 10).map(function(i) { 
 
     let x_val=i * width/10; 
 
     let noise=Math.random()*500; 
 
     let y_val=m*x_val+c + noise; 
 
     return { 
 
      x:x_val, 
 
      y:y_val 
 

 
     }; 
 
    }); 
 

 

 

 

 

 

 
    let x = d3.scaleLinear() 
 
     .rangeRound([0, width]); 
 

 
    let y = d3.scaleLinear() 
 
     .rangeRound([height, 0]); 
 

 
    let xAxis = d3.axisBottom(x), 
 
     yAxis = d3.axisLeft(y); 
 

 
    let line = d3.line() 
 
     .x(function(d) { return x(d.x); }) 
 
     .y(function(d) { return y(d.y); }); 
 

 
    let drag = d3.drag() 
 
     .on('start', dragstarted) 
 
     .on('drag', dragged) 
 
     .on('end', dragended); 
 

 
    svg.append('rect') 
 
     .attr('class', 'zoom') 
 
     .attr('cursor', 'move') 
 
     .attr('fill', 'none') 
 
     .attr('pointer-events', 'all') 
 
     .attr('width', width) 
 
     .attr('height', height) 
 
     .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); 
 

 
    let focus = svg.append("g") 
 
     .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 
 

 
    x.domain(d3.extent(points, function(d) { return d.x; })); 
 
    y.domain(d3.extent(points, function(d) { return d.y; })); 
 

 
    focus.append("path") 
 
     .datum(points) 
 
     .attr("fill", "none") 
 
     .attr("stroke", "steelblue") 
 
     .attr("stroke-linejoin", "round") 
 
     .attr("stroke-linecap", "round") 
 
     .attr("stroke-width", 1.5) 
 
     .attr("d", line); 
 

 
    focus.selectAll('circle') 
 
     .data(points) 
 
     .enter() 
 
     .append('circle') 
 
     .attr('r', 5.0) 
 
     .attr('cx', function(d) { return x(d.x); }) 
 
     .attr('cy', function(d) { return y(d.y); }) 
 
     .style('cursor', 'pointer') 
 
     .style('fill', 'steelblue'); 
 

 
    focus.selectAll('circle') 
 
     .call(drag); 
 

 
    focus.append('g') 
 
     .attr('class', 'axis axis--x') 
 
     .attr('transform', 'translate(0,' + height + ')') 
 
     .call(xAxis); 
 

 
    focus.append('g') 
 
     .attr('class', 'axis axis--y') 
 
     .call(yAxis); 
 

 
    function dragstarted(d) { 
 
     d3.select(this).raise().classed('active', true); 
 
    } 
 

 
    function dragged(d) { 
 
     d.x = x.invert(d3.event.x); 
 
     d.y = y.invert(d3.event.y); 
 
     d3.select(this) 
 
      .attr('cx', x(d.x)) 
 
      .attr('cy', y(d.y)); 
 
     focus.select('path').attr('d', line); 
 
    } 
 

 
    function dragended(d) { 
 
     d3.select(this).classed('active', false); 
 
    } 
 

 
</script>

任何人都可以解釋爲什麼他們給不同結果,當我改變了所有結構數據的重新?謝謝!

回答

0

對數據的xy屬性混淆默認(subject accessor)[https://github.com/d3/d3-drag#drag_subject]。顯然它會解決問題:

let drag = d3.drag() 
     .on('start', dragstarted) 
     .on('drag', dragged) 
     .subject(function(d){ return {x: x(d.x), y: y(d.y)} }) 
     .on('end', dragended); 
相關問題