简体   繁体   English

d3 circle .on(“ click”)事件未触发

[英]d3 circle .on(“click”) event not firing

I understand it should be as simple as selecting the element you need and applying the call to it, but in my case, nothing is happening when I do so. 我知道它应该很简单,只需选择所需的元素并对其应用调用,但就我而言,这样做没有任何反应。

In my case, I need to re draw circles based on a zoom level of a map. 就我而言,我需要根据地图的缩放级别重新绘制圆圈。

If the zoom level is < a certain number, use dataset A for the circles. 如果缩放级别<一定数值,则将数据集A用于圆圈。 If the zoom level is > the number use dataset B to draw the circles. 如果缩放级别>数字,则使用数据集B绘制圆圈。

I can draw the circles fine, and they do change on changing of the zoom level, but when I add an .on("click") event to these though, nothing happens. 我可以很好地绘制圆圈,并且它们确实会随着缩放级别的改变而改变,但是当我向其中添加.on("click")事件时,什么也没有发生。

Here is a Codepen link showing the lack of click event working CODEPEN LINK 这是一个Codepen链接,显示缺少点击事件,可以正常工作CODEPEN LINK

Here is the code I am using, I have a feeling I am doing something wrong in the update() function, and the way I am using the .remove() function: 这是我正在使用的代码 ,我有一种感觉,我在update()函数中做错了事,以及我使用.remove()函数的方式:

L.mapbox.accessToken = 'pk.eyJ1Ijoic3RlbmluamEiLCJhIjoiSjg5eTMtcyJ9.g_O2emQF6X9RV69ibEsaIw';
var map = L.mapbox.map('map', 'mapbox.streets')
  .setView([53.4072, -2.9821], 14);

var data = {
  "largeRadius": [{
    "coords": [53.3942, -2.9785],
    "name": "Jamaica Street"
  }, {
    "coords": [53.4073, -2.9824],
    "name": "Hood Street"
  }],
  "smallRadius": [{
    "coords": [53.4075, -2.9936],
    "name": "Chapel Street"
  }, {
    "coords": [53.4073, -2.9824],
    "name": "Hood Street"
  }]
};

// Sort data for leaflet LatLng conversion
data.largeRadius.forEach(function(d) {
  d.LatLng = new L.LatLng(d.coords[0], d.coords[1]);
});
data.smallRadius.forEach(function(d) {
  d.LatLng = new L.LatLng(d.coords[0], d.coords[1]);
});

var svg = d3.select(map.getPanes().overlayPane).append("svg");

var g = svg.append("g").attr("class", "leaflet-zoom-hide");

var circles = g.selectAll("circle")
  .data(data.smallRadius)
  .enter().append("circle");

function update() {
  circles.remove();
  translateSVG();

  var dataInstance;
  var radius;

  if (map.getZoom() < 17) {
    dataInstance = data.largeRadius;
    radius = 0.008;
  } else {
    dataInstance = data.smallRadius;
    radius = 0.001;
  }

  dataInstance.forEach(function(d) {
    d.LatLng = new L.LatLng(d.coords[0], d.coords[1]);
  });

  circles = g.selectAll("circle")
    .data(dataInstance)
    .enter().append("circle")
    .attr("id", function(d) {
      return d.name
    })
    .attr("cx", function(d) {
      return map.latLngToLayerPoint(d.LatLng).x
    })
    .attr("cy", function(d) {
      return map.latLngToLayerPoint(d.LatLng).y
    })
    .attr("r", function() {
      return radius * Math.pow(2, map.getZoom())
    });
}

function translateSVG() {
  var width = window.innerWidth;
  var height = window.innerHeight;

  var regExp = /\(([^)]+)\)/;
  var translateString = regExp.exec(document.querySelector(".leaflet-map-pane").attributes[1].nodeValue);
  var translateX = parseInt(translateString[1].split(" ")[0]);
  var translateY = parseInt(translateString[1].split(" ")[1]);

  if (translateX < 0) {
    translateX = Math.abs(translateX);
  } else {
    translateX = -translateX;
  }
  if (translateY < 0) {
    translateY = Math.abs(translateY);
  } else {
    translateY = -translateY;
  }

  svg.attr("width", width);
  svg.attr("height", height);
  svg.attr("viewBox", function() {
    return translateX + " " + translateY + " " + width + " " + height;
  });
  svg.attr("style", function() {
    return "transform: translate3d(" + translateX + "px, " + translateY + "px, 0px);";
  });
}

// THIS IS THE CLICK EVENT THAT DOES NOT WORK
circles.on("click", function () {
  alert("clicked");
})

map.on("moveend", update);
update();

I'm not sure if this fixes your issue completely, mostly because I'm not sure I fully understand what you're trying to achieve, but if you move the 'click' code: 我不确定这是否能完全解决您的问题,主要是因为我不确定我是否完全理解您要实现的目标,但是如果您移动“点击”代码,则:

circles.on("click", function () {
  alert("clicked");
});

Inside your update, then you'll rebind that after you've done the destroy and re-create, so your update function becomes this: 在更新内部,完成销毁并重新创建后,您将对其进行重新绑定,因此更新功能将变为:

function update() {
  circles.remove();
  translateSVG();

  var dataInstance;
  var radius;

  if (map.getZoom() < 17) {
    dataInstance = data.largeRadius;
    radius = 0.008;
  } else {
    dataInstance = data.smallRadius;
    radius = 0.001;
  }

  dataInstance.forEach(function(d) {
    d.LatLng = new L.LatLng(d.coords[0], d.coords[1]);
  });

  circles = g.selectAll("circle")
    .data(dataInstance)
    .enter().append("circle")
    .attr("id", function(d) {
      return d.name
    })
    .attr("cx", function(d) {
      return map.latLngToLayerPoint(d.LatLng).x
    })
    .attr("cy", function(d) {
      return map.latLngToLayerPoint(d.LatLng).y
    })
    .attr("r", function() {
      return radius * Math.pow(2, map.getZoom())
    });

    circles.on("click", function () {
      alert("clicked");
    });
}

and you then remove the circles.on("click") part from the bottom. 然后从底部删除circle.on(“ click”)部分。 It may also be worth making sure you're releasing that bind each time, i'm unsure if it'll be overwriting the memory or adding to it each update. 确保每次都释放绑定也是值得的,我不确定是要覆盖内存还是在每次更新时添加绑定。

Here's a fork of yours where it seems to be working as I imagine it: http://codepen.io/anon/pen/waqJqB?editors=101 这是您的一个分支,似乎可以像我想象的那样工作: http : //codepen.io/anon/pen/waqJqB?editors=101

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM