我设计了一个使用D3 V4树形布局的键盘。在svg上的任意位置先左键单击,以调用zoomed函数,并将translate(0,0)scale(1)应用于标记“ points_g”(代码潘的第595行)。这种偏移会在x尺度值和节点值之间产生差异。(非叶节点值表示x轴值)。
为什么在没有鼠标或触摸板移动的情况下第一次单击左键就将svg转换为translation(0,0)scale(1)。 https://codepen.io/ankit-jo14/pen/qQXweG
在这里反应只是调用this.createcluster()。所有D3填充/渲染都只能通过createcluster方法完成。
/*
* A simple React component
*/
let data = {
"nodeName": "node3",
"parentName": null,
"height": 0.9855515016920474,
"children": [{
"nodeName": "PI101404A",
"parentName": "node3",
"height": 0,
"children": null
}, {
"nodeName": "node2",
"parentName": "node3",
"height": 0.7673460120162033,
"children": [{
"nodeName": "PI103079",
"parentName": "node2",
"height": 0,
"children": null
}, {
"nodeName": "node1",
"parentName": "node2",
"height": 0.6499660584648042,
"children": [{
"nodeName": "PI123440",
"parentName": "node1",
"height": 0,
"children": null
}, {
"nodeName": "node0",
"parentName": "node1",
"height": 0.3968508997429306,
"children": [{
"nodeName": "PI124871",
"parentName": "node0",
"height": 0,
"children": null
}, {
"nodeName": "PI131531",
"parentName": "node0",
"height": 0,
"children": null
}]
}]
}]
}]
};
class HCluster extends React.Component {
constructor(props) {
super(props);
// Don't call this.setState() here!
this.state = {
svgwidth: 1000,
svgheight: 1000
};
}
componentDidMount() {
this.createcluster();
}
componentDidUpdate() {
this.createcluster();
}
createcluster() {
let pcamargin = {
top: 20,
right: 150,
bottom: 20,
left: 30
};
let width = this.state.svgwidth;
let height = this.state.svgheight - 20;
let root = d3.hierarchy(this.props.data);
// height and width are opposite of dim as it 90 degree roteted.
var tree = d3
.cluster()
.size([height - pcamargin.bottom, width - pcamargin.right]);
tree(root);
console.log(root);
let cluster = d3.select(this.refs.anchor);
cluster.selectAll("*").remove();
cluster.attr("width", this.state.svgwidth);
cluster.attr("height", this.state.svgheight);
// create a clipping region
cluster
.append("defs")
.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
// create scale objects
let xScale = d3
.scaleLinear()
.domain([0, 1])
.range([width - pcamargin.left, 0]);
// create axis objects
let xAxis = d3.axisBottom(xScale).ticks(20, "s");
// Draw Axis
let gX = cluster
.append("g")
.attr(
"transform",
"translate(" +
pcamargin.left +
"," +
(this.state.svgheight - pcamargin.bottom) +
")"
)
.call(xAxis);
let zoom = d3
.zoom()
.extent([
[0, 0],
[width, height]
])
.on("zoom", zoomed);
cluster
.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.style("pointer-events", "all")
.attr(
"transform",
"translate(" + pcamargin.left + "," + pcamargin.top + ")"
)
.call(zoom);
// Draw Datapoints
var points_g = cluster
.append("g")
.attr(
"transform",
"translate(" + pcamargin.left + "," + pcamargin.top + ")"
)
.attr("clip-path", "url(#clip)")
.classed("points_g", true);
let links = points_g
.selectAll(".link")
.data(root.descendants().slice(1))
.enter()
.append("path");
links.each(function (d) {
// console.log("d.y before " +d.data.name +" "+ d.y + " height" + d.data.height );
//d.y = d.depth * 120 + (d.children ? d.data.height : height - 160 );
//d.y = (height/2) - d.data.height;
return (d.y = xScale(d.data.height));
// console.log("d.y after " + d.y);
});
links.attr("class", "link").attr("d", function (d) {
return (
"M" +
d.y +
"," +
d.x +
"L" +
d.parent.y +
"," +
d.x +
" " +
d.parent.y +
"," +
d.parent.x
);
});
let nodes = points_g
.selectAll(".node")
.data(root.descendants())
.enter()
.append("g")
.attr("class", function (d) {
return "node" + (d.children ? " node--internal" : " node--leaf");
})
.attr("transform", function (d) {
return (
"rotate( 0 " +
d.y +
"," +
d.x +
")" +
" translate(" +
d.y +
"," +
d.x +
")"
);
});
nodes.append("circle").attr("r", 2.5);
nodes
.append("text")
.attr("x", 10)
.attr("y", 2)
.text(function (d) {
return d.children ? d.data.height : d.data.name;
});
// width = +svg.attr("width");
// height = +svg.attr("height");
// var g = svg.append("g").attr("transform", "translate(40,0)");
function zoomed() {
console.log("zoomcalled");
var new_xScale = d3.event.transform.rescaleX(xScale);
points_g.attr("transform", d3.event.transform);
gX.call(xAxis.scale(new_xScale));
}
}
render() {
return <svg ref="anchor" />;
}
}
/*
* Render the above component into the div#app
*/
ReactDOM.render(
<HCluster data={data} />,
document.getElementById("app")
);