0

So I'm using the simple Geomap library on top of D3 to draw a map. All I want to do now is to have shape I draw before rendering the map to appear 'on top of' the map.

I know I can draw on top of the map as I'm rendering it, but I want to draw some shapes on the page first, then render the map, but have my original shapes appear on top of the map (at the moment they appear 'under' the map).

I've created a very simple JSFiddle to show the problem, although I don't know how to include the 'GeoMap' JS code as an external resource. Hopefully the example is simple enough to understand as is: http://jsfiddle.net/vqxf951t/2/

            d3.selection.prototype.moveToFront = function () {
            return this.each(function () {
                this.parentNode.appendChild(this);
            });
        }


        d3.selection.prototype.moveToBack = function () {
            return this.each(function () {
                var firstChild = this.parentNode.firstChild;
                if (firstChild) {
                    this.parentNode.insertBefore(this, firstChild);
                }
            });
        }


        function finishedDrawingMap() {
            d3.select('#allParts')
                .append('g')
                .attr('id', 'blueRect')
                .append('svg')
                .append('rect')
                .style({
                'position': 'fixed',
                'left': '5px'
            })
                .attr('width', 1500)
                .attr('height', 300)
                .attr('fill', 'blue');


            d3.select('#yellowRect').moveToFront();
            d3.select('#blueRect').moveToFront();
        }


        $(document).ready(function () {
            allParts = d3.select('#mapDemo')
                .append('g')
                .attr('id', 'allParts');

            allParts.append('svg')
                .attr('id', 'yellowRect')
                .append('rect')
                .style({
                'position': 'fixed'
            })
                .attr('width', 800)
                .attr('height', 100)
                .attr('fill', 'yellow');

            allParts.append('svg')
                .attr('id', 'map')
                .attr('width', 800)
                .attr('height', 200)
                .style({
                'position': 'fixed',
                'left': '5px'
            })
                .style('opacity', 1);

            var map = d3.geomap()
                .geofile('../resources/js/plugins/d3.geomap/topojson/countries/USA.json')
                .projection(d3.geo.albersUsa)
                .scale(1000)
                .postUpdate(finishedDrawingMap);

            d3.select('#map').call(map.draw, map);
        });

The example simply creates an SVG 'g' element, then puts inside that 'g' a yellow rectangle, then draws the map, then when the map is rendered (i.e. the 'postUpdate() function is called), it draws a blue rectangle.

Both rectangle's appear under the map, even though I drew the blue one after the map had rendered.

I've tried using simple 'moveToBack()' and 'moveToFront()' methods (that I've successfully used in other parts of my JS), and I can see in WebDeveloper tools that HTML does have the 'map' in-between the two rectangles, but I just can't figure out why the map continues to be rendered on top of the two rectangles...!?

Thanks,

Pat.

PMcB
  • 21
  • 2

1 Answers1

1

Even though you're appending your blue rect after the map has been drawn, it is being added to a g element that was created before the map svg was created, therefore it will still be "under" the map In your postUpdate function, append another g element to allParts and add the rect to that and you should see it appear on top of the map. With a working jsfiddle I could verify that this is definitely the case, but give it a go.

Ben Lyall
  • 1,976
  • 1
  • 12
  • 14
  • Thanks so much Ben. Your comment gave me enough of a clue to fix my problem - although to be honest I'm still not 100% sure how it's now working! (I fixed it via experimentation really, but based strongly on your comment). I also need to learn JSFiddle better to be able to include external files - so much stuff to learn... – PMcB Feb 18 '15 at 12:12