首页 文章

D3-通过鼠标事件在小册子 Map 上绘制线条

提问于
浏览
1

我正在尝试实施this example . 但是我正在使用d3 v4和宣传单版本1.在鼠标上移动svg函数,我正在设置线条,但它会抛出一个错误 Uncaught TypeError: Cannot read property 'style' of null 我可以形成一个套索,但它全是黑色,这意味着没有圈子得到样式也不是线条 . 我不知道为什么行变量为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;
};

1 回答

  • 0

    没有错误的行,很难给出解释 .

    最好将所有样式的东西放在 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();
    };
    

相关问题