d3 v4 中差分力 'center' 之间的转换
Transition between difference force 'center' in d3 v4
当我调整 window 大小时,我启动了一个 'resize' 事件,它将执行:
var width = +container.clientWidth;
var height = +container.clientHeight;
simulation.force('center', d3.forceCenter(width / 2, height / 2));
simulation.alphaTarget(0.3).restart();
将我的节点-link 图置于 canvas 的中间。
这工作正常,但我没有向中心过渡,而是立即跳转。
我想要一个如本例所示的动画:https://bl.ocks.org/mbostock/raw/3355967/
但是,在 d3 v4 中,我不知道如何实现这种转变。我必须使用不同的力量还是可以强制执行 'transition'?我必须在哪里申报?
示例:https://jsfiddle.net/n4m1r8nb/157/(一开始它位于左上角,调整大小时它会'jump'居中')
这似乎已在 d3 v3 中通过以下方式完成:
force.size([width, height]).resume();
但是,此方法在 v4 中不再可用,并已替换为 forceCenter(或 forceX、forceY)。
您可以通过设置 transition
:
var nodes = [{
"id": 1,
"name": "server 1"
}, {
"id": 2,
"name": "server 2"
}, {
"id": 3,
"name": "server 3"
}, {
"id": 4,
"name": "server 4"
}, {
"id": 5,
"name": "server 5"
}, {
"id": 6,
"name": "server 6"
}, {
"id": 7,
"name": "server 7"
}, {
"id": 8,
"name": "server 8"
}, {
"id": 9,
"name": "server 9"
}]
var links = [{
source: 1,
target: 2
}, {
source: 1,
target: 3
}, {
source: 1,
target: 4
}, {
source: 2,
target: 5
}, {
source: 2,
target: 6
}, {
source: 3,
target: 7
}, {
source: 5,
target: 8
}, {
source: 6,
target: 9
}, ]
var index = 10;
var svg = d3.select("svg"),
width = document.getElementById('container').clientWidth,
height = document.getElementById('container').clientHeight,
node,
link;
d3.select(window).on('resize', function() {
var w = document.getElementById('container').clientWidth;
var h = document.getElementById('container').clientHeight;
d3.select({}).transition().delay(500)
.tween("center.move", function() {
var i = d3.interpolateArray([width/2, height/2],[w/2,h/2]);
width = w; height = h;
return function(t) {
var c = i(t);
simulation.force('center', d3.forceCenter(c[0], c[1]));
simulation.alphaTarget(0.3).restart();
};
});
});
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) {
return d.id;
}))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
update();
function update() {
link = svg.selectAll(".link")
.data(links, function(d) {
return d.target.id;
})
link = link.enter()
.append("line")
.attr("class", "link");
node = svg.selectAll(".node")
.data(nodes, function(d) {
return d.id;
})
node = node.enter()
.append("g")
.attr("class", "node");
node.append("circle")
.attr("r", 2.5)
simulation
.nodes(nodes)
.on("tick", ticked);
simulation.force("link")
.links(links);
}
function ticked() {
link
.attr("x1", function(d) {
return d.source.x;
})
.attr("y1", function(d) {
return d.source.y;
})
.attr("x2", function(d) {
return d.target.x;
})
.attr("y2", function(d) {
return d.target.y;
});
node
.attr("transform", function(d) {
return "translate(" + d.x + ", " + d.y + ")";
});
}
.link {
stroke: #aaa;
}
svg {
width: 100%;
height: 100%;
}
#container {
width: 100%;
height: 100%;
}
.node {
pointer-events: all;
stroke: none;
stroke-width: 40px;
}
<script src="http://d3js.org/d3.v4.js"></script>
<div id="container">
<svg></svg>
</div>
对于立即过渡(并且比补间更容易的替代方法),只需删除当前控制中心的力,然后创建一个新力:
例如
d3.select(window).on('resize', function() {
let w = document.getElementById('container').clientWidth;
let h = document.getElementById('container').clientHeight;
simulation.force("center", null)
simulation.force('center', d3.forceCenter(w / 2, h / 2));
});
如果您正在寻找平滑过渡(与补间一样),只需使用 .force('x', ...)
和 .force('y', ...)
而不是上面的 .force('center', ...)
将我们的节点居中。
当我调整 window 大小时,我启动了一个 'resize' 事件,它将执行:
var width = +container.clientWidth;
var height = +container.clientHeight;
simulation.force('center', d3.forceCenter(width / 2, height / 2));
simulation.alphaTarget(0.3).restart();
将我的节点-link 图置于 canvas 的中间。 这工作正常,但我没有向中心过渡,而是立即跳转。
我想要一个如本例所示的动画:https://bl.ocks.org/mbostock/raw/3355967/
但是,在 d3 v4 中,我不知道如何实现这种转变。我必须使用不同的力量还是可以强制执行 'transition'?我必须在哪里申报?
示例:https://jsfiddle.net/n4m1r8nb/157/(一开始它位于左上角,调整大小时它会'jump'居中')
这似乎已在 d3 v3 中通过以下方式完成:
force.size([width, height]).resume();
但是,此方法在 v4 中不再可用,并已替换为 forceCenter(或 forceX、forceY)。
您可以通过设置 transition
:
var nodes = [{
"id": 1,
"name": "server 1"
}, {
"id": 2,
"name": "server 2"
}, {
"id": 3,
"name": "server 3"
}, {
"id": 4,
"name": "server 4"
}, {
"id": 5,
"name": "server 5"
}, {
"id": 6,
"name": "server 6"
}, {
"id": 7,
"name": "server 7"
}, {
"id": 8,
"name": "server 8"
}, {
"id": 9,
"name": "server 9"
}]
var links = [{
source: 1,
target: 2
}, {
source: 1,
target: 3
}, {
source: 1,
target: 4
}, {
source: 2,
target: 5
}, {
source: 2,
target: 6
}, {
source: 3,
target: 7
}, {
source: 5,
target: 8
}, {
source: 6,
target: 9
}, ]
var index = 10;
var svg = d3.select("svg"),
width = document.getElementById('container').clientWidth,
height = document.getElementById('container').clientHeight,
node,
link;
d3.select(window).on('resize', function() {
var w = document.getElementById('container').clientWidth;
var h = document.getElementById('container').clientHeight;
d3.select({}).transition().delay(500)
.tween("center.move", function() {
var i = d3.interpolateArray([width/2, height/2],[w/2,h/2]);
width = w; height = h;
return function(t) {
var c = i(t);
simulation.force('center', d3.forceCenter(c[0], c[1]));
simulation.alphaTarget(0.3).restart();
};
});
});
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) {
return d.id;
}))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
update();
function update() {
link = svg.selectAll(".link")
.data(links, function(d) {
return d.target.id;
})
link = link.enter()
.append("line")
.attr("class", "link");
node = svg.selectAll(".node")
.data(nodes, function(d) {
return d.id;
})
node = node.enter()
.append("g")
.attr("class", "node");
node.append("circle")
.attr("r", 2.5)
simulation
.nodes(nodes)
.on("tick", ticked);
simulation.force("link")
.links(links);
}
function ticked() {
link
.attr("x1", function(d) {
return d.source.x;
})
.attr("y1", function(d) {
return d.source.y;
})
.attr("x2", function(d) {
return d.target.x;
})
.attr("y2", function(d) {
return d.target.y;
});
node
.attr("transform", function(d) {
return "translate(" + d.x + ", " + d.y + ")";
});
}
.link {
stroke: #aaa;
}
svg {
width: 100%;
height: 100%;
}
#container {
width: 100%;
height: 100%;
}
.node {
pointer-events: all;
stroke: none;
stroke-width: 40px;
}
<script src="http://d3js.org/d3.v4.js"></script>
<div id="container">
<svg></svg>
</div>
对于立即过渡(并且比补间更容易的替代方法),只需删除当前控制中心的力,然后创建一个新力:
例如
d3.select(window).on('resize', function() {
let w = document.getElementById('container').clientWidth;
let h = document.getElementById('container').clientHeight;
simulation.force("center", null)
simulation.force('center', d3.forceCenter(w / 2, h / 2));
});
如果您正在寻找平滑过渡(与补间一样),只需使用 .force('x', ...)
和 .force('y', ...)
而不是上面的 .force('center', ...)
将我们的节点居中。