代码之家  ›  专栏  ›  技术社区  ›  Stav Alfi

D3.js v4+-如何确定强制装卸中的具体位置

  •  0
  • Stav Alfi  · 技术社区  · 6 年前

    其他在线教程/答案是关于D3.jsv3.x或可拖动元素的特定位置。

    我看了文档,不太明白怎么做:

    我试图阻止红色矩形与圆形重叠而不改变矩形的位置。

    我指定了 fx fy 但仍然没有成功。

    const nodes = d3.range(100).map(d => ({radius: 5, type: "circle"}));
    
    const walls = [{}, {}, {}, {}].map((_, index) => ({
        fx: 200 * index,
        fy: 100,
        type: "wall"
    }));
    
    const circleCenters = [100, 300, 500];
    
    d3.forceSimulation(nodes.concat(walls))
        .force('charge', d3.forceManyBody().strength(10))
        .force('x', d3.forceX().x(function (d, i) {
            if (d.type === "circle")
                return circleCenters[i % 3];
            else
                return d.fx;
        }))
        .force('y', d3.forceY().y(100))
        .force('collision', d3.forceCollide().radius(d => d.radius))
        .on('tick', ticked);
    
    function ticked() {
        d3.select('svg')
            .selectAll('rect')
            .data(walls)
            .enter()
            .append('rect')
            .attr('width', 100)
            .attr('height', 10)
            .attr('fill', 'red')
            .attr('x', d => d.x)
            .attr('y', d => d.y);
    
        const u = d3.select('svg')
            .selectAll('circle')
            .data(nodes);
    
        u.enter()
            .append('circle')
            .merge(u)
            .attr('fill', 'blue')
            .attr('r', d => d.radius)
            .attr('cx', d => d.x)
            .attr('cy', d => d.y);
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.js"></script>
    <svg width="90vw" height="90vh">
    </svg>
    1 回复  |  直到 6 年前
        1
  •  1
  •   rioV8    6 年前

    您需要用正确大小的保护节点填充整个rect。

    如果你想看到守护圈的注释部分代码。

    有两个 g 元素,一个包含保护节点,另一个包含 blue 节点。

    编辑

    .force('x', d3.forceX()
        .x( (d, i) => (d.type === "circle") ? circleCenters[i % 3] : d.fx )
        .strength(0.3))
    

    const nodes = d3.range(100).map(d => ({radius: 5, type: "circle"}));
    
    const walls = [{}, {}, {}, {}].map((_, index) => ({
        fx: 200 * index,
        fy: 100,
        width: 100,
        height: 10,
        radius: 5,
        type: "wall"
    }));
    
    const circleCenters = [100, 300, 500];
    
    // construct "invisible" circles covering the rects
    var invCircles = [];
    walls.forEach(e => {
        d3.range(e.fx+3, e.fx+e.width-3, 3).forEach(cx => {
            invCircles.push({
                fx: cx,
                fy: e.fy + e.radius,
                radius: e.radius,
                type: e.type
            });
        });
    });
    
    d3.forceSimulation(nodes.concat(invCircles))
        .force('charge', d3.forceManyBody().strength(10))
        .force('x', d3.forceX().x( (d, i) => (d.type === "circle") ? circleCenters[i % 3] : d.fx ).strength(0.3))
        .force('y', d3.forceY().y(100))
        .force('collision', d3.forceCollide().radius(d => d.radius))
        .on('tick', ticked);
    
    var wallGeom = d3.select('svg').append('g').attr('class', 'wall');
    var circlesGeom = d3.select('svg').append('g').attr('class', 'circles');
    
    wallGeom.selectAll('rect')
        .data(walls)
        .enter()
        .append('rect')
        .attr('width', d => d.width )
        .attr('height', d => d.height )
        .attr('fill', 'red')
        .attr('x', d => d.fx)
        .attr('y', d => d.fy);
    
    // wallGeom.selectAll('circle')
    //     .data(invCircles)
    //     .enter()
    //     .append('circle')
    //       .attr('fill', 'yellow')
    //       .attr('r', d => d.radius)
    //       .attr('cx', d => d.fx)
    //       .attr('cy', d => d.fy);
    
    function ticked() {
    
        const u = d3.select('svg')
            .select('.circles')
            .selectAll('circle')
            .data(nodes);
    
        u.enter()
            .append('circle')
            .attr('fill', 'blue')
            .attr('r', d => d.radius)
          .merge(u)
            .attr('cx', d => d.x)
            .attr('cy', d => d.y);
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.js"></script>
    <svg width="90vw" height="90vh"></svg>