如何使D3js对象改变它的属性,鼠标移动到对象附近

How to make D3js object changing it's properties on mouse move near the object?

本文关键字:对象 移动 鼠标 D3js 何使 改变 属性      更新时间:2023-09-26

这个想法是让一个对象对其附近的鼠标移动做出反应。

这就是我现在所做的:

//declaring a canvas
var canvas = d3.select("body")
               .append("svg")
               .attr("width", 100)
               .attr("height", 100);
//create circle with attributes and listeners         
var circles = canvas.selectAll("circle")
                    .data([1])
                    .enter()
                    .append("circle")
  .attr("cy", 50).attr("cx", 50).attr("r", 20)
  .style({"fill": "grey"})      
  .on("mousemove", handleMouseMove);
//listener on mouse move inside the canvas
function handleMouseMove(){
    var coordinates = [0, 0];
      coordinates = d3.mouse(this);
      var x = coordinates[0];
      var y = coordinates[1];
      console.log(x,y);
      console.log(this.attributes);
}

参见codepen

的示例

我可以得到的对象与它的属性只有当悬停在它-看到最后的console.log();。我被它困住了。

也许最干净的方法是,如果可以的话,在你现有的圆圈下面放一个半径更大的圆圈,填充为transparent:

var g = canvas.selectAll("g")
    .data([1])
    .enter()
    .append("g")
    .on("mouseover", handleMouseOver) // event handlers here are applied
    .on("mouseout", handleMouseOut)   // to both 'circle'
g.append('circle').classed('invisible', true) // this goes before the
    .attr("cy", 50)                           // visible circle
    .attr("cx", 50)
    .attr("r", 40)
    .style({"fill": "transparent"});
g.append('circle').classed('visible', true)
    .attr("cy", 50)
    .attr("cx", 50)
    .attr("r", 20)
    .style({"fill": "grey"});
    function handleMouseOver(d,i){
        d3.select(this).select('.visible').transition()
            .style({"fill": "red"});            
    };
    function handleMouseOut(d,i){
        d3.select(this).select('.visible').transition()
            .style({"fill": "green"});          
    };

或者如果你想使用鼠标位置:

var circles = canvas.selectAll("circle")
    .data([1])
    .enter()
    .append("circle")
        .attr("cy", 50)
        .attr("cx", 50)
        .attr("r", 20)
        .style({"fill": "grey"})        
        .on("mousemove", handleMouseMove);
function handleMouseMove(){
    var coordinates = [];
    coordinates = d3.mouse(this);
    var x = coordinates[0];
    var y = coordinates[1];
    if (x>10 && x<90 && y>10 && y<90) {     // example values; this is a rectangle but you can use more complex shapes
         d3.select('.visible').style({"fill": "red"});
    }
    else {
        d3.select('.visible').style({"fill": "green"});
    }

在这里你可以看到两个版本。

如果你想检测鼠标在圆圈附近,你需要在包含圆圈的对象上设置事件处理程序,在这种情况下,svg包含在canvas变量中。然后,为了确定鼠标是否靠近,我将使用点距离公式。

function handleMouseMove(){
  var coordinates = d3.mouse(this),
          x = coordinates[0],
          y = coordinates[1];
  var dist = Math.sqrt(Math.pow(circPos.x - x, 2) + Math.pow(circPos.y - y, 2));
  console.log("distance to circle center is " + dist);
}

更新注释

var canvas = d3.select("body")
  .append("svg")
  .attr("width", 500)
  .attr("height", 500)
  .on("mousemove", handleMouseMove);
var data = [];
for (var i = 0; i < 10; i++) {
  data.push({
    x: Math.random() * 500,
    y: Math.random() * 500
  });
}
var circles = canvas.selectAll("circle")
  .data(data)
  .enter()
  .append("circle")
  .attr("cy", function(d) {
    return d.y;
  })
  .attr("cx", function(d) {
    return d.x;
  })
  .attr("r", 10)
  .style({
    "fill": "grey"
  });
function handleMouseMove() {
  var coordinates = d3.mouse(this),
    x = coordinates[0],
    y = coordinates[1];
  circles.style("fill", "grey");
  var closestCircle = {
    obj: null,
    dist: 1e100
  };
  circles.each(function(d) {
    var dist = Math.sqrt(Math.pow(d.x - x, 2) + Math.pow(d.y - y, 2));
    if (dist < closestCircle.dist) {
      closestCircle = {
        obj: this,
        dist: dist
      };
    }
  });
  d3.select(closestCircle.obj).style("fill", "green");
}
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>

<

Voroni例子/strong>

var canvas = d3.select("body")
  .append("svg")
  .attr("width", 500)
  .attr("height", 500);
var data = [];
for (var i = 0; i < 10; i++) {
  data.push({
    x: Math.random() * 500,
    y: Math.random() * 500,
    id: i
  });
}
var circles = canvas.selectAll("circle")
  .data(data)
  .enter()
  .append("circle")
  .attr("cy", function(d) {
    return d.y;
  })
  .attr("cx", function(d) {
    return d.x;
  })
  .attr("id", function(d) {
    return "circle" + d.id;
  })
  .attr("r", 10)
  .style("fill", "grey");
var voronoi = d3.voronoi()
  .extent([
    [-1, -1],
    [500 + 1, 500 + 1]
  ])
  .x(function(d) {
    return d.x;
  })
  .y(function(d) {
    return d.y;
  })
var voronoiGroup = canvas.append("g")
  .attr("class", "voronoi");
voronoiGroup.selectAll("path")
  .data(voronoi.polygons(data))
  .enter().append("path")
  .attr("d", function(d) {
    return d ? "M" + d.join("L") + "Z" : null;
  })
  .style("pointer-events", "all")
  .style("fill", "none")
  .style("stroke", "steelblue")
  .style("opacity", "0.5")
  .on("mouseover", mouseover);
function mouseover(d) {
  circles.style("fill", "grey");
  d3.select("#circle" + d.data.id).style("fill", "green");
}
<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>