2017-03-10 14 views
3

私はd3.jsを新しくしました。ポイントを使って折れ線グラフをドラッグしたかったのです。 x軸とy軸なしで正常に動作しています。 私は参照としてこの例を使用しました:https://bl.ocks.org/mbostock/4342190d3 v4 x軸とy軸の線グラフをドラッグ

軸を線グラフにすると、線は正確にプロットされません。下のスニペットを見てください。

ありがとうございます。

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

 
var 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; 
 
    
 

 
let points = d3.range(1, 10).map(function(i) { 
 
    return [i * width/10, 50 + Math.random() * (height - 100)]; 
 
}); 
 
var x = d3.scaleLinear() 
 
    .rangeRound([0, width]); 
 

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

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

 
var 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 + ')') 
 

 
var 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) { 
 
    d3.select(this) 
 
     .attr('cx', d[0] = d3.event.x) 
 
     .attr('cy', d[1] = d3.event.y) 
 
    focus.select('path').attr('d', line); 
 
} 
 

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

 
</script>

答えて

6

d3.event画素位置を保持しているが、あなたのプロットは、ユーザー空間の座標によって駆動されます。したがって、それらのピクセル位置をユーザー空間に変換する必要があります。そうするには、スケールinvertを使用することができます。

function dragged(d) { 
    d[0] = x.invert(d3.event.x); // convert to user-space 
    d[1] = y.invert(d3.event.y); 
    d3.select(this) 
     .attr('cx', x(d[0])) // back to pixels 
     .attr('cy', y(d[1])) 
    focus.select('path').attr('d', line); //line does pixel conversion too 
} 

実行コードは:

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

 
var 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; 
 
    
 

 
let points = d3.range(1, 10).map(function(i) { 
 
    return [i * width/10, 50 + Math.random() * (height - 100)]; 
 
}); 
 
var x = d3.scaleLinear() 
 
    .rangeRound([0, width]); 
 

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

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

 
var 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 + ')') 
 

 
var 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>

+0

これは私が...おかげでマークを探しているものです。.. – user3085628

関連する問題