在同一元素上实现shift单击和单击功能

时间:2018-01-05 17:33:40

标签: javascript d3.js svg

我正在尝试在d3中实现一个on click事件,但我也希望有一个选项来转换单击相同的svg元素以触发不同的功能。如果我点击元素,我希望它叫我clicked()函数,但如果我移动点击元素,我希望它将它的填充样式更改为“steelblue”。我想做的是:

.on("click", function(d){
      if (d3.event.shiftKey) {
          d3.select(this).style("fill", "steelblue");
      }
      clicked(d);
 })

但是我刚从d3得到“未捕获的TypeError:t.getAttribute不是函数”,因为我没有正确调用或传递了clicked()函数。

如果我这样做:

.on("click", clicked);

我的clicked()函数运行正常,但我无法实现shift单击功能。有没有人知道如何使两种功能都有效?我点击的功能本质上是一个缩放功能,顺便接收数据。

1 个答案:

答案 0 :(得分:0)

  

如果我.on("click", clicked);我的clicked()函数运行正常,但我无法实现shift单击功能。

为什么不呢?当然可以。只需检查clicked函数内的转换。

这是一个基本演示:



var circles = d3.select("svg")
  .selectAll(null)
  .data(d3.range(5))
  .enter()
  .append("circle")
  .attr("r", 20)
  .attr("cy", 50)
  .attr("cx", function(d) {
    return 50 + 100 * d
  })
  .style("fill", "darkgray")
  .style("stroke", "black")
  .style("cursor", "pointer")
  .on("click", clicked);

function clicked() {
  if (d3.event.shiftKey) {
    d3.select(this).style("fill", "steelblue");
  }
  console.log("This is the clicked function")
}

<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="100"></svg>
&#13;
&#13;
&#13;

为了完整性,这是您的第一个代码段的问题:当您使用selection.on附加侦听器时,

  

将为元素评估指定的侦听器,传递当前数据(d),当前索引(i)和当前组(节点),并将其作为当前DOM元素(nodes [i])

但是,在您的情况下,您只是将数据传递给clicked函数:

clicked(d);

因此,clicked函数对this的引用不正确,这将是window。请查看以下代码段:

&#13;
&#13;
var circles = d3.select("svg")
  .selectAll(null)
  .data(d3.range(5))
  .enter()
  .append("circle")
  .attr("r", 20)
  .attr("cy", 50)
  .attr("cx", function(d) {
    return 50 + 100 * d
  })
  .style("fill", "darkgray")
  .style("stroke", "black")
  .style("cursor", "pointer")
  .on("click", function(d){
  	clicked(d)
  });

function clicked(datum) {
  console.log("The datum is: " + datum);
  console.log("'this' is: " + this)
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="100"></svg>
&#13;
&#13;
&#13;

一个简单的解决方法是保留对this

的引用

&#13;
&#13;
var circles = d3.select("svg")
  .selectAll(null)
  .data(d3.range(5))
  .enter()
  .append("circle")
  .attr("r", 20)
  .attr("cy", 50)
  .attr("cx", function(d) {
    return 50 + 100 * d
  })
  .style("fill", "darkgray")
  .style("stroke", "black")
  .style("cursor", "pointer")
  .on("click", function(d) {
    var self = this;
    clicked(d, self)
  });

function clicked(datum, thisElement) {
  console.log("The datum is: " + datum);
  console.log("'this' is: " + thisElement)
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="100"></svg>
&#13;
&#13;
&#13;

或使用Function.prototype.call(由@DavidKnipe建议):

&#13;
&#13;
var circles = d3.select("svg")
  .selectAll(null)
  .data(d3.range(5))
  .enter()
  .append("circle")
  .attr("r", 20)
  .attr("cy", 50)
  .attr("cx", function(d) {
    return 50 + 100 * d
  })
  .style("fill", "darkgray")
  .style("stroke", "black")
  .style("cursor", "pointer")
  .on("click", function(d) {
    clicked.call(this, d);
  });

function clicked(datum) {
  console.log("The datum is: " + datum);
  console.log("'this' is: " + this)
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="100"></svg>
&#13;
&#13;
&#13;