问题
I want to show multiple charts in a table, each chart is a separate svg, generated with d3.
The height of each chart has to be easily adjustable - and I want that to be done in a similar manner as you adjust the 4 panels (html, javaScript, css, output) in jsFiddle, by dragging the mouse over a border between those panels - in my case it's only horizontal borders.
I'd like to use d3.behavior.drag(). When the border (a div in a td of the table, or something like that) is dragged, the height of some of the svg elements has to change. In the code I got so far, I'm putting simple div's rather than svg's, to keep things simple.
I got 2 versions; one that "should" be working, but isn't, and one the is working, but I don't like it (it uses d3.mouse(), which "should" be unnecessarily complicated); I would like to find out whether I found a bug in d3, or (more likely), I'm not doing it right in the version that "should" be working.
Here is a fiddle, it shows the working version; to see the not working version (in which "jittering" occurs), switch the names of ondragmove and _ondragmove.
Voilà code:
<table cellspacing="0" cellpadding="0">
<tr><td><div class="content" id="content_0" style="height: 100px; background-color: yellow;"></div></td></tr>
<tr><td><div class="spacer" id="spacer_0"></div></td></tr>
<tr><td><div class="content" id="content_1" style="height: 200px; background-color: green;"></div></td></tr>
<tr><td><div class="spacer" id="spacer_1"></div></td></tr>
<tr><td><div class="content" id="content_2" style="height: 70px; background-color: orange;"></div></td></tr>
<tr><td><div class="spacer" id="spacer_2"></div></td></tr>
</table>
<div><br/>
x <span id="xLog"></span><br/>
y <span id="yLog"></span><br/>
dx <span id="dxLog"></span><br/>
dy <span id="dyLog"></span><br/>
datumX <span id="datumXLog"></span><br/>
datumY <span id="datumYLog"></span><br/>
mouse <span id="mouseLog"></span><br/>
body mouse <span id="bodyMouseLog"></span>
</div>
div.spacer {
width: 400px;
height: 5px;
background-color: #ddd;
cursor: ns-resize;
position: relative;
left: 0;
top: 0;
}
div.content {
width: 400px;
}
var heights = d3.selectAll(".content")[0].map(function(elt){return parseInt(d3.select(elt).style("height"));});
var xElt = d3.select("#xLog");
var yElt = d3.select("#yLog");
var dxElt = d3.select("#dxLog");
var dyElt = d3.select("#dyLog");
var datumXElt = d3.select("#datumXLog");
var datumYElt = d3.select("#datumYLog");
var mouseElt = d3.select("#mouseLog");
var bodyMouseElt = d3.select("#bodyMouseLog");
var theBody = d3.select("body").node();
var drag = d3.behavior.drag()
.origin(function(x){return x;})
.on("drag", dragmove)
.on("dragstart", function(d){
console.log("start" + d.index);
y0 = d3.mouse(theBody)[1];
})
.on("dragend", function(d){
console.log("end " + d.index);
var newHeight = parseFloat(d3.select("#content_" + d.index).style("height"));
heights[d.index] = newHeight;
});
var spacers = d3.selectAll("div.spacer");
spacers.data(d3.range(heights.length).map(function(d,i){ return {x:0, y:0, index: i }}));
spacers.call(drag);
function showDebugOutput(d, that){
xElt.text(d3.event.x);
yElt.text(d3.event.y);
dxElt.text(d3.event.dx);
dyElt.text(d3.event.dy);
datumXElt.text(d.x);
datumYElt.text(d.y);
mouseElt.text(d3.mouse(that).join(", "));
bodyMouseElt.text(d3.mouse(theBody).join(", "));
}
function dragmove_NOT_WORKING(d){
showDebugOutput(d, this);
var elt = d3.select("#content_" + d.index);
var originalHeight = heights[d.index];
var newHeight = originalHeight + d3.event.y;
elt.style("height", newHeight + "px");
d.x = d3.event.x;
d.y = d3.event.y;
elt.html("<br />" + newHeight);
}
function dragmove(d){
showDebugOutput(d, this);
var elt = d3.select("#content_" + d.index);
var originalHeight = heights[d.index];
y1 = d3.mouse(theBody)[1];
var dy = y1 - y0;
var newHeight = originalHeight + dy;
elt.style("height", newHeight + "px");
d.x = d3.event.x;
d.y = dy;
elt.html("<br />" + newHeight);
}
And here is another fiddle, which accomplishes a simpler task (moving around html div elements with d3 drag behavior - the elements moving (on which drag is called) have no "side effects" on other elements, and their style.left and style.top are in one-to-one with x and y of the drag behavior, so very simple, what I'm trying to do is more complicated.) Just to show that it is possible to use drag behavior on non-svg elements.
来源:https://stackoverflow.com/questions/23936524/d3-drag-behavior-not-working-properly-on-html-elements