我使用 D3 创建了带有动态场的力定向图。 它目前已安装缩放功能,但我希望删除缩放功能但保留平移功能。我已经看到了 xyzoom 的使用,但我不确定如何将其转换为代码,或者是否有更好的替代版本可用 任何建议将不胜感激
<svg width="100%" height="100%"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var baseNodes = [
//Base node here
]
var baseLinks = [
//Base links here
]
var nodes = [...baseNodes]
var links = [...baseLinks]
function getNeighbors(node) {
return baseLinks.reduce(function (neighbors, link) {
if (link.target.id === node.id) {
neighbors.push(link.source.id)
} else if (link.source.id === node.id) {
neighbors.push(link.target.id)
}
return neighbors
},
[node.id]
)
}
function isNeighborLink(node, link) {
return link.target.id === node.id || link.source.id === node.id
}
function getNodeColor(node, neighbors) {
if (Array.isArray(neighbors) && neighbors.indexOf(node.id) > -1) {
return node.level === 1 ? 'blue' : 'green'
}
return node.level === 1 ? 'red' : 'gray'
}
function getLinkColor(node, link) {
return isNeighborLink(node, link) ? 'green' : '#E5E5E5'
}
function getTextColor(node, neighbors) {
return Array.isArray(neighbors) && neighbors.indexOf(node.id) > -1 ? 'green' : 'black'
}
var width = window.innerWidth
var height = window.innerHeight
var svg = d3.select('svg')
.attr("width", 1920)
.attr("height", 1080)
.call(d3.zoom().on("zoom", function () {
svg.attr("transform", d3.event.transform)
}))
.append("g")
var linkElements,
nodeElements,
textElements
var linkGroup = svg.append('g').attr('class', 'links')
var nodeGroup = svg.append('g').attr('class', 'nodes')
var textGroup = svg.append('g').attr('class', 'texts')
var selectedId
var linkForce = d3
.forceLink()
.id(function (link) { return link.id })
.strength(function (link) { return link.strength })
var simulation = d3
.forceSimulation()
.force('link', linkForce)
.force('charge', d3.forceManyBody().strength(-2000))
.force('center', d3.forceCenter(width / 1.5, height / 1.5))
var dragDrop = d3.drag().on('start', function (node) {
node.fx = node.x
node.fy = node.y
}).on('drag', function (node) {
simulation.alphaTarget(1).restart()
node.fx = d3.event.x
node.fy = d3.event.y
}).on('end', function (node) {
if (!d3.event.active) {
simulation.alphaTarget(0.05)
}
node.fx = null
node.fy = null
})
function selectNode(selectedNode) {
if (selectedId === selectedNode.id) {
selectedId = undefined
resetData()
updateSimulation()
} else {
selectedId = selectedNode.id
updateData(selectedNode)
updateSimulation()
}
var neighbors = getNeighbors(selectedNode)
nodeElements.attr('fill', function (node) { return getNodeColor(node, neighbors) })
textElements.attr('fill', function (node) { return getTextColor(node, neighbors) })
linkElements.attr('stroke', function (link) { return getLinkColor(selectedNode, link) })
}
function resetData() {
var nodeIds = nodes.map(function (node) { return node.id })
baseNodes.forEach(function (node) {
if (nodeIds.indexOf(node.id) === -1) {
nodes.push(node)
}
})
links = baseLinks
}
function updateData(selectedNode) {
var neighbors = getNeighbors(selectedNode)
var newNodes = baseNodes.filter(function (node) {
return neighbors.indexOf(node.id) > -1 || node.level === 1
})
var diff = {
removed: nodes.filter(function (node) { return newNodes.indexOf(node) === -1 }),
added: newNodes.filter(function (node) { return nodes.indexOf(node) === -1 })
}
diff.removed.forEach(function (node) { nodes.splice(nodes.indexOf(node), 1) })
diff.added.forEach(function (node) { nodes.push(node) })
links = baseLinks.filter(function (link) {
return link.target.id === selectedNode.id || link.source.id === selectedNode.id
})
}
function updateGraph() {
linkElements = linkGroup.selectAll('line')
.data(links, function (link) {
return link.target.id + link.source.id
})
linkElements.exit().remove()
var linkEnter = linkElements
.enter().append('line')
.attr('stroke-width', 1)
.attr('stroke', 'rgba(50, 50, 50, 0.2)')
linkElements = linkEnter.merge(linkElements)
nodeElements = nodeGroup.selectAll('circle')
.data(nodes, function (node) { return node.id })
nodeElements.exit().remove()
var nodeEnter = nodeElements
.enter()
.append('circle')
.attr('r', 5)
.attr('fill', function (node) { return node.level === 1 ? 'red' : 'gray' })
.call(dragDrop)
.on('click', selectNode)
nodeElements = nodeEnter.merge(nodeElements)
textElements = textGroup.selectAll('text')
.data(nodes, function (node) { return node.id })
textElements.exit().remove()
var textEnter = textElements
.enter()
.append('text')
.text(function (node) { return node.label })
.attr('font-size', 16)
.attr('dx', 20)
.attr('dy', 16)
textElements = textEnter.merge(textElements)
}
function updateSimulation() {
updateGraph()
simulation.nodes(nodes).on('tick', () => {
nodeElements
.attr('cx', function (node) { return node.x })
.attr('cy', function (node) { return node.y })
textElements
.attr('x', function (node) { return node.x })
.attr('y', function (node) { return node.y })
linkElements
.attr('x1', function (link) { return link.source.x })
.attr('y1', function (link) { return link.source.y })
.attr('x2', function (link) { return link.target.x })
.attr('y2', function (link) { return link.target.y })
})
simulation.force('link').links(links)
simulation.alphaTarget(0.05).restart()
}
updateSimulation()
</script>
您可以使用
scaleExtent()
关闭缩放。
参考:https://d3js.org/d3-zoom#zoom_scaleExtent
示例:
var svg = d3.select('svg')
.attr("width", 1920)
.attr("height", 1080)
.call(
d3.zoom()
.scaleExtent(1, 1)
.on("zoom", function () {
svg.attr("transform", d3.event.transform)
})
)
.append("g")