首页 > 解决方案 > 我可以在 d3.js 中使用 drag.container 来限制拖动区域吗?

问题描述

我试图理解 d3.drag() 但我无法掌握drag.container()部分中的内容,所以我在这里寻求帮助。

这是我理解的方式:如果我添加容器功能,那么我可以限制我可以拖动的区域。如果解释正确,那么我该如何使用它?

例如,在下面的代码片段中,我创建了一个可以拖动的圆圈。但我只想限制白色圆圈内的拖动区域。我可以使用 drag.container() 吗?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://d3js.org/d3.v6.min.js"></script>

    <style>

    </style>

</head>
<body>



    <script>

        const svg = d3.select("body").append("svg").attr("width", "600").attr("height", "500").style("background", "lightblue");

        // Can I use this circle as the container?
        const circleAsContainer = svg.append("circle").attr("cx", "180").attr("cy", "200").attr("r", "120").attr("fill", "white")

        const circle = svg.append("circle").attr("cx", "120").attr("cy", "150").attr("r", "30").attr("fill", "orange").call(d3.drag() 
            .on("start", (event, d) => circle.attr("stroke", "black").attr("stroke-width", "4"))
            .on("drag", (event, d) => circle.attr("cx", d => event.x).attr("cy", d => event.y))
            .on("end", (event, d) => circle.attr("stroke", "none"))
        );


    </script>
</body>
</html>

标签: javascriptd3.js

解决方案


这是我的代码。试试把蓝圈移到红圈外面~

    .active {
      stroke: #000;
      stroke-width: 2px;
  } 
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <svg width="1000" height="500" style="border: 1px solid black">
    <circle cx="250" cy="250" r="200" style="fill:none;stroke:#FF7F7F;stroke-width:16px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;z-index: 1;"/>
    <circle cx="750" cy="250" r="200" style="fill:none;stroke:#FF7F7F;stroke-width:16px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;z-index: 1;"/>
  </svg>  
  <script>
  
  var svg = d3.select("svg"),
      width = +svg.attr("width"),
      height = +svg.attr("height"),
      radius = 32; 
 
  var circles = [{},{},
               // dcx: default_center_X_coordinate
                 {dcx: 250, dcy: 250, color: '#1f77b4', id: 0}, 
                 {dcx: 750, dcy: 250, color: '#aec7e8', id: 1}]; 
  
  svg.selectAll("circle")
    .data(circles)
    .enter().append("circle")
      .attr("cx", function(d) { return d.dcx; })
      .attr("cy", function(d) { return d.dcy; })
      .attr("dcx", function(d) { return d.dcx; })
      .attr("dcy", function(d) { return d.dcy; })
      .attr("r", radius)
      .attr("id", function(d) { return d.id; })
      .style("fill", function(d, i) { return d.color; })
      .call(d3.drag()
        .on("start", dragstarted)
        .on("drag", dragged)
        .on("end", dragended));
   
  function dragstarted(d) {
    d3.select(this)
      .raise()
      .classed("active", true);
  }
  
  function keepInCircle(dcx, dcy, x, y, r) {
    const dx = x - dcx, 
          dy = y - dcy, 
        dist = Math.sqrt(dx * dx + dy * dy)
    return (dist>r) ? { x:dcx+dx/dist*r, y:dcy+dy/dist*r } : {x:x, y:y}  
  } 
  
  function dragged(d) {  
    //console.log(d.id);
    var obj = keepInCircle(d.dcx, d.dcy, d3.event.x, d3.event.y, 200)  
    d3.select(this)
      .attr("cx", obj.x)
      .attr("cy", obj.y);
  }
  
  function dragended(d) {
    d3.select(this)
      .attr("cx", d.dcx)
      .attr("cy", d.dcy)
      .classed("active", false);
  }
  
  </script>


推荐阅读