如何让D3js对象改变它在对象附近移动鼠标的属性?

时间:2016-11-10 18:16:02

标签: javascript d3.js

这个想法是让一个物体对物体附近的鼠标移动作出反应。

到目前为止,我已经走了多远:

//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);
}

See example on codepen

只有将鼠标悬停在对象上时,我才能获得该对象的属性 - 请参阅上一页console.log();。我被困在上面。如果有的话,请分享您对解决方案的想法。

2 个答案:

答案 0 :(得分:2)

如果要检测鼠标是否在圆圈附近,则需要在包含圆圈的对象上设置事件处理程序,在这种情况下,sleep 1变量中包含svg。然后,为了确定鼠标是否接近,我使用点distance formula

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");
}

Voroni示例

<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
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");
}

答案 1 :(得分:2)

如果可以的话,也许最干净的方法是在现有的圆圈下方放置另一个半径更大的圆圈,填充透明:

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"});
    }

以下是FIDDLE,您可以看到这两个版本 希望它有所帮助...