首页 > 解决方案 > D3在拖动圆圈时获取下方多边形的ID

问题描述

我正在创建一个 d3 对象,它由三角形多边形组成。

我有一个可拖动的圆形指针我如何捕获鼠标下方多边形的 id(在鼠标事件下,而圆形仍然表现得像一个视觉指针)。希望这是有道理的。

html

  <div style="width:1000px;" id="triangle">
    <svg height="1000" width="1000" id="ternary">  
        <defs>
            <!--The Pointe-->
            <g id="pointer" transform="scale(0.8)">
          <circle cx="0" cy="0" r="20" stroke="black" stroke-width="1"/>     
            </g>
        </defs>
         </svg>

</div>

Javascript

   window.addEventListener('load', function() {

        var ternary = d3.select("#ternary");
        var pointer = d3.select("#pointer");
        var w = 50,
            h = 50,
            rows = 20;
        b = 1000;
        t = 950;
        wm = 25;
        var osb = 0;

        for (s = 1; s <= 20; s++) {

            if (!s % 2 == 0) {
                rb = b - osb;
                rt = t - osb;

            } else {
                rb = b - osb;
                rt = t - osb;

            }
            for (i = 1; i <= rows - s; i++) {
                console.log();
                osl = (i - 1) * w + ((s - 1) * 25);
                if (s) {
                    if (s % 2 == 0) {
                        trColor = '#3c763d';
                        osl = (i - 1) * w + ((s - 1) * 25);
                        var x1 = osl;
                        var x2 = osl + (w / 2);;
                        var x3 = osl + w;
                        // console.log(rt);
                        ternary.append('polygon')
                            .attr('points', osl + ' ' + (rt) + ',  ' + x3 + ' ' + (rt) + ' , ' + x2 + ' ' + (rb))
                            .attr('class', 'r' + s + 'c' + i)
                            .style('fill', '#3c754d');
                    } else {
                        trColor = '#3c739d'
                        osl = (i - 1) * w + ((s - 1) * 25);
                        var x1 = osl;
                        var x2 = osl + (w / 2);;
                        var x3 = osl + w;

                        ternary.append('polygon')
                            .attr('points', osl + ' ' + rb + ',  ' + x2 + ' ' + rt + ' , ' + x3 + ' ' + rb)
                            .attr('class', 'r' + s + 'c' + i)
                            .style('fill', '#3c763d');

                    };

                }
            }

            if (s % 2 == 0 && s > 2) {

                osb = osb + 50;
            }
        }




        ternary.append("use")
            .attr("href", "#pointer")
            .attr("x", 500)
            .attr("y", 875)
            .attr("fill", "#039BE5")
            .attr("stroke", "#039BE5")
            .attr("stroke-width", "1px");


        var dragHandler = d3.drag()
            .on("drag", function() {
                d3.select(this)
                    .attr("x", d3.event.x)
                    .attr("y", d3.event.y);
                /*
                  How do I Get the id of underlying triangle?
                */

            });

        dragHandler(svg.selectAll("use"));
    });

他们是实现这一目标的直接方法吗?

标签: javascriptd3.js

解决方案


有几个选项可以找到拖动元素下的内容。

一种是利用拖动的startend事件,根据需要改变被拖动对象的指针事件属性。在拖动开始时,我们可以将其设置为none,在拖动结束时,我们可以将指针事件恢复为all。尽管将指针事件设置为无,但拖动仍在继续,但现在指针事件现在可以针对被拖动元素下方的内容触发。

如果我们只希望它们响应拖动事件,我们还可以使用开始/结束事件将事件侦听器添加到底层元素。

下面的代码片段使用了这个想法,拖动圆圈与底层矩形进行交互。当拖动开始时,指针事件从圆圈中移除,鼠标事件监听器被添加到矩形中。在拖动结束时,一切都恢复到原来的样子:

var svg = d3.select("body")
  .append("svg")
  .attr("width",500)
  .attr("height",300);
  
function color(d) {
  return d3.scaleLinear()
    .range(["teal","steelblue","crimson","orange"])
    .domain([0,30,40,60])(d);
}
  
var grid = svg.selectAll(null)
  .data(d3.range(60))
  .enter()
  .append("rect")
  .attr("width", 50)
  .attr("height", 50)
  .attr("y", function(d) { return Math.floor(d/10)*50; })
  .attr("x", function(d) { return d%10*50; })
  .attr("fill", color)
  .attr("id", function(d){
    return "rect-"+d;
  })

  
var circle  = svg.append("circle")
  .attr("cx", 100)
  .attr("cy", 100)
  .attr("r", 10);
  
var drag = d3.drag()
  .on("start",start)
  .on("drag",dragged)
  .on("end",end);
  
circle.call(drag);

function start() {
  grid.on("mouseover", function() {
    d3.select(this).attr("fill","yellow");
    console.log(this.id);
  })
  .on("mouseout", function() {
    d3.select(this).attr("fill",color);
  })
  
  d3.select(this)
    .style("pointer-events","none");
}
function dragged() {
  d3.select(this)
    .attr("cx", d3.mouse(this)[0])
    .attr("cy", d3.mouse(this)[1]);
}
function end() {
  grid.on("mouseover",null)
   .on("mouseout", null)
   .transition()
   .attr("fill",color);

  d3.select(this)
    .style("pointer-events","all");
  
}
.as-console-wrapper { max-height: 30px !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>


推荐阅读