Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

d3-tip offset on svgs within Leaflet, Firefox only, not working

I'm using the d3-tip plugin to show tooltips for countries. The countries are an svg layer that sits on top of the Leaflet base layer. I want the tooltips to be centered within each state. What I currently have works great for all browsers except Firefox. Firefox is just way off. I've tried to adjust for Firefox, but it gets thrown off depending on the size of the browser window.

Any thoughts on how I can fix this?

Here is a Plunker: https://plnkr.co/edit/1FLMkbMSZmF59dxloIlY?p=preview

Screenshot of what it looks like in Firefox when hovering over Texas: screenshot

Code:

<!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <script src="http://d3js.org/d3.v3.min.js"></script>
        <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5/leaflet.css" />
            <!--[if lte IE 8]>
            <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5/leaflet.ie.css" />
            <![endif]-->
        <script src="http://cdn.leafletjs.com/leaflet-0.5/leaflet-src.js"></script>
        <script src="d3.tip.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
        <style>
            body{
              margin: 0px;
              font-family:Arial, sans-serif;
            }
            /* geojson components */
            #map {
              width: 100%;
              height: 100%;
              position:absolute;
              top:0;
              left:0;
              z-index:0;
            }
            path.states { fill: #ff3300; fill-opacity: .65; stroke: #fff; stroke-width: 3px;}
            path.states:hover {
              fill-opacity: 1;
            }
            /* Leaflet */
            .leaflet-container {
              background: #ccc !important;
            }
            .leaflet-right {
              right: 10px !important;
            }
            .leaflet-top {
              top: 10px !important;
            }
            /* D3 tips for states*/
            .d3-tip-state {
              line-height:130%;
              font-weight: normal;
              font-family: Helvetica, Arial, sans-serif;
              font-size:13px;
              padding: 12px;
              background: rgba(205, 72, 122, 0.9);
              color: #fff;
              border-radius: 5px;
              position:relative;
              z-index:101;
            }
            /* Firefox styles */
            @-moz-document url-prefix() {
              .d3-tip-state {
                margin-left:-100px;
              }
            }
        </style>
      </head>
    <body>
    <div id="map"></div>

    <script>
    //tiles
    var map = new L.Map("map", {zoomControl: true, center: [29, -92], zoom: 6})
       .addLayer(new L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/Ocean_Basemap/MapServer/tile/{z}/{y}/{x}', {
         attribution: 'Tiles &copy; Esri &mdash; Sources: GEBCO, NOAA, CHS, OSU, UNH, CSUMB, National Geographic, DeLorme, NAVTEQ, and Esri',
         maxZoom: 13
       }));

    /* Initialize the SVG layer */
    map._initPathRoot();

    var svg = d3.select("#map").select("svg"),
        g = svg.append("g");

    /* Define the d3 projection */
    var path = d3.geo.path().projection(function project(x) {
        var point = map.latLngToLayerPoint(new L.LatLng(x[1], x[0]));
        return [point.x, point.y];
      });

      var firefox = /Firefox/i.test(navigator.userAgent);

      var statetip = d3.tip()
      .attr('class', 'd3-tip-state')
      .offset(function(){
        if (firefox) {
          return [(this.getBBox().height / 6) - 200, -800]
        }else{
          return [this.getBBox().height / 2, 0]
        }
      })
      .html(function(d,i) {
          return d.properties.name;
      });

      g.call(statetip);

      // Add states
      d3.json("states.json", function(states) {

      var states =  g.selectAll("path")
            .data(states.features)
            .enter()
            .append("path")
            .attr("class", function(d){ return "states " + d.properties.postal;})
            .attr("d", path)
            .on('mouseover', statetip.show)
            .on('mouseout', statetip.hide);

        map.on("viewreset", function reset() {
          states.attr("d",path)
        })
      });
    </script>
    </body>
    </html>
like image 403
sprucegoose Avatar asked Apr 11 '16 18:04

sprucegoose


1 Answers

Analyzed the code and modified for the expected output. Check this plunker:

Click here to view plunker page

We have achieved through Leaflet marker with Popup without d3.tip

**OnMouseOver**: I get necessary info like latitude & longitude,   
tooltip   text from data point and placed Leaflet marker with empty 
icon, then bind popup and opened it

**OnMouseOut**: I have removed Leaflet marker layer from Map.

Please check the link, code and let me know your feedback.

like image 166
Mayil Avatar answered Oct 21 '22 17:10

Mayil