Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to overlay a dynamically selected image over a dynamically populated div

Description of requirement:

I am using d3 to parse a .csv file for data and then populate various items on a page dynamically. One section is shown below:

Requirement

My Code progression:

  • I started out by housing each dynamically retrieved number within its own div tag and setting the background image for each dynamically. Here is the d3 JavaScript code:

    careerstage_td.append("div")
    .text(function(d){ return d.count })
    .attr("class", "career-count")
    .style("color", function(d){return d.color;})
    .style("background-image", function(d){return "url('images/" + d.icon + "')";})
    .style("background-repeat", "no-repeat")
    .style("background-position", "center center");
    

    (Notice that I am using a function to dynamically populate the number as well as to figure out which image to overlay)

    This gave me the following expected result, where the images were behind the text:

First implementation pass result

  • The next step was to figure out how to overlay that background image on top of the text. For this I started digging around on google and found this question on SO: How to overlay images. Over here I identified two different solutions:

    Solution 1: (from the top answer on that page) add a span in the div with the number, then position the span absolutely in the center using css, like so

    div.career-count span.stickperson
    {
        position:absolute;
        left:45%;
        top: 34%;
    }
    

    Solution 2: (from another answer on that page) Add the following css that extends the class of the div with the dynamic text, like so

    .career-count:after
    {
        content: url(/images/person_assoc.gif);
        position: absolute;
        left:45%;
        top: 34%;
    }
    

Both solutions work, but Solution 1 only works in Chrome, and Solution 2 doesn't allow me to set the images dynamically since it is all done in css and the 'after' contruct cannot be used in-line.

I would appreciate help in figuring out a solution that allows me to set the image dynamically and also works in Chrome, Firefox 25 and IE 11.

EDIT: Thanks for the up-votes, folks. I added images now :)

like image 725
BakaTono Avatar asked Nov 02 '22 10:11

BakaTono


1 Answers

Actually I think the best solution is not to add a background-image to the div elements in which you put your text, but rather to create a child div for each div you created, and work with the image inside the child.

careerstage_td.selectAll('div')
    .data(dataset)
    .enter().append('div')
    .attr("class", "career-count")
    .text(function(d){return d;})
    .style("color", function(d){return d.color;})
    .append('div')
    .attr("class", "childClass")
    .style("background-image", function(d){return "url('images/" + d.icon + "')";})
    .style("background-repeat", "no-repeat")
    .style("background-position", "center center");

In the given code, I generate my divs thanks to the data, and for each div I append a new div (classnames "childClass"). Now I can play on this childClass.

See the jsfiddle for an example. (note that I used a simplified dataset so I pushed always the image as a background, and the same text color).

The trick to ensure that the icon displays in the middle of the parent node is to define the parent as position:relative and the children as absolute with a width and height of 100%. Centering the background both on x and y does the job.

like image 51
leMoisela Avatar answered Nov 14 '22 14:11

leMoisela