在 D3 上使用平移但不缩放

问题描述 投票:0回答:1

我使用 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>
javascript d3.js d3-force-directed
1个回答
0
投票

您可以使用

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")
© www.soinside.com 2019 - 2024. All rights reserved.