D3 polygonContains()用于简单的rect

时间:2017-05-26 05:52:52

标签: d3.js svg

我过去曾使用polygonContains(polygon, [x,y]),我注意到polygon参数需要坐标。我没有那种数据结构,如果你愿意,我有更多的“预制”SVG形状。特别是SVG rects。

问题:当您实际只有SVG请求时,实施polygongContains()调用有哪些选项?

我最初的想法是通过在rect创建时对SVG rect进行逆向工程:

.on('click', function(d) {
    var containing_rect = d3.select(this);
    console.log(containing_rect)
    console.log(containing_rect.x1)
    var points_contained = d3.selectAll('circle').filter(function(d) {
        return !d3.polygonContains(containing_rect, [x(d.x),y(d.y)]);
    })
})

containing_rect.x1在日志中显示为undefined,这让我相信我的逆向工程方法无法获得矩形的终点。

也许有更好的方法可以在传递参数方面与polygonContains()进行交互,以便将SVG矩形用作4边界边界(调用期望)。

2 个答案:

答案 0 :(得分:1)

您可以创建自己的函数来检查圆是否在矩形内。

例如,我刚写的这个函数:

function containing(container, point) {
    var border = container.node().getBBox();
    var coordinates = {
        left: border.x,
        right: border.x + border.width,
        top: border.y,
        bottom: border.y + border.height
    };
    if (point.attr("cx") > coordinates.left && 
        point.attr("cx") < coordinates.right && 
        point.attr("cy") > coordinates.top && 
        point.attr("cy") < coordinates.bottom) {
        return true
    } else {
        return false
    }
}

它有两个参数,container(矩形)和points(圆圈),都是D3选择。

以下是该功能的演示,我创建了100个圆圈并随机定位。那些落在矩形之外的是黄色的,落在里面的那些是蓝色的:

var w = 400,
  h = 200;

var svg = d3.select("body")
  .append("svg")
  .attr("width", w)
  .attr("height", h);

var rectangle = svg.append("rect")
  .attr("x", 100)
  .attr("y", 50)
  .attr("width", 150)
  .attr("height", 100)
  .attr("fill", "white")
  .attr("stroke", "teal");

var circles = svg.selectAll("schrodinger")
  .data(d3.range(100))
  .enter()
  .append("circle")
  .attr("cx", function(d) {
    return Math.random() * w
  })
  .attr("cy", function(d) {
    return Math.random() * h
  })
  .attr("r", 4);

circles.each(function() {
  var circle = d3.select(this);
  circle.attr("fill", function() {
    return containing(rectangle, circle) ? "royalblue" : "goldenrod";
  })
});

function containing(container, point) {
  var border = container.node().getBBox();
  var coordinates = {
    left: border.x,
    right: border.x + border.width,
    top: border.y,
    bottom: border.y + border.height
  };
  if (point.attr("cx") > coordinates.left && point.attr("cx") < coordinates.right && point.attr("cy") > coordinates.top && point.attr("cy") < coordinates.bottom) {
    return true
  } else {
    return false
  }
}
<script src="https://d3js.org/d3.v4.min.js"></script>

奖励:使用D3拖动,您可以检查拖动功能内圆圈的位置。这是一个演示,拖动矩形:

var w = 400,
  h = 200;

var svg = d3.select("body")
  .append("svg")
  .attr("width", w)
  .attr("height", h);

var rectangle = svg.append("rect")
  .datum({
    x: 100,
    y: 50
  })
  .attr("x", function(d) {
    return d.x
  })
  .attr("y", function(d) {
    return d.y
  })
  .attr("width", 150)
  .attr("height", 100)
  .attr("fill", "white")
  .attr("stroke", "teal")
  .call(d3.drag().on("drag", dragged));

var circles = svg.selectAll("schrodinger")
  .data(d3.range(100))
  .enter()
  .append("circle")
  .attr("cx", function(d) {
    return Math.random() * w
  })
  .attr("cy", function(d) {
    return Math.random() * h
  })
  .attr("r", 4)
  .attr("pointer-events", "none");

circles.each(function() {
  var circle = d3.select(this);
  circle.attr("fill", function() {
    return containing(rectangle, circle) ? "royalblue" : "goldenrod";
  })
});

function containing(container, point) {
  var border = container.node().getBBox();
  var coordinates = {
    left: border.x,
    right: border.x + border.width,
    top: border.y,
    bottom: border.y + border.height
  };
  if (point.attr("cx") > coordinates.left && point.attr("cx") < coordinates.right && point.attr("cy") > coordinates.top && point.attr("cy") < coordinates.bottom) {
    return true
  } else {
    return false
  }
}

function dragged(d) {
  d3.select(this).attr("x", d.x = d3.event.x).attr("y", d.y = d3.event.y);
  circles.each(function() {
    var circle = d3.select(this);
    circle.attr("fill", function() {
      return containing(rectangle, circle)  ? "royalblue" : "goldenrod";
    })
  });
}
<script src="https://d3js.org/d3.v4.min.js"></script>

编辑:如果您想使用polygonContains,我们首先获取矩形的角,就像我们在上一个代码段中所做的那样,并填充一个名为polygon的数组。然后,我们在您的选择中使用它:

circles.each(function() {
    var points = [+d3.select(this).attr("cx"), +d3.select(this).attr("cy")]
    d3.select(this).attr("fill", function() {
        return d3.polygonContains(polygon, points) ? "green" : "red";
    })
});

这是一个演示:

var w = 400,
  h = 200;

var svg = d3.select("body")
  .append("svg")
  .attr("width", w)
  .attr("height", h);

var rectangle = svg.append("rect")
  .datum({
    x: 100,
    y: 50
  })
  .attr("x", function(d) {
    return d.x
  })
  .attr("y", function(d) {
    return d.y
  })
  .attr("width", 150)
  .attr("height", 100)
  .attr("fill", "white")
  .attr("stroke", "teal");

var border = rectangle.node().getBBox();
var corners = {
  left: border.x,
  right: border.x + border.width,
  top: border.y,
  bottom: border.y + border.height
};
var polygon = [
  [corners.left, corners.top],
  [corners.right, corners.top],
  [corners.right, corners.bottom],
  [corners.left, corners.bottom]
];

var circles = svg.selectAll("schrodinger")
  .data(d3.range(100))
  .enter()
  .append("circle")
  .attr("cx", function(d) {
    return Math.random() * w
  })
  .attr("cy", function(d) {
    return Math.random() * h
  })
  .attr("r", 3);

circles.each(function() {
  var points = [+d3.select(this).attr("cx"), +d3.select(this).attr("cy")]
  d3.select(this).attr("fill", function() {
    return d3.polygonContains(polygon, points) ? "green" : "red";
  })
});
<script src="https://d3js.org/d3.v4.min.js"></script>

答案 1 :(得分:-1)

您可以使用

D:\project>create-react-native-app crna
Creating a new React Native app in D:\project\crna.

Installing packages. This might take a couple minutes.
Installing react-native-scripts...

npm WARN deprecated fs-promise@1.0.0: Use mz or fs-extra^3.0 with Promise Suppor
t
npm WARN deprecated @exponent/spawn-async@1.2.8: Please switch to @expo/spawn-as
ync, the new name of this package. It's the same code with our new name.
npm ERR! shasum check failed for C:\Users\ui-admin\AppData\Local\Temp\npm-3204-a
eacedd1\registry.npmjs.org\_40exponent\ngrok\-\ngrok-2.2.7.tgz
npm ERR! Expected: 37fe66f922b1003da2a78c66b7d4d3bc9313e423
npm ERR! Actual:   d134060eb730b880da06d5c040ca933f6a75b613
npm ERR! From:     https://registry.npmjs.org/@exponent/ngrok/-/ngrok-2.2.7.tgz

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\ui-admin\AppData\Roaming\npm-cache\_logs\2017-05-26T09_36_
04_379Z-debug.log
`npm install --save-dev --save-exact react-native-scripts` failed

检索rect的左上角和

的x和y坐标
containing_rect.attr("x")
containing_rect.attr("y")

检索宽度和高度。那你就算数学了;)