Kartograph.js: 2. Bölüm Etkileşimli Haritalar

Merhabalar,

Geçtiğimiz hafta temel anlamda Kartograph kütüphanesi nasıl kurulur, kullanılır konusuna değinmiştim. Bu hafta başladığımız çalışmaya devam ederek haritalar üzerinde bilgi balonları çıkarma ve bar grafikler çizme konusuna değineceğim.

Etkileşimli Haritalar

İlk örneğimiz bölgelerin üzerine gelindiğinde ufak bir bilgi balonu çıkarmak olacak. Bunun için Jquery QTip2 eklentisine ihtiyaç duyuyoruz. Geçtiğimiz hafta içi QTip2 projesinin stabil sürümü jquery’nin son sürümü ile sorunlu çalıştı bu yüzden nightly build indirmenizi tavsiye ediyorum.

Qtip2’yi indirdikten sonra aşağıdaki satırları html kodunuza eklemeniz gerekmektedir.

<link href="/s/css/jquery.qtip.min.css" rel="stylesheet" media="screen">
<script type="text/javascript" src="jquery.qtip.min.js"></script>


Şimdi sıra geçtiğimiz hafta katman eklemek için kullandığımız addLayer fonksiyonunu değiştirmeye geldi.

map.addLayer('countries', {
    styles: {
        fill: '#abc',
        stroke: '#fff'
    },
    chunks: 50,
    tooltips: function(data) {
        return "Merhaba Dünya";
    }
});


addLayer fonksiyonun da kullandığımız tooltip ifadesi fare ile svg path elemanın üzerine gelindiğinde görüntülenmesi istenen değeri döndüren bir fonksiyondur. İlk aşamada sadece “Merhaba Dünya” ifadesini döndürecektir, data parametresinden birazdan bahsedeceğim.

İlk bilgi balonumuz şöyledir.

popupHelloWorld

Eğer bu görüntü hoşunuza gitmediyse, bootstrap desteğini de kullanmamız mümkün. Bunu yapmak için aşağıda ki kodları loadMap fonksiyonundan önce ekleyiniz.

$.fn.qtip.defaults.style.classes = 'qtip-bootstrap';
$.fn.qtip.defaults.style.def = false;


popupHelloWorld2

Ufak bir not, balonlar içinde html taglerini kullanmanızın mümkün olduğunu belirteyim.

Evet ilk aşamayı böylece tamamlamış bulunuyoruz. Peki bilgi balonlarında gösterilecek bu verileri SVG içersinden nasıl çekeceğiz, daha da önemlisi bu bilgileri SVG içersine nasıl ekleyeceğiz?

Öncelikle daha kısa olduğu için SVG içersinden nasıl veri çekebileceğimizden bahsetmek istiyorum. Yapmamız gereken tek şey tooltips için tanımladığımız fonksiyonun data parametresini kullanmak olacaktır. Bu data parametresin ile SVG içersinde bulunan path elemanına ait attributelere erişmemiz mümkün. Örnek olarak üzerine gelindiğinde ülke isimlerini listelemek istersek yapmamız gereken kodu aşağıda ki gibi değiştirmek olacaktır.

tooltips: function(data) {
    return data.name;
}


popupHelloWorld3

Şimdi sırada istediğimiz bilgileri içersinde barındıran SVG’ler üretmeye geldi. Bu işi yapmak için bir önceki yazıda kullandığımız kartograph.py kütüphanesini kullanacağız. Geçen yazıda kullandığımız json dosyasının içeriğinde ufak bir değişiklik yapıyoruz ve iki anahtar ifade daha ekliyoruz, “charset” ve “attributes”. World.json dosyamızın içeri şu şekildedir.

{
    "layers": [{
        "id"         : "countries",
        "src"        : "ne_50m_admin_0_countries.shp",
        "charset"    : "utf-8",
        "attributes" : "all"
    }],
    "export": {
        "width" : 1000
    },
    "styles": {
        "fill"  : "#dfdcdc",
        "stroke": "#fff"
    }
}


İlk aşamada kaynak dosyasının içeriğini bilmediğimizi varsayarak tüm bilgileri SVG’ye ekleyelim. Bunun için attribute anahtar kelimesine “all” değerini vermemiz yeterli. “charset” ile SVG içersine yazılacak bilgilerin hangi encoding kullanılarak yazılacağını belirtiyoruz. Json dosyamızda gerekli değişiklikleri yaptıktan sonra kartograph.py’i çalıştırıyoruz.

kartograph world.json -o world-detailed.svg


Elde edilen yeni SVG dosyası yaklaşık 300kb daha büyük oldu. Bu SVG içerinde hangi attributelar olduğunu öğrenmek için aşağıdaki basit python betiği kullanabiliriz.

from xml.dom import minidom
svgFile = 'world-detailed.svg'
xmldoc = minidom.parse(svgFile)
paths=xmldoc.getElementsByTagName('path')
p=paths[0] # sadece ilk elemana bakalım.
attr=p.attributes
for k in attr.keys():
    if k <> 'd':
        print k, '=',attr.get(k).value


Bu betik ilk path elemanı üzerinde tanımlanmış attribute ve değerlerini listeliyor.  Betik sadece fikir vermesi için hazırlanmıştır. d attributeu bu aşamada işimize yaramayacağı için atlanmıştır. Betiğin ekran çıktısı şu şekildedir.

data-adm0-a3-is = ABW
data-mapcolor13 = 9.0
data-su-dif = 0.0
data-sovereignt = Netherlands
data-wb-a3 = ABW
data-fips-10 =
data-admin = Aruba
data-pop-year = -99.0
data-geou-dif = 0.0
data-lastcensus = 2010.0
data-economy = 6. Developing region
data-gdp-year = -99.0
data-tiny = 4.0
data-sov-a3 = NL1
data-adm0-a3-us = ABW
data-iso-n3 = 533
data-mapcolor8 = 2.0
data-mapcolor9 = 2.0
data-subregion = Caribbean
data-un-a3 = 533
data-abbrev = Aruba
data-formal-fr =
data-abbrev-len = 5.0
data-adm0-a3-wb = -99.0
data-homepart = -99.0
data-name-sort = Aruba
data-adm0-a3-un = -99.0
data-featurecla = Admin-0 country
data-subunit = Aruba
data-long-len = 5.0
data-income-grp = 2. High income: nonOECD
data-region-un = Americas
data-brk-name = Aruba
data-adm0-dif = 1.0
data-name-alt =
data-adm0-a3 = ABW
data-postal = AW
data-brk-diff = 0.0
data-brk-a3 = ABW
data-name = Aruba
data-name-long = Aruba
data-gdp-md-est = 2258.0
data-scalerank = 3
data-iso-a3 = ABW
data-iso-a2 = AW
data-su-a3 = ABW
data-labelrank = 5.0
data-geounit = Aruba
data-brk-group =
data-gu-a3 = ABW
data-woe-id = -99.0
data-pop-est = 103065.0
data-mapcolor7 = 4.0
data-note-brk =
data-wb-a2 = AW
data-continent = North America
data-type = Country
data-note-adm0 = Neth.
data-formal-en = Aruba
data-region-wb = Latin America & Caribbean
data-wikipedia = -99.0
data-name-len = 5.0
data-level = 2.0


Bu bilgilere tooltips için tanımladığımız fonksiyonunun data parametresi üzerinden erişmemiz mümkün.

Harita Üzerinde Bar Grafiği Göstermek

Bilgi balonları konusunu tamamladıktan sonra şimdi sıra haritalar üzerinde çeşitli olay yoğunluklarını özetlemek için yaygın olarak kullanılan bar grafiklerine geldi. Bu tip grafikleri çizmeden önce haritalar üzerinde basit işaretleri nasıl koyacağımızdan bahsedelim. Örnek olarak Türkiye sınırları içersinde bir nokta ve bu noktaya bir bilgi balonu ekleyelim.

function drawPoint(map, x, y) {
    x = -1 * x;
    var c = new Array(x, y);
    var bar = map.addGeoPath([c, c]);
    bar.attr({
        stroke: '#FF0000',
        opacity:.75,
        'stroke-width': 5,
        fill: '#FF0000',
        'stroke-linecap': 'round'
    }); /* stroke-linecap için tanımlı değerler: butt, round, square, inherit */

    if (Raphael.svg) {
        /* Bilgi Balonu için kullanılan kod bölümü */
        setTimeout(function() {
            $(bar.node).qtip({
                content: {
                    title: 'Baslik',
                    text: 'x: ' + x + ' y: ' + y
                },
                position: {
                    target: 'mouse',
                    viewport: $(window),
                    adjust: { x:7, y:7}
                }
            }, 0);
        });
    } else {
        bar.attr('path', map.getGeoPathStr(pts));
    }
}

Bu fonksiyonu addLayer fonksiyonundan sonra drawPoint(map, 40, 40); şeklinde çağırdığımızda aşağıda ki ekran görüntüsünü elde ediyoruz.
pointWithPopup
parametre olarak x için 40 vermemize rağmen -40 olmasının sebebi kullanılan koordinat sistemlerinin farklı olmasıdır. Ayrıntılara sonraki yazılarda değinmeye çalışacağım.
Kodu kısaca açıklayalım.
  • var c = new Array(x, y); ile bir koordinat ikilisi olusturuyoruz. Daha sonra bu duzlemde gosterilecek noktamızı var bar = map.addGeoPath([c, c]); komutu ile sisteme ekliyoruz. Bu fonksiyon parametre olarak çizilecek şekil koordinatlarını alıyor. En az iki nokta tanımlamamız gerekmekte, nokta olduğu için tanımlanan iki noktada birbirinin aynısı oluyor. Öteyandan bu fonksiyona birden fazla koordinat vermenizde mümkün.
  • noktamızı olusturduktan sonra görsel özelliklerini belirlemek için bar.attr() fonksiyonunu kullanıyoruz. Bu fonksiyonun özelliklerinden vurgulamam gereken sadece “stroke-linecap” olduğunu düşünüyorum. Bu değer konulacak olan noktanın şeklini belirlemeye yarıyor ve alabileceği değerler ise “butt, round, square, inherit” olarak tanımlıdır.
  • Devamında ki bölümde ise qtip kullanarak konulan nokta için bilgi balonu tanımlanıyor.

Noktanın nasıl ekleneceğini gördükten sonra bunu bir bar haline getirmek için yapmamız gereken tek şey, noktayı tanımlamak için kullandığımız koordinatlardan ikincisini istenilen büyüklüğe uygun olacak koordinatı hesaplamak ve çizdirmek olacaktır. Örnek kodu aşağıda ki gibi güncellemediğimizde  bu ekran görüntüsünü elde edeceğiz.

drawPoint(map, 42, 38.42);

// drawPoint fonksiyonun içini aşağıdaki gibi güncelleyiniz.

var c = new Array(x, y);
var d = new Array(x+0.6, y+4);
var bar = map.addGeoPath([c, d]);

barWithPopup

Burada örnek olması için verdiğimiz değerlerin oluşturduğunuz haritalara göre otomatik hesaplanabiliyor olması gerekmektedir. Bu konuya ilerleyen yazılarda değineceğim.
Umarım faydalı bir yazı olmuştur.
İyi haftalar,
Gürcan
Tagged with: , ,
Posted in yakindanegitim

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Archives
%d bloggers like this: