如何计算 D3 中矩形之间的距离?

时间:2021-03-02 20:38:06

标签: d3.js data-visualization

我正在做这个项目,我需要计算矩形之间的距离?有什么想法吗?

我的目标是从华盛顿邮报的这篇文章中复制一篇关于 Covid 的文章:https://www.washingtonpost.com/graphics/2020/health/coronavirus-herd-immunity-simulation-vaccine/

图片下方是我用来生成这个图表的代码。

谢谢!!

enter image description here

export function main(){
  createSVG()
  build()

}

let offset = {top: 20, left: 70}
let screenWidth = 800 - offset.left
let screenHeight = 400 - offset.top


function createSVG() {
    let container = d3.select('#container')
    svg = container.append('svg')
    .attr('id', 'canvas')
    .attr('width', screenWidth + offset.left)
    .attr('height', screenHeight + offset.top)
}

function build() {
    let rectWidth = 15
    let rectHeight = 15
    let randomMovementLimit = 9

    let people = []
    for(let i = 0; i< 100; i++){
      const cellX = i % 10
      const randomX = Math.random() * randomMovementLimit - 3
      const x = offset.left + cellX * (rectWidth + 10) + randomX
      const cellY = Math.floor(i / 10)
      const randomY = Math.random() * randomMovementLimit - 3
      const y = offset.top + cellY * (rectHeight + 10) + randomY
      const infected = Math.random() > 0.5
      people.push({x: x, y: y, cellX: cellX, cellY: cellY, infected: infected})
    }

    console.log(people[0])

    const infectedPeople = people.filter
    const healtyPeople = people.filter

    let rects = svg.selectAll('rect')
      .data(people)
      .enter()
      .append('rect')
        .attr('x', function(d,i) {
            return d.x
          })
        .attr('y', function(d,i) {
          return d.y
          })  
        .attr('height', rectHeight) 
        .attr('width', rectWidth)
        .style('fill', (d, i) => {
          return d.infected ? "red" : "blue"
        }) 

        .attr('rx', 5)

}

1 个答案:

答案 0 :(得分:3)

使用勾股定理计算距每个矩形中心的距离。我想但没有测试我是否记得每个矩形的中心在 d.x + rectWidth/2 和 d.y - rectHeight/2。在构建函数之外初始化 rectWidth 和 rectHeight 使它们在范围内。

在距离先前感染者小于 social_dist 的距离处获取新感染矩形的示例:

let social_dist = 6;

rects.filter(function(d,i){ 
 for (let p of infectedPeople){
   let xDist = (p.x + rectWidth/2) - (d.x + rectWidth/2);
   let yDist = (p.y - rectHeight/2) - (d.y - rectHeight/2);
   let dist = Math.sqrt( xDist*xDist + yDist*yDist );  
   if (dist < social_dist){
   return true;
 }
 return false;
});