画布圆不可点击

时间:2018-08-29 09:04:09

标签: javascript html d3.js

我正在使用d3js库创建一个Map,并在特定位置指向一个圆圈,并尝试在这些圆圈上创建click事件,但是这些圆圈不可点击。 这是代码。

<!DOCTYPE html>
<head>
<title>A D3 Map, points plotted with canvas instead of SVG</title>
<style>

body {
  margin: 0;
}

#container {
  position: relative;
  overflow: hidden;
    z-index: 0;
}


#points{
    width:100%;
    height:100%;
    position:relative;
    z-index:100;
}

.layer{
    position:absolute;
    z-index:-10;
}

.tile {
    pointer-events: none;
    position: absolute;
    width: 256px;
    height: 256px;
}

.info {
  position: absolute;
  bottom: 0px;
  left: 0px;
    padding: 20px;
    background: #000;
    color: #fff;
    width: 100%;
    height: 18px;
    z-index: 1000;
    font-family:Helvetica, Arial, sans-serif;
    font-size:16px;
}   

.credit{
    position:absolute;
  bottom: 0px;
  right: 0px;
    padding: 9px 20px;
    color:#fff;
    font-family:Helvetica, Arial, sans-serif;
    font-size:13px;
    z-index: 1000;
}

.credit a{
    text-decoration:none;
    color:#ddd;
}


</style>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/d3.geo.tile.v0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js"></script>
</head>
<body>
<div id="container">
    <div class="layer"></div>
    <div id="map">
        <canvas>
            <div id="points" ></div>
        </canvas>
    </div>
    <div class="credit"><p>Data &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> Tiles &copy; <a href="http://cartodb.com/attributions">CartoDB</a></p></div>
</div>
  <script type='text/javascript'>

/* global variables and initial canvas space set up*/

var width = window.innerWidth;
var height = window.innerHeight;
var prefix = prefixMatch(["webkit", "ms", "Moz", "O"]);
console.log(width,height)
var dataSet = "";

d3.csv("/../map2/karriereTutor.csv", function(error, dataset) {
  dataSet = dataset;
  createMap(dataset) 
});

var tile = d3.geo.tile()
    .size([width, height]);

var projection = d3.geo.mercator()
.scale((1 << 24) / 2 / Math.PI)
.translate([width / 2, height / 2]); // just temporary

$('.arc').on('click',function(){
  console.log('asdfd')
})

var zoom = d3.behavior.zoom()
.scale(4.5 << 12)
    .scaleExtent([1 << 9, 12 << 23])
    .translate([width / 3  ,3000])
    .on("zoom", zoomed);

var container = d3.select("#container")
        .style("width", width + "px")
        .style("height", height + "px")
        .call(zoom)
        .on("mousemove", mousemoved)

var base = d3.select('#map');

var chart = d3.select('canvas')
            .attr("class", "layer")
      .attr('width', width)
      .attr('height', height);

var context = chart.node().getContext('2d');

var locations = d3.select('#points');


var layer = d3.select('.layer');

var info = base.append("div")
    .attr("class", "info");

zoomed();

function createMap(dataset) {

  var dataBinding = locations.selectAll("points.arc")
    .data(dataset)
    .enter()
    .append("div")
    .classed("arc", true)
    .attr('id',function(d){ return d.city })
    .attr("x", function(d) { return projection([d.y,d.x])[0]})
    .attr("y", function(d) {return projection([d.y,d.x])[1]})
    .attr("radius", 5)
    .attr("fillStyle", "#ff0000")
    drawCanvas();
}

function drawCanvas() {

    var elements = locations.selectAll("div.arc");
    elements.each(function(d) {
        var node = d3.select(this);
        context.beginPath();
        context.arc(node.attr("x"), node.attr("y"), node.attr("radius"), 0, 2 * Math.PI);
        context.fillStyle = node.attr("fillStyle");
        context.fill();        
        context.closePath();
    })
}


function reDraw() {
    context.clearRect(0, 0, width, height);
    drawCanvas();
}

function zoomed() {
  var tiles = tile
      .scale(zoom.scale())
      .translate(zoom.translate())
      ();

  projection
      .scale(zoom.scale() / 2 / Math.PI)
      .translate(zoom.translate());

    d3.selectAll("div.arc")
        .attr("x", function(d) {return projection([d.y,d.x])[0]})
        .attr("y", function(d) {return projection([d.y,d.x])[1]})
        reDraw();

  var image = layer
      .style(prefix + "transform", matrix3d(tiles.scale, tiles.translate))
      .selectAll(".tile")
      .data(tiles, function(d) { return d; })


  image.exit()
      .remove();

 image.enter().append("img")
 .attr("class", "tile")
      .attr("src", function(d) { return "http://" + ["a", "b", "c"][Math.random() * 3 | 0] + ".tile.openstreetmap.org/" + d[2] + "/" + d[0] + "/" + d[1] + ".png"; })
      .style("left", function(d) { return (d[0] << 8) + "px"; })
      .style("top", function(d) { return (d[1] << 8) + "px"; })
}



function mousemoved() {
  // for(var i = 0; i < dataSet.length; i++){
  //   var projectionPoints = projection.invert(d3.mouse(this));
  //   // console.log(dataSet[i].x, projectionPoints[1])
  //   if(Math.round(projectionPoints[1]) == Math.round(dataSet[i].x)){
  //     console.log(dataSet[i].city)
  //   }   
  // }
  info.text(formatLocation(projection.invert(d3.mouse(this)), zoom.scale()));
}

function matrix3d(scale, translate) {
  var k = scale / 256, r = scale % 1 ? Number : Math.round;
  return "matrix3d(" + [k, 0, 0, 0, 0, k, 0, 0, 0, 0, k, 0, r(translate[0] * scale), r(translate[1] * scale), 0, 1 ] + ")";
}

function prefixMatch(p) {
  var i = -1, n = p.length, s = document.body.style;
  while (++i < n) if (p[i] + "Transform" in s) return "-" + p[i].toLowerCase() + "-";
  return "";
}

function formatLocation(p, k) {
  var format = d3.format("." + Math.floor(Math.log(k) / 2 - 2) + "f");
  return (p[1] < 0 ? format(-p[1]) + " S" : format(p[1]) + " N") + " "
       + (p[0] < 0 ? format(-p[0]) + " W" : format(p[0]) + " E");
}

</script>
</body>
</html>

我正在使用d3.js创建地图,这是用于创建这些圆圈位置的csv文件

x,y,name,city
48.0851267,11.198654,karriere tutor,Wörthsee
52.2815691,7.443409099999999,karriere tutor,Rheine
48.2629984,11.4339022,karriere tutor,Dachau
49.7019294,9.2559214,karriere tutor,Miltenberg
47.697371,9.5629717,karriere tutor,Meckenbeuren
48.5667364,13.4319466,karriere tutor,Passau
52.4357364,8.6159777,karriere tutor,Rahden
49.6743636,12.1489337,karriere tutor,Weiden in der Oberpfalz
47.7782704,9.612130299999999,karriere tutor,Ravensburg
48.3705449,10.89779,karriere tutor,Augsburg Bayern
51.9032375,8.385753500000002,karriere tutor,Gütersloh
53.6764136,10.2378854,karriere tutor,Ahrensburg
51.3876468,10.7465696,karriere tutor,Straussberg
49.749992,6.6371433,karriere tutor,Trier
52.52000659999999,13.404954,karriere tutor,Berlin
54.3232927,10.1227651,karriere tutor,Kiel
51.4969802,11.9688029,karriere tutor,Halle (Saale)
51.6659316,8.7276375,karriere tutor,Borchen
52.3472237,14.5505672,karriere tutor,Frankfurt (Oder)
54.0729431,9.9840158,karriere tutor,Neumünster Holstein
53.9317752,9.5051475,karriere tutor,Itzehoe
53.5395845,8.580942499999999,karriere tutor,Bremerhaven
54.19517639999999,9.1019015,karriere tutor,Heide Holstein
51.8368113,10.7844266,karriere tutor,Wernigerode
52.9154545,12.7990783,karriere tutor,Neuruppin
52.21697469999999,13.453792,karriere tutor,Zossen
53.2464214,10.4115179,karriere tutor,Lüneburg
50.8021728,8.7667933,karriere tutor,Marburg
53.8654673,10.6865593,karriere tutor,Lübeck
51.8205718,9.8683087,karriere tutor,Einbeck
50.0522076,8.6952638,karriere tutor,Neu-Isenburg
51.2964148,6.8401844,karriere tutor,Ratingen
51.2041968,6.6879511,karriere tutor,Neuss
50.0294877,8.6949231,karriere tutor,Dreieich
51.3387609,6.5853417,karriere tutor,Krefeld
49.4874592,8.466039499999999,karriere tutor,Mannheim
54.0924406,12.0991466,karriere tutor,Rostock
54.08654629999999,13.3923414,karriere tutor,Greifswald
47.84199820000001,12.9728226,karriere tutor,Freilassing
50.4358385,7.825795299999999,karriere tutor,Montabaur
53.2778837,9.7240138,karriere tutor,Tostedt
49.8028671,8.603536199999999,karriere tutor,Pfungstadt
48.8914741,9.034192899999999,karriere tutor,Hardthof bei Markgröningen
48.6471033,9.4519635,karriere tutor,Kirchheim unter Teck
48.6893963,10.1610948,karriere tutor,Heidenheim an der Brenz
47.6779496,9.173238399999999,karriere tutor,Konstanz
50.5558095,9.6808449,karriere tutor,Fulda
53.6355022,11.4012499,karriere tutor,Schwerin Mecklenburg
51.3127114,9.4797461,karriere tutor,Kassel Hessen
50.0782184,8.239760799999999,karriere tutor,Wiesbaden
48.4010822,9.987607599999999,karriere tutor,Ulm Donau
48.5950369,8.8671577,karriere tutor,Herrenberg
50.1109221,8.6821267,karriere tutor,Frankfurt am Main
52.3758916,9.732010400000002,karriere tutor,Hannover
48.1351253,11.5819805,karriere tutor,München
51.3396955,12.3730747,karriere tutor,Leipzig
50.937531,6.9602786,karriere tutor,Köln
51.5135872,7.465298100000001,karriere tutor,Dortmund
51.4556432,7.0115552,karriere tutor,Essen Ruhr
53.07929619999999,8.8016936,karriere tutor,Bremen
53.5510846,9.9936819,karriere tutor,Hamburg
50.14720579999999,8.824969099999999,karriere tutor,Maintal
48.8940624,9.195464,karriere tutor,Ludwigsburg Württemberg
49.9456399,11.5713346,karriere tutor,Bayreuth
52.2688736,10.5267696,karriere tutor,Braunschweig
50.2612094,10.962695,karriere tutor,Coburg
50.3569429,7.5889959,karriere tutor,Koblenz am Rhein
47.9837999,10.1801883,karriere tutor,Memmingen
51.3670777,7.4632841,karriere tutor,Hagen Westfalen
51.1652199,7.0671161,karriere tutor,Solingen
53.1434501,8.214552099999999,karriere tutor,Oldenburg (Oldb)
51.1804572,6.4428041,karriere tutor,Mönchengladbach
51.4185682,6.884522599999999,karriere tutor,Mülheim an der Ruhr
49.0134297,12.1016236,karriere tutor,Regensburg
49.47741,8.445179999999999,karriere tutor,Ludwigshafen am Rhein
49.4771169,10.988667,karriere tutor,Fürth Bayern
51.0504088,13.7372621,karriere tutor,Dresden
50.8216502,6.1320672,karriere tutor,Würselen
51.2562128,7.150763599999999,karriere tutor,Wuppertal
50.73743,7.0982068,karriere tutor,Bonn
48.7781001,8.0875217,karriere tutor,Karlsruhe Baden
48.7758459,9.1829321,karriere tutor,Stuttgart
51.2277411,6.7734556,karriere tutor,Düsseldorf
48.1916623,11.6460441,karriere tutor,Unterföhring
50.22683079999999,8.6181618,karriere tutor,Bad Homburg vor der Höhe
50.09563620000001,8.776084299999999,karriere tutor,Offenbach am Main
50.17874,8.47191,karriere tutor,Königstein im Taunus
49.3063689,8.6427693,karriere tutor,Walldorf Baden
50.98476789999999,11.02988,karriere tutor,Erfurt
49.24015720000001,6.996932699999999,karriere tutor,Saarbrücken
52.3905689,13.0644729,karriere tutor,Potsdam
49.4521018,11.0766654,karriere tutor,Nürnberg Mittelfranken
51.9606649,7.6261347,karriere tutor,Münster Westfalen
49.9928617,8.2472526,karriere tutor,Mainz am Rhein
52.1205333,11.6276237,karriere tutor,Magdeburg
47.9990077,7.842104299999999,karriere tutor,Freiburg im Breisgau
50.1467469,8.561455500000001,karriere tutor,Eschborn Taunus
49.8728253,8.6511929,karriere tutor,Darmstadt
48.6813312,9.0088299,karriere tutor,Böblingen
52.0302285,8.532470800000002,karriere tutor,Bielefeld
52.844198,8.053015799999999,karriere tutor,Cloppenburg
53.7513549,9.6632521,karriere tutor,Elmshorn
48.5788725,7.8160821,karriere tutor,Kehl Rhein

1 个答案:

答案 0 :(得分:0)

您已经通过使用DOM节点(在本例中为未渲染)使用画布实现了进入/更新/退出循环,但是这些DOM节点根本不与画布进行交互-画布是像素的无状态集合。结果,任何与画布的鼠标交互只能与画布整体交互-像素不能具有自己的鼠标单击事件。

幸运的是,有许多方法可用于在画布上跟踪鼠标并将其与绘制的形状相关。

开箱即用的最简单方法可能是使用d3.forceSimulation而不进行任何实际模拟。它带有一个方便的方法,该方法使用四叉树来查找最接近鼠标动作的节点(它也允许人们指定搜索半径)。这具有快速编码和快速执行的优点,而无需尝试学习四叉树。 如果您的形状不是圆形,则可能不理想

force.find(x,y,r)`仅在d3v4及更高版本中可用,但似乎您同时使用d3v3和d3v4,因此d3.forceSimulation在此示例中无需修改即可工作 < / p>

下面是一个示例,该示例跟踪在画布上哪个城市最接近鼠标:

首先,我们设置节点:

var simulation = d3.forceSimulation().nodes(dataset);

然后我们找到鼠标位置并找到最近的节点:

 var xy = d3.mouse(this);               // get xy position of mouse
 var longlat = projection.invert(xy);   // convert it to a lat long
 var nearest = simulation.find(longlat[1],longlat[0]); // see what point is closest.

一些注意事项:

  • 您已在csv中将经度标记为y,在纬度上标记为x,这与常规惯例相反,但是为了避免在代码的其他地方进行更改,我将其保留。这就是为什么near.find()在此处使用纬度,经度(y,x)的原因。
  • 强制布局使用xy属性跟踪节点位置,这就是为什么我没有指定任何访问器函数的原因,因为您的数据集中已经具有x,y属性
  • 当我在find函数中比较纬度和经度时,我在比较哪个圆是通过角距离而不是投影距离更接近鼠标的,这可以通过我赢得的一些工作来避免这里不谈,因为这是一个单独的问题,在这种情况下,还使用了多个坐标系:缩放,画布,地理和图块

上面的四到五行代码,对鼠标悬停功能进行了少许修改,以显示距离鼠标最近的城市看起来像this

我尚未指定搜索半径,但是请记住,由于模拟是使用地理坐标(d.xd.y)进行操作,因此以度为单位。