2017-04-24 8 views
2

私は(このFiddleに基づいて)別のdiv内の1つのdiv要素とD3-折りたたみ可能なツリーの基本的なリーフレット地図を持っています。 enter image description hereD3ツリーやリーフレット地図意図しないIntereference

地図(右divが)にGeoJSONをロードD3ツリー(左のdiv)は、対応する階層JSonデータをロードします。ツリー内のノードを展開すると、マップ要素も移動します(赤い矢印を参照)。

すべてのクラス名、変数、IDの名前を変更しようとしましたが、問題は解決しません。 Hereは、データが&コードのcodepenです。ノード/機能のグループ化されたSVG要素(1つには<g>?)を使用してリーフレットとD3の両方と関係があると思います。 を使用してツリーを調整しました。

私の問題に特定の解決策を提示できない場合は、お互いに隣り合わせにD3とリーフレットを使用する方法を示すリファレンスまたは例もあります。

[編集]問題解決:

私はすべての<g>を保持しているロブSchmueckerのブロック7880033必要な木SVG(svgTree)の両方とコンテナSVG(svgGroup)から組み込むことを試みたパン機能要素。最後に、centerNode機能がsvgTree.select("g").transition()(とないd3.select("g")またはsvgGroup.select("g"))ここで

が更新されたコードで呼び出す必要があります。リーフレットマップのコードは本体にあります

<body> 
    <div id="map"></div> 
    <div id="d3tree"></div> 
    <!--Leaflet Map JS--> 
    <script> 
     var CartoDB_Positron = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', { 
      attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> &copy; <a href="http://cartodb.com/attributions">CartoDB</a>', 
      subdomains: 'abcd', 
      maxZoom: 19 
     }); 


     var map = new L.Map("map", { 
       center: [37.8, -96.9], 
       zoom: 4 
      }) 
      .addLayer(CartoDB_Positron); 

     var legend = L.control({position: 'topright'}); 
     legend.onAdd = function (map) { 
     var div = L.DomUtil.create('div', 'info legend'); 
     div.innerHTML = '<select><option>root</option><option>1</option><option>2</option></select>'; 
     div.firstChild.onmousedown = div.firstChild.ondblclick = L.DomEvent.stopPropagation; 
     return div; 
     }; 
     legend.addTo(map); 

     //set empty geojson feature layer with pre-defined layout & oneachfeature function handlers 
     var geojsonLayer = L.geoJSON(false, { 
      style: function(feature) { 
       return { 
        stroke: true, 
        weight: 1, 
        color: '#4682B4', 
        weight: 2, 
        fillOpacity: 0.6 
       }; 
      }, 
      onEachFeature: onEachFeature 
     }).addTo(map); 


     // add GeoJSON layer to the map once the file is loaded 
     geojsonLayer.addData(data); 
     map.fitBounds(geojsonLayer.getBounds()); 


     //OnClick function for features 
     function onEachFeature(feature, layer) { 
      popupOptions = { 
       maxWidth: 200 
      }; 
      layer.bindPopup("<b>Cluster HFID:</b> " + feature.properties.H_FID + 
       "<br><b>Reference Tag: goldengatebridge</b>" + 
       "<br><br>This photo cluster consists of " + feature.properties.PCount+ " photos from " + feature.properties.UCount + " Flickr users.", popupOptions); 
      //Auto zoom to feature 
      layer.on({ 
       click: zoomToFeature 
      }); 
     } 
     //Zoom to feature function 
     function zoomToFeature(e) { 
      map.fitBounds(e.target.getBounds()); 
     } 

     //Change GeoJSON based on click/selection event 
     function clean_map() { 
      map.eachLayer(function (layer) { 
       if (layer instanceof L.GeoJSON) 
       { 
        map.removeLayer(layer); 

       } 
       //console.log(layer); 
      }); 
     } 
    </script> 
</body> 

D3-ツリーのコードをヘッダーにロードされます。

//Script initialized on load to fit to browser size (root center) 
    //TODO: add root center update function upon window resize 
    //D3 Tree JS 
    //zoom/pan to node http://bl.ocks.org/robschmuecker/7880033 

    window.onload = function() { 
     var margin = { 
      top: 20, 
      right: 120, 
      bottom: 20, 
      left: 120 
     }, 
      width = document.getElementById("d3tree").offsetWidth, 
      height = document.getElementById("d3tree").offsetHeight; 

     // size of the diagram 
     var viewerWidth = width 
     var viewerHeight = height 


     var i = 0, 
      duration = 750, 
      nodeRectW = 60, 
      nodeRectH = 30; 

     //Set Fixed Node Size 
     var tree = d3.layout.tree().nodeSize([nodeRectW + 10, nodeRectH + 10]); 
     var diagonal = d3.svg.diagonal() 
      .projection(function (d) { 
       return [d.x + nodeRectW/2, d.y + nodeRectH/2]; 
      }); 

     // Define the redraw function for the whole (zoomable) tree 
     function redraw() { 
      svgGroup.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); 
     } 

     // define the zoomListener which calls the zoom function on the "zoom" event constrained within the scaleExtents 
     // this updates the center of the tree, needed for auto panning 
     var zoomListener = d3.behavior.zoom().scaleExtent([0.1, 3]).on("zoom", redraw); 

     // Append a group which holds all nodes and which the zoomListener can act upon 
     var svgTree = d3.select("#d3tree").append("svg") 
      .attr("width", viewerWidth) 
      .attr("height", viewerHeight) 
      .call(zoomListener); 

     // Add tooltip div 
     var tooltipDiv = d3.select("body").append("div") 
      .attr("class", "tooltip") 
      .style("opacity", 1e-6); 

     //Set position of treeRoot 
     //root = treeData; -->not necessary because of var treeRoot in subfile 
     treeRoot.x0 = 0; 
     treeRoot.y0 = height/2; 

     //Collapse function 
     function collapse(d) { 
      if (d.children) { 
       d._children = d.children; 
       d._children.forEach(collapse); 
       d.children = null; 
      } 
     } 

     // Append a group which holds all nodes and which the zoom Listener can act upon. 
     var svgGroup = svgTree.append("g"); 

     // Collapse all nodes upon start 
     treeRoot.children.forEach(collapse); 
     update_tree(treeRoot); 
     centerNode(treeRoot); 

     //Update tree on event 
     function update_tree(source) {    
      // Compute the new tree layout. 
      var nodes = tree.nodes(treeRoot).reverse(), 
       links = tree.links(nodes); 

      // Normalize for fixed-depth (depth = vertival distance of nodes) 
      nodes.forEach(function (d) { 
       d.y = d.depth * 110; 
      }); 

      // Update the nodes 
      var node = svgGroup.selectAll("g.node") 
       .data(nodes, function (d) { 
        return d.id || (d.id = ++i); 
       }); 

      // Enter any new nodes at the parent's previous position. 
      var nodeEnter = node.enter().append("g") 
       .attr("class", "node") 
       .attr("transform", function (d) { 
        return "translate(" + source.x0 + "," + source.y0 + ")"; 
       }) 
       .on("click", click_tree) 
       .on("mouseover", function (d) { 
        var g = d3.select(this) // The node 
        // The class is used to remove the additional text later 
        var info = g.append('text') 
         .classed('info', true) 
         .attr('x', 20) 
         .attr('y', -20) 
         .text(function (d) { 
          return d.id; //Feature ID 
         });       
       }) 
       .on("mouseout", function() { 
        // Remove the info text on mouse out. 
        tooltipDiv.transition() 
         .duration(300) 
         .style("opacity", 1e-6) 
        d3.select(this).select('text.info').remove(); 
       }); 

      nodeEnter.append("rect") 
       .attr("width", nodeRectW) 
       .attr("height", nodeRectH) 
       .attr("stroke", "black") 
       .attr("stroke-width", 0.25) 
       .style("fill", function (d) { 
        return d._children ? "lightsteelblue" : "#fff"; 
       }); 

      nodeEnter.append("text") 
       .attr("x", nodeRectW/2) 
       .attr("y", nodeRectH/2) 
       .attr("dy", ".35em") 
       .attr("text-anchor", "middle") 
       .text(function (d) { 
        return d.name; 
       }); 

      // Transition nodes to their new position. 
      var nodeUpdate = node.transition() 
       .duration(duration) 
       .attr("transform", function (d) { 
        return "translate(" + d.x + "," + d.y + ")"; 
       }); 

      nodeUpdate.select("rect") 
       .attr("width", nodeRectW) 
       .attr("height", nodeRectH) 
       .attr("stroke", "black") 
       .attr("stroke-width", 0.25) 
       .style("fill", function (d) { 
        return d._children ? "lightsteelblue" : "#fff"; 
       }); 

      nodeUpdate.select("text") 
       .style("fill-opacity", 1); 

      // Transition exiting nodes to the parent's new position. 
      var nodeExit = node.exit().transition() 
       .duration(duration) 
       .attr("transform", function (d) { 
        return "translate(" + source.x + "," + source.y + ")"; 
       }) 
       .remove(); 

      nodeExit.select("rect") 
       .attr("width", nodeRectW) 
       .attr("height", nodeRectH) 
       .attr("stroke", "black") 
       .attr("stroke-width", 1); 

      nodeExit.select("text"); 

      // Update the links 
      var link = svgGroup.selectAll("path.link") 
       .data(links, function (d) { 
        return d.target.id; 
       }); 

      // Enter any new links at the parent's previous position. 
      link.enter().insert("path", "g") 
       .attr("class", "link") 
       .attr("x", nodeRectW/2) 
       .attr("y", nodeRectH/2) 
       .attr("d", function (d) { 
        var o = { 
         x: source.x0, 
         y: source.y0 
        }; 
        return diagonal({ 
         source: o, 
         target: o 
        }); 
       }); 

      // Transition links to their new position. 
      link.transition() 
       .duration(duration) 
       .attr("d", diagonal); 

      // Transition exiting nodes to the parent's new position. 
      link.exit().transition() 
       .duration(duration) 
       .attr("d", function (d) { 
        var o = { 
         x: source.x, 
         y: source.y 
        }; 
        return diagonal({ 
         source: o, 
         target: o 
        }); 
       }) 
       .remove(); 

      // Stash the old positions for transition. 
      nodes.forEach(function (d) { 
       d.x0 = d.x; 
       d.y0 = d.y; 
      }); 
     } 

     // Toggle children on click. 
     function click_tree(d) { 
      if (d.children) { 
       d._children = d.children; 
       d.children = null; 
      } else { 
       d.children = d._children; 
       d._children = null; 
      } 

      update_tree(d); 
      centerNode(d); //PanToNode 
     } 

     // Function to center node when clicked so node doesn't get lost when collapsing/moving with large amount of children. 
     function centerNode(source) { 
      //find the current zoom level by calling: 
      scale = zoomListener.scale(); 
      x = -source.x0; 
      y = -source.y0; 
      x = x * scale + width/2; 
      y = y * scale + height/2; 
      svgTree.select("g").transition() 
       .duration(duration) 
       .attr("transform", "translate(" + x + "," + y + ")scale(" + scale + ")"); 
      zoomListener.scale(scale); 
      zoomListener.translate([x, y]); 
     } 
    } 

答えて

3

をごcenterNode機能では、代わりに:

d3.select('g').transition() 

次のようになります。

svgTree.select('g').transition() 

ここにあなたの更新されたCodePenがあります:http://codepen.io/anon/pen/NjRdGB?editors=0010

+0

うわー、素晴らしい - 私はこれを見つけませんでした。ちょうど理解しようとしています:d3.select( 'g')は、リーフレットSVGを含む「すべてのSVG 要素を選択」を意味しますか? – Alex

+1

主な違いはこれです: 'svgTree.select'は' svgTree'選択内の要素だけを選択します。一方、 'd3.select'は* anywhere *の要素を選択します。 –

+1

Gerardoさん、ありがとうございました。上のコードにはまだいくつかのバグがありますが、それはまったく異なるものです。あなたの答えは大きな助けになった! – Alex

関連する問題