0

I would like to create something like the image below but instead of the circles I would like to use images of emoji's (the whatsapp emoticons etc.)

enter image description here

The data I would like to extract from the JSON should look something like this:

{
    'url': 'see-no-evil.png',
    'hits': 456
  }, 
  {
    'url': 'speak-no-evil.png',
    'hits': 425
  },

The emoji's should appear on a canvas randomly and the one with the most "hits" should be displayed the biggest and the one with the least hits as the smallest. It should be as simple as possible and automatic update as soon as I change the values or add something to the JSON.

Does anyone know how I can achieve this?

I found a really great example but I don't know how to play with the code so that I can get images instead of colours? http://codepen.io/girliemac/pen/cDfmb

VividD
  • 10,456
  • 6
  • 64
  • 111
Mae
  • 443
  • 2
  • 5
  • 22
  • Where are you looking for the data from? If you know - go look at the API - if not then find a source. We're not here to do work for you - we're here to solve problems. – BLewis Jan 05 '15 at 08:14
  • @BLewis I don't need like real live data. The thing is that I want to know how I can make something like this? I will just make up some data in a JSON file. – Mae Jan 05 '15 at 08:17
  • @BLewis Also, I found a great example here: http://codepen.io/girliemac/pen/cDfmb but the thing is that I don't know how to edit it so it only shows images instead of colours. – Mae Jan 05 '15 at 08:20
  • OK, so you should probably re-phrase your question - what you're looking for is a way to use D3 to embed custom images - you could simply use dynamic CSS to style elements like the one you've sent but that'd be inefficient with many emoji - so you probably want the web browser to rasterise the output - I've not done this - so I can't really offer a solution. Sorry! – BLewis Jan 05 '15 at 08:21
  • If you simply want it to work, but don't care about performance/build time - modify the CSS to use `background-image` instead of `background-colour` and reference the emoji - another minor time saver while building is to use JS to add that CSS from the JSON instead. – BLewis Jan 05 '15 at 08:23
  • @BLewis Yeah I'm only planning to use like 10 emoji's. And thanks for your tip, I didn't know how to ask the question. I think that code generates an SVG file and they use "fill" in CSS but I don't think you can fill with an image but only with HEX colours – Mae Jan 05 '15 at 08:24
  • I see. Stupid me thinking it was HTML. You're right - it's an SVG, see this: http://stackoverflow.com/questions/19202450/adding-an-image-within-a-circle-object-in-d3-javascript – BLewis Jan 05 '15 at 08:28
  • @BLewis the thing is that they don't use `background-colour` but something called `fill` – Mae Jan 05 '15 at 08:28
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/68203/discussion-between-mae-and-blewis). – Mae Jan 05 '15 at 08:33

1 Answers1

4

d3 is a good library to use for this.

In your example, try replacing this code:

vis.enter().append('circle')
        .attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; })
        .attr('r', function(d) { return d.r; })
        .attr('class', function(d) { return d.className; });

with this code:

vis.enter().append("image")
    .attr("xlink:href", "your-image-url.png")
    .attr("width", function(d) { return 2*d.r; })
    .attr("height", function(d) { return 2*d.r; })
    .attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; })
    .attr('class', function(d) { return d.className; });

Note that you will have to play with the size of the images a bit because the image will be square and you are trying to deal with circles. Try to find an image where the emoji touches the edges of the image.

Hope this helps! Let me know how it goes.

EDIT: solution part 2 based on discussion in the comments

(function() {

var json = {"countries_msg_vol": [
    {"url":"emoji-1.png","hits":100},{"url":"emoji-2.png","hits":200}
  ]};

    // D3 Bubble Chart 

    var diameter = 600;

    var svg = d3.select('#graph').append('svg')
                    .attr('width', diameter)
                    .attr('height', diameter);

    var bubble = d3.layout.pack()
                .size([diameter, diameter])
                .value(function(d) {return d.size;})
         // .sort(function(a, b) {
                //  return -(a.value - b.value)
                // }) 
                .padding(3);

  // generate data with calculated layout values
  var nodes = bubble.nodes(processData(json)); // filter out the outer bubble

  var vis = svg.selectAll('circle')
                    .data(nodes);

  vis.enter().append("image")
    .attr("xlink:href", function(d){

    return  d.url;})
    .attr("width", function(d) { 
    console.log("d.r:"+d.r);
    return d.r; })
    .attr("height", function(d) { return d.r; })
    .attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; })
    .attr('class', function(d) { return d.className; });

  function processData(data) {
    var objs = data.countries_msg_vol;

    var newDataSet = [];


    for(var i=0; i<objs.length; i++) {
        var obj = objs[i];
 console.log(obj.url+" "+obj.hits);
      newDataSet.push({url: obj.url, className: obj.url, size: obj.hits});
    }
    return {children: newDataSet};
  }

})();
  • Thanks for your tweak! It worked and turned out like this http://i.imgur.com/FywzJQ5.png. Appending on all objects. So if I would like it per object I would most likely have to add each and every url of the emoji in the JSON data set right? edit - wait a minute, it's a fake json dataset. Is there a way I can assign a picture for each different object? – Mae Jan 05 '15 at 08:45
  • Yep you're right, that's just a matter of changing the data. Here's a full example, but you will need to add more JSON data to see any decent results. –  Jan 05 '15 at 09:04
  • One second, I can't comment it's too large –  Jan 05 '15 at 09:05
  • Ok I've updated with a more complete solution in the original answer. You can see in the JSON data how you can now add more elements. Cheers! –  Jan 05 '15 at 09:06