0

I am using d3.js to render a heatmap of census block population on top of a leaflet map. I would like to display information about the census block in a fixed div to the right of the map when the mouse hovers over the block. No matter what I do, the information appears below the map instead of to the right of the map. I am new to d3, and I am trying to modify code relating to a number of tooltip examples I have found.

All of my code is below (sorry); however, the most relevant potions, I think, are the css for div.info and the .on("mouseover" . . .) parts in the reset() function. Any suggestions would be greatly appreciated.

<html>  
<head>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css" />
</head>
<style>
svg {
  position: relative;
}

div.tooltip {   
  /*position: absolute; (to make the tooltip follow mouse in map, uncomment this line)*/ 
  text-align: center;           
  width: 150px;                  
  height: 25px;                 
  padding: 2px;             
  font-size: 10px;     
  background: #FFFFE0;
  border: 1px;      
  border-radius: 8px;           
  pointer-events: none;         
}        


div.info {
  padding: 6px 8px;
  font: 14px/16px Arial, Helvetica, sans-serif;
  background: white;
  background: rgba(255,255,255,0.8);
  box-shadow: 0 0 15px rgba(0,0,0,0.2);
  border-radius: 5px;
}
</style>

<h1>This file presents a map of MidTown area in Tallahassee, Florida.</h1>

<body>
    <div id="map" style="width: 900px; height: 600px"></div>
<script type="text/javascript" src="./d3.v3.js" charset="utf-8"></script>
<!--<script src="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js"></script>-->
<script type="text/javascript" src="./leaflet.js"></script>
<script>
var map;
var ajaxRequest;
var plotlist;
var plotlayers=[];

var div = d3.select("body").append("div")   
  //.attr("class", "tooltip")
  .attr("class", "info")
  .style("opacity", 0);

function initmap() {
    // set up the map
    map = new L.Map('map');

    // create the tile layer with correct attribution  15/30.4606/-84.2973
    //var osmUrl='http://www.openstreetmap.org/#map=13/30.4467/-84.3087';
//var osmUrl='http://osm.org/go/ZGUQ8RJ';
var osmUrl='http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
var osmAttrib='Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors';
var osm = new L.TileLayer(osmUrl, {minZoom: 8, maxZoom: 18, attribution: osmAttrib});       

// start the map in Tallahassee Florida
map.setView(new L.LatLng(30.4606,-84.2780),15);
//map.setView(new L.LatLng(51.3, 0.7),9);
map.addLayer(osm);
 }
 initmap();


var svg = d3.select(map.getPanes().overlayPane).append("svg"),
g = svg.append("g").attr("class", "leaflet-zoom-hide");


d3.json("./flare5.json", function(json) {

    var color = d3.scale.quantile()
        .domain([0,11,51,101,251,501,901,1201,1500])
        //.range(["#fff7ec","#fee8c8","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#b30000","#7f0000"]);  //red scale
        //.range(["#f7fcfd","#e5f5f9","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#006d2c","#00441b"]);  //green scale
        .range(["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"]);  //blue scale

    //var group = canvas.selectAll("g")
    //  .data(json.features)
    //  .enter()
    //  .append("g")

    var projection = d3.geo.mercator()
        .center([-84.49,30.44])
        .translate([1000/2,800/2])
        .scale([75000]);



    var transform = d3.geo.transform({point: projectPoint}),
        path = d3.geo.path().projection(transform);


    var feature = g.selectAll("path")
        .data(json.features)
        .enter().append("path");


    map.on("viewreset", reset);
    reset();



    // Reposition the SVG to cover the features.
    function reset() {
        var bounds = path.bounds(json),
            topLeft = bounds[0],
            bottomRight = bounds[1];

        svg .attr("width", bottomRight[0] - topLeft[0])
            .attr("height", bottomRight[1] - topLeft[1])
            .style("left", topLeft[0] + "px")
            .style("top", topLeft[1] + "px");

        g.attr("transform", "translate(" + -topLeft[0] + "," + -topLeft[1] + ")");

        //feature.attr("d", path)
        var areas = feature.attr("d", path)
        .attr("class","area")
        //.attr("fill","steelblue");
        .attr("fill", function(d){
            var value = d.properties.population;
            return color(value);
            })
        .attr("fill-opacity", .5)

        //Adding mouseevents
        .on("mouseover", function(d) {
            d3.select(this).transition().duration(300).style("opacity", .5);
            div.transition().duration(300)
            .style("opacity", 1)
            div.text(d.id + " : Pop.:" + d.properties.population +"; Med. Age:" + d.properties.median_age);
            //.style("left", (d3.event.pageX) + "px")
            //.style("top", (d3.event.pageY -30) + "px");
        })
        .on("mouseout", function() {
            d3.select(this)
            .transition().duration(300)
            .style("opacity", 0.8);
            div.transition().duration(300)
            .style("opacity", 0);
        })
        }

         // Use Leaflet to implement a D3 geometric transformation.
    function projectPoint(x, y) {
        var point = map.latLngToLayerPoint(new L.LatLng(y, x));
        this.stream.point(point.x, point.y);
    }
});




</script>
</body>
</html>
ELamar
  • 114
  • 11
  • Are you saying that the content appears in the wrong `div` or the `div` is in the wrong position? – Lars Kotthoff Apr 06 '14 at 15:00
  • `div.info` will by default be the full width of it's parent ("body") container. In most browsers, so will the SVG. If you want them side-by-side you'll need to constrain the width so that the two together (plus margins and padding) are not more than the width of the page body. Alternately, you could give the SVG a `float` property (and a fixed width less than 100%), and the div text would wrap around it. – AmeliaBR Apr 06 '14 at 15:18
  • Thanks, @LarsKotthoff AmeliaBR. My issue is that the div appears in the wrong position. I will try AmeliaBR's suggestion and scale the two divs so that they will both fit in the page body. My initial attempts to do that haven't been successful, though. Will keep trying. Thanks. – ELamar Apr 06 '14 at 19:45
  • I was able to manage a work-around by referring to [http://stackoverflow.com/questions/20141817/how-to-align-two-svgs-side-by-side-in-d3-js] and [http://stackoverflow.com/questions/2697976/css-move-a-floatright-element-to-top-to-align-with-the-first-element-of-the]. For the time being, I modified the css of the div.info by adding float:right; and margin-top: -600px to the attribute list. Thanks again. – ELamar Apr 06 '14 at 20:08

0 Answers0