【问题标题】:D3- Drawing line on leaflet map through mouse eventsD3-通过鼠标事件在传单地图上画线
【发布时间】:2018-12-10 00:28:14
【问题描述】:

我正在尝试实现this example。但我使用的是 d3 v4 和传单版本 1。在鼠标移动 svg 函数时,我正在设置线条的样式,但它给我一个错误Uncaught TypeError: Cannot read property 'style' of null 我可以形成一个套索,但它全是黑色的,这意味着两个圆圈都不是得到风格也没有线条。我不知道为什么行变量为空?这是我的代码--

svgLayer = L.svg({clickable:true});
   svgLayer.addTo(map)

   // assigning  SVG
   svg = d3.select('#map').select('svg').attr("pointer-events", "auto");
   pointsG = svg.select('g').attr('class', 'leaflet-zoom-hide');

    map.dragging.disable();
    map.touchZoom.disable();
    map.doubleClickZoom.disable();
    map.scrollWheelZoom.disable();

    if (map.tap) map.tap.disable();

     function project(ll) {
       //console.log(ll);
      var point = map.latLngToLayerPoint(ll.LatLng);
      //console.log(point)
      return point;
    }

    d3.queue()
    .defer(d3.csv, 'dots.csv', function(row) {
        return {LatLng: [+row['lat'], +row['lng']]};
    })    
    .await(readyToDraw);

    function readyToDraw(error,data){
     //console.log(data);

     var points = pointsG.selectAll(".points")
                              .data(data);

    var pointsEnter = points.enter().append("circle")
                            .attr("class", "points")
                            .attr("r", 6)
                            .style("fill-opacity", 0.4)
                            .style("fill","black")
                            .attr("pointer-events","visible");

      var lassoPoints = [];
      var lassoClosed = false;
      var dragging = false;



      svg.on("click.lasso", function() {
        if(dragging) return;
        var p = d3.mouse(this);
        //console.log(p)
        var ll = map.containerPointToLatLng(L.point([p[0],p[1]]))
        //console.log(ll)


        if(lassoPoints.length) {
          var fp = project(lassoPoints[0])
         // console.log(lassoPoints[0])
          var dist2 = (fp.x - p[0])*(fp.x - p[0]) + (fp.y - p[1])*(fp.y-p[1])
          if(dist2 < 100) {
            lassoClosed = true;
            renderLasso();
            pointsG.selectAll("line.lasso").remove();
            return;
          }
        }
        if(lassoClosed) {
          /*
          lassoClosed = false;
          g.selectAll(".lasso").remove();
          lassoPoints = [];
          return render();
          */
          return;
        };

        lassoPoints.push(ll);
        updateLayers();
      });

      svg.on("mousemove", function() {
        // we draw a guideline for where the next point would go.
        var lastPoint = lassoPoints[lassoPoints.length-1];
        var p = d3.mouse(this);
        var ll = map.containerPointToLatLng(L.point([p[0],p[1]]));
        //console.log(lastPoint)
        var line = pointsG.selectAll("line.lasso").data([lastPoint])
        //console.log(line)
        line.enter().append("line").classed("lasso", true)
        if(lassoPoints.length && !lassoClosed) {
          //console.log(project(lastPoint))
          line.attr('x1', project(lastPoint).x)
              .attr('y1', project(lastPoint).y)
              .attr('x2', project(ll).x)
              .attr('y2', project(ll).y)
              .style('stroke', "#111")
              .style("stroke-dasharray", "5 5");
        } else {
          line.remove();
        }
      })

  var path = d3.line()
        .x(function(d) {  return project(d).x})
        .y(function(d) { return project(d).y})


      function renderLasso() {
        // render our lasso
        //console.log(lassoPoints)
        var lassoPath = pointsG.selectAll("path.lasso").data([lassoPoints])
        lassoPath.enter().append("path").classed("lasso", true)
        .on("click", function() {
          if(lassoClosed) {
            lassoClosed = false;
            pointsG.selectAll(".lasso").remove();
            lassoPoints = [];
            d3.event.stopPropagation();
            return updateLayers();
          };
        })
        //console.log(lassoPath)
        lassoPath.attr("d", function(d) { 
          var str = path(d)
          if(lassoClosed) str += "Z"
          return str;
        })
        .style('stroke', '#010')
        .style('fill', "#010")
        .style("fill-opacity", 0.1);


        var drag = d3.drag()
        .on("drag", function(d) {
          if(!lassoClosed) return;
          dragging = true;
          var p = d3.mouse(svg.node())
          var ll = map.containerPointToLatLng(L.point([p[0],p[1]]));
          d.lat = ll.lat;
          d.lng = ll.lng;
          renderLasso();

        }).on("end", function() {
          setTimeout(function() {
            dragging = false;
          }, 100)
        })
        //console.log(lassoPoints)
        var lasso = pointsG.selectAll("circle.lasso")
        .data(lassoPoints)
        lasso.enter().append("circle").classed("lasso", true)
        .call(drag);
        //console.log(lasso)
        lasso.attr('cx', function(d) { return project(d).x;})
          .attr('cy', function(d) { return project(d).y;})
          .attr('r',8)
          .style('stroke','#010')
          .style('fill','#b7feb7')
          .style("fill-opacity",0.9);


        var projected = lassoPoints.map(function(d){
          return project(d)
        })

        //console.log(projected)
        pointsG.selectAll(".points").style('fill', function(d) {
          //console.log(d);
            var isInside = inside(project(d), projected);
            //console.log(project(d), isInsid
            //console.log(isInside)
            if(isInside) {
              return "#ff8eec";
            } else {
              return "#0082a3";
            }
          })
      }

 function updateLayers(){
   pointsG.selectAll('.points')
       .attr('cx', function(d){ return map.latLngToLayerPoint(d.LatLng).x})
       .attr('cy', function(d){return map.latLngToLayerPoint(d.LatLng).y})

  renderLasso();

}; 

    map.on('zoomend', updateLayers);
    updateLayers();

        }



function inside(point, vs) {


    var x = point.x, y = point.y;

    var inside = false;
    for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
        var xi = vs[i].x, yi = vs[i].y;
        var xj = vs[j].x, yj = vs[j].y;

        var intersect = ((yi > y) != (yj > y))
            && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
        if (intersect) inside = !inside;
    }

    return inside;
};

【问题讨论】:

    标签: javascript d3.js event-handling leaflet mousemove


    【解决方案1】:

    如果没有错误所在的行,很难给出解释。

    最好把所有样式的东西都放在style 标签中。

    你对点绑定数据的使用不一致

    这里你使用d

        pointsG.selectAll(".points").style({
          fill: function(d) {
            var isInside = inside(project(d), projected);
            //console.log(project(d), isInside)
            if(isInside) {
              return "#ff8eec";
            } else {
              return "#0082a3"
            }
          }
        })
    

    这里你使用d.LatLng

    function updateLayers(){
      pointsG.selectAll('.points')
          .attr('cx', function(d){ return map.latLngToLayerPoint(d.LatLng).x})
          .attr('cy', function(d){ return map.latLngToLayerPoint(d.LatLng).y})
      renderLasso();
    };
    

    【讨论】:

    • 我已经更新了代码。我可以解决那种风格错误。那是因为我写作风格的点和风格。但现在我在投影点方面确实面临错误。当我在line.attr('x1', project(lastPoint).x) 中得到Uncaught TypeError: Cannot read property 'lat' of undefined
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-14
    • 1970-01-01
    • 1970-01-01
    • 2015-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多