2016-08-20 59 views
0

我正在尝试将这个在D3 v3中的JSFiddle迁移到D3 v4,但它不起作用。从D3.js v3迁移到D3.js v4无法正常工作 - 一个选择问题?

我现在知道D3拖动的行为简直是d3.drag()我已经改变,但试图运行它的时候,它给了一个错误在线53:

rect = d3.select(self.rectangleElement[0][0]); 

与Chrome的话说:

Uncaught TypeError: Cannot read property '0' of undefined

我该如何着手改变这个JSFiddle,使其在D3 v4中运行?

回答

1

首先,你为什么要重新选择这些东西?他们已经是你想要的选择。例如,self.rectangleElement是rect的选择。其次,将一个对象传递给.attr是no longer supported in version 4。第三,拖动行为已经改变,圆圈正在吃掉你的第二只老鼠。这里就是我搞掂这些东西一个版本:

d3.select('#rectangle').on('click', function(){ new Rectangle(); }); 
 

 
var w = 600, h = 500; 
 
var svg = d3.select('body').append('svg').attr("width", w).attr("height", h); 
 

 
function Rectangle() { 
 
    var self = this, rect, rectData = [], isDown = false, m1, m2, isDrag = false; 
 
    
 
    svg.on('mousedown', function() { 
 
    \t \t console.log(isDown); 
 
     m1 = d3.mouse(this); 
 
     if (!isDown && !isDrag) { 
 
      self.rectData = [ { x: m1[0], y: m1[1] }, { x: m1[0], y: m1[1] } ]; 
 
      self.rectangleElement = d3.select('svg').append('rect').attr('class', 'rectangle').call(dragR); 
 
      self.pointElement1 = d3.select('svg').append('circle').attr('class', 'pointC').call(dragC1); 
 
      self.pointElement2 = d3.select('svg').append('circle').attr('class', 'pointC').call(dragC2);    
 
      self.pointElement3 = svg.append('circle').attr('class', 'pointC').call(dragC3); 
 
      self.pointElement4 = svg.append('circle').attr('class', 'pointC').call(dragC4); 
 
      updateRect(); 
 
      isDrag = false; 
 
     } else { 
 
      isDrag = true; 
 
     } 
 
     isDown = !isDown; 
 
    }) 
 
    
 
    .on('mousemove', function() { 
 
     m2 = d3.mouse(this); 
 
     if(isDown && !isDrag) { 
 
      self.rectData[1] = { x: m2[0] - 5, y: m2[1] - 5}; 
 
      updateRect(); 
 
     } 
 
    }); 
 
    
 
    function updateRect() { 
 
     self.rectangleElement 
 
     \t \t .attr("x", self.rectData[1].x - self.rectData[0].x > 0 ? self.rectData[0].x : self.rectData[1].x) 
 
      .attr("y", self.rectData[1].y - self.rectData[0].y > 0 ? self.rectData[0].y : self.rectData[1].y) 
 
      .attr("width", Math.abs(self.rectData[1].x - self.rectData[0].x)) 
 
      .attr("height", Math.abs(self.rectData[1].y - self.rectData[0].y)); 
 

 
     var point1 = self.pointElement1.data(self.rectData); 
 
     point1.attr('r', 5) 
 
       .attr('cx', self.rectData[0].x) 
 
       .attr('cy', self.rectData[0].y);   
 
     var point2 = self.pointElement2.data(self.rectData); 
 
     point2.attr('r', 5) 
 
       .attr('cx', self.rectData[1].x) 
 
       .attr('cy', self.rectData[1].y); 
 
     var point3 = self.pointElement3.data(self.rectData); 
 
     point3.attr('r', 5) 
 
       .attr('cx', self.rectData[1].x) 
 
       .attr('cy', self.rectData[0].y);   
 
     var point3 = self.pointElement4.data(self.rectData); 
 
     point3.attr('r', 5) 
 
       .attr('cx', self.rectData[0].x) 
 
       .attr('cy', self.rectData[1].y); 
 
    } 
 
    
 
    var dragR = d3.drag().on('drag', dragRect); 
 
    
 
    function dragRect() { 
 
     var e = d3.event; 
 
     for(var i = 0; i < self.rectData.length; i++){ 
 
      self.rectangleElement 
 
       .attr('x', self.rectData[i].x += e.dx) 
 
       .attr('y', self.rectData[i].y += e.dy); 
 
     } 
 
     self.rectangleElement.style('cursor', 'move'); 
 
     updateRect(); 
 
    } 
 
    
 
    var dragC1 = d3.drag().on('drag', dragPoint1); 
 
    var dragC2 = d3.drag().on('drag', dragPoint2); 
 
    var dragC3 = d3.drag().on('drag', dragPoint3); 
 
    var dragC4 = d3.drag().on('drag', dragPoint4); 
 
    
 
    function dragPoint1() { 
 
     var e = d3.event; 
 
     self.pointElement1 
 
      .attr('cx', function(d) { return d.x += e.dx }) 
 
      .attr('cy', function(d) { return d.y += e.dy });   
 
     updateRect(); 
 
    } 
 
    
 
    function dragPoint2() { 
 
     var e = d3.event; 
 
     self.pointElement2 
 
      .attr('cx', self.rectData[1].x += e.dx) 
 
      .attr('cy', self.rectData[1].y += e.dy); 
 
     updateRect(); 
 
    } 
 
    
 
    function dragPoint3() { 
 
     var e = d3.event; 
 
     self.pointElement3 
 
      .attr('cx', self.rectData[1].x += e.dx) 
 
      .attr('cy', self.rectData[0].y += e.dy);  
 
     updateRect(); 
 
    } 
 
    
 
    function dragPoint4() { 
 
     var e = d3.event; 
 
     self.pointElement4 
 
      .attr('cx', self.rectData[0].x += e.dx) 
 
      .attr('cy', self.rectData[1].y += e.dy); 
 
     updateRect(); 
 
    } 
 
    
 
}//end Rectangle
svg { 
 
    border: solid 1px red; 
 
} 
 

 
rect { 
 
    fill: lightblue; 
 
    stroke: blue; 
 
    stroke-width: 2px; 
 
}
<button id='rectangle'>Rectangle</button> 
 
<script src="https://d3js.org/d3.v4.js" charset="utf-8"></script>

1

从D3 v4开始,选择不再是数组的数组,而是对象。该changelog有它:

Selections no longer subclass Array using prototype chain injection; they are now plain objects, improving performance.

当在做V3 你在访问中选择的第一个节点。要在v4中获得此节点,您需要拨打self.rectangleElement上的selection.node()。有了这个你的代码变为:

rect = d3.select(self.rectangleElement.node()); 

查看更新的JSFiddle为工作版本。

+0

因为小提琴仍然使用d3.js V3该版本工作正常。我在这里更新了http://jsfiddle.net/pjmdbq4s/而不是使用d3.js v4,但它不起作用,控制台在d3.v4.min上显示[Uncaught TypeError:无法读取属性'ownerDocument'为null]。 js:4 – molotofc

+0

在非缩小版本 - d3.v4.js上,显示相同的错误,但在行#7383 [this.ownerDocument = parent.ownerDocument;] – molotofc