API Access: Flickr

The following is an introduction to the Flickr API about pulling data from Flickr for use in your maproom.

First, go to Flickr’s developer page and request an API key. You will need to create a Flickr account first to request an API key.  Once you have your key, you will use this in the URL to every API call you make.

Setting up

Start with an empty maproom layout:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
   
    <style type="text/css">
        html { height: 100% }
        body { height: 100%; margin: 0px; padding: 0px }
        #map_canvas { height: 100% }
    </style>
   
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
   
    <!-- jQuery -->
    <script type="text/javascript" src="http://kensairyce.bol.ucla.edu/jquery-1.5.2.min.js"></script>

    <script type="text/javascript">    
        //declare namespace
        var ryan = {};
       
        //declare map
        var map;

        //trace function for debugging
        function trace(message)
        {
            if (typeof console != 'undefined')
            {
                console.log(message);
            }
        }
                       
        //Function that gets run when the document loads
        ryan.initialize = function()
        {
            var latlng = new google.maps.LatLng(34.0194543,-118.4911912);
            var myOptions = {
                zoom: 12,
                center: latlng,
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };
            map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
           
        }
    </script>
</head>

<body onload="ryan.initialize()">
    <!-- side panel div container -->
    <div style="position:absolute; width:380px; height: 100%; overflow:auto; float:left; padding-left:10px; padding-right:10px;">
        <h1>Flickr API</h1>
    </div>
    <!-- map div container -->

    <div id="map_canvas" style="height:100%; margin-left:400px;"></div>
</body>
</html>

Then, create a few global variables:

1
2
3
4
5
6
7
8
//array to hold flickr markers
var flickr = [];

//bounds to allow zooming to the extent of all markers
var bounds;

//info window
var infowindow = new google.maps.InfoWindow();

Creating a function that calls Flickr’s API

In this tutorial, we will be using Flickr’s photo search API documented here. We will be using the text, lat, lon, radius, radius_units, extras, and per_page arguments to create a search that returns 20 photos around a center point with geotags. To make this API call, input the following URL:

http://api.flickr.com/services/rest/?method=flickr.photos.search&format=json&api_key={your api key}&text=bus&lat=34.0194543&lon=-118.4911912&extras=geo,url_t,url_m&radius=20&radius_units=mi&per_page=20&jsoncallback=?

Let’s break this down:

  • format:  the format in which you wish to receive a response in (we will be using json)
  • api_key:  required API key
  • text: search field (example: food, cats)
  • lat/lon: latitude and longitude
  • extras: this allows us to add additional fields that are otherwise not available by default. In this case, we will ask for: “geo” (for geographic info), “url_sq” (for the photo thumbnail url, and “url_m” (for the regular sized photo url)
  • radius: distance from center point it will search against
  • radius_units:  units that the radius value is in
  • per_page:  number of results to return (max is 100)
  • jsoncallback=?:  remember to append this to the end of your API call

Now let’s create a new function that generates this URL based on the center latitude and longitude of the map. Google has a function to get the current center latitude and longitude coordinates which we will use:

  • map.getCenter().lat()
  • map.getCenter().lng()

Here’s the function:

1
2
3
4
5
6
7
8
9
10
11
//Function to get data from Flickr
ryan.getFlickr = function()
{
    bounds = new google.maps.LatLngBounds ();
    $.getJSON('http://api.flickr.com/services/rest/?method=flickr.photos.search&format=json&api_key=c7da18f4cdc5e79a5f073858e7871a53&lat='+map.getCenter().lat()+'&lon='+map.getCenter().lng()+'&extras=geo,url_t,url_m,url_sq&radius=20&radius_units=mi&per_page=20&jsoncallback=?',
        function(data)
        {
            trace(data);
        }
    );
}

Tracing the data to see what we need

Notice that we are using the trace function to see what gets returned first. Using Chrome’s developer tools, see what appears in the console window.

flickr trace

flickr trace

According to this, the following are the key parameters we need:

  • object -> photos: Object -> photo (array) -> title
  • object -> photos: Object -> photo (array) -> latitude
  • object -> photos: Object -> photo (array) -> longitude
  • object -> photos: Object -> photo (array) -> url_sq
  • object -> photos: Object -> photo (array) -> url_m

Creating a function (createFlickrMarker) to map the results

Now let’s create a second function that maps these results:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//Function to create Flickr Marker
ryan.createFlickrMarker = function(i,latitude,longitude,infowindowcontent,icon)
{
    var markerLatLng = new google.maps.LatLng(latitude,longitude);  
   
    //extent bounds for each stop and adjust map to fit to it
    bounds.extend(markerLatLng);
    map.fitBounds(bounds);
   
    //set marker to be the flickr image, resizing it to 32 by 32 pixels
    var image = new google.maps.MarkerImage(icon, null, null, null, new google.maps.Size(32,32));
   
    //create and map the marker
    flickr[i] = new google.maps.Marker({
        position: markerLatLng,
        map: map,
        title: infowindowcontent,
        icon: image
    });
   
    //add an onclick event
    google.maps.event.addListener(flickr[i], 'click', function() {
        infowindow.setContent(infowindowcontent);
        infowindow.open(map,flickr[i]);
    });
}

This function accepts the following parameters:

  • i: the array count
  • latitude
  • longitude
  • infowindowcontent: an html text string that will be used to populate the infowindow
  • icon: the photo icon that will be used instead of the google marker

Notice too that the function creates an “image” variable that resizes the provided thumbnail image to 32 pixels by 32 pixels to adhere to the Google Maps icon size.

Modifying the getFlickr function

Finally, we need to modify the getFlickr function to use the createFlickrMarker we just created:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//Function to get data from Flickr
ryan.getFlickr = function(search)
{
    removeLayer();
    bounds = new google.maps.LatLngBounds ();
    $.getJSON('http://api.flickr.com/services/rest/?method=flickr.photos.search&format=json&api_key=c7da18f4cdc5e79a5f073858e7871a53&text='+search+'&lat='+map.getCenter().lat()+'&lon='+map.getCenter().lng()+'&extras=geo,url_t,url_m,url_sq&radius=20&radius_units=mi&per_page=20&jsoncallback=?',
        function(data)
        {trace(data);
            $.each(data.photos.photo, function(i,item){
                infowindowcontent = '<strong>'+item.title+'</strong><br>';
                infowindowcontent += '<a href="'+item.url_m+'" target="_blank">';
                infowindowcontent += '<img src="'+item.url_t+'"></a>';
                ryan.createFlickrMarker(i,item.latitude,item.longitude,infowindowcontent,item.url_sq); 
            });    
        }
    );
}

Let’s take a closer look at the rewritten getFlickr function. You’ll notice that within the $.getJSON function there is a $.each function, and within that function there is a call to your newly created createFlickrMarker function.

As its name implies, the $.each function will go through each object in your data, retrieve the parameters that you specify, and place them in the variable ‘data’. The data that we want (latitude, longitude, and title) is organized in the following hierarchy: photos->photo. Thus we use the syntax data.photos.photo in order to indicate to the $.each function of the hierarchy.

In the final step of this function, each lat/long and title information extracted from the Flickr search is fed into our createFlickrMarker function which in turns draws a marker in our maproom.

Adding a toggle

Let’s now add a checkbox that will allow users to toggle the Flickr layer on and off. Since we are using an array to map the Flickr objects, let’s bring in the array toggle function from tutorial 4.2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//toggle array layers on/off
ryan.toggleArrayLayer = function(arraylayer)
{
    if (arraylayer) {
        for (i in arraylayer) {                
            if (arraylayer[i].getVisible() == true)
            {
                arraylayer[i].setMap(null);
                arraylayer[i].visible = false;
            }
            else
            {
                arraylayer[i].setMap(map);
                arraylayer[i].visible = true;
            }
        }
    }
}

Then, we just need to create an input checkbox that will have an onclick event to toggle the flickr layer:

1
<input type="checkbox" id="toggleFlickr" onClick="ryan.toggleArrayLayer(flickr)" checked> flickr layer

Complete code example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
   
    <style type="text/css">
        html { height: 100% }
        body { height: 100%; margin: 0px; padding: 0px }
        #map_canvas { height: 100% }
    </style>
   
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
   
    <!-- jQuery -->
    <script type="text/javascript" src="http://kensairyce.bol.ucla.edu/jquery-1.5.2.min.js"></script>

    <script type="text/javascript">    
        //declare namespace
        var ryan = {};
       
        //declare map
        var map;
       
        var flickr = [];

        //defines bounding box of all locations
        var bounds;
       
        //info window
        var infowindow = new google.maps.InfoWindow();
       
        //trace function for debugging
        function trace(message)
        {
            if (typeof console != 'undefined')
            {
                console.log(message);
            }
        }
       
        //toggle array layers on/off
        ryan.toggleArrayLayer = function(arraylayer)
        {
            if (arraylayer) {
                for (i in arraylayer) {                
                    if (arraylayer[i].getVisible() == true)
                    {
                        arraylayer[i].setMap(null);
                        arraylayer[i].visible = false;
                    }
                    else
                    {
                        arraylayer[i].setMap(map);
                        arraylayer[i].visible = true;
                    }
                }
            }
        }
       
        //Function to create Flickr Marker
        ryan.createFlickrMarker = function(i,latitude,longitude,infowindowcontent,icon)
        {
            var markerLatLng = new google.maps.LatLng(latitude,longitude);  
           
            //extent bounds for each stop and adjust map to fit to it
            bounds.extend(markerLatLng);
            map.fitBounds(bounds);
           
            //set marker to be the flickr image, resizing it to 32 by 32 pixels
            var image = new google.maps.MarkerImage(icon, null, null, null, new google.maps.Size(32,32));
           
            //create and map the marker
            flickr[i] = new google.maps.Marker({
                position: markerLatLng,
                map: map,
                title: infowindowcontent,
                icon: image
            });
           
            //add an onclick event
            google.maps.event.addListener(flickr[i], 'click', function() {
                infowindow.setContent(infowindowcontent);
                infowindow.open(map,flickr[i]);
            });
        }
               
        //Function to get data from Flickr
        ryan.getFlickr = function(search)
        {
            bounds = new google.maps.LatLngBounds ();
            $.getJSON('http://api.flickr.com/services/rest/?method=flickr.photos.search&format=json&api_key=c7da18f4cdc5e79a5f073858e7871a53&text='+search+'&lat='+map.getCenter().lat()+'&lon='+map.getCenter().lng()+'&extras=geo,url_t,url_m,url_sq&radius=20&radius_units=mi&per_page=20&jsoncallback=?',
                function(data)
                {trace(data);
                    $.each(data.photos.photo, function(i,item){
                        infowindowcontent = '<strong>'+item.title+'</strong><br>';
                        infowindowcontent += '<a href="'+item.url_m+'" target="_blank">';
                        infowindowcontent += '<img src="'+item.url_t+'"></a>';
                        ryan.createFlickrMarker(i,item.latitude,item.longitude,infowindowcontent,item.url_sq); 
                    });    
                }
            );
        }
                       
        //Function that gets run when the document loads
        ryan.initialize = function()
        {
            var latlng = new google.maps.LatLng(34.0194543,-118.4911912);
            var myOptions = {
                zoom: 12,
                center: latlng,
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };
            map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
           
            //Sample call for yelp data for cafe's
            ryan.getFlickr('bus');
        }
    </script>
</head>

<body onload="ryan.initialize()">
    <!-- side panel div container -->
    <div style="position:absolute; width:380px; height: 100%; overflow:auto; float:left; padding-left:10px; padding-right:10px;">
        <h1>Flickr API</h1>
        <input type="checkbox" id="toggleFlickr" onClick="ryan.toggleArrayLayer(flickr)" checked> flickr layer
    </div>
    <!-- map div container -->

    <div id="map_canvas" style="height:100%; margin-left:400px;"></div>
</body>
</html>

Sample Code

Leave a Reply