D3.js Başlangıç

D3.js ile grafik oluştururken yapılan işlemleri sırayla inceleyelim.

1) Veriyi Yüklemek

Veri kaynağına bakılmaksızın, büyük olasılıkla XML, CSV veya JSON formatında tekli veri dosyalarına sahip olacaksınız. D3 bu verileri almak ve kullanmak için çeşitli fonksiyonlar sunar. Bu formatlar arasındaki temel farklardan biri verileri nasıl modellediğidir. Başka bir fark, d3.csv() ve d3.json() ‘in bir JSON nesneler dizisi üretmesi, d3.xml() ise farklı şekilde erişilmesi gereken bir XML belgesi oluşturmasıdır.

1.1) Dosya Formatları

D3’te, karşılaşacağınız beş dosya türüne karşılık gelen verileri yüklemek için beş işlev bulunur:

Genellikle d3.csv() ve d3.json() kullanılır. d3.xml() ve d3.text()‘yi verilerle nasıl ilgilendiğinize bağlı olarak daha kullanışlı bulabilirsiniz. JSON yerine XML’de rahat olabilirsiniz (küçük bir ihtimal), bu durumda d3.xml() yöntemini kullanabilir ve veri fonksiyonlarınızı buna göre formatlayabilirsiniz. Metin dizeleriyle çalışmayı tercih ediyorsanız, verileri almak ve başka bir kütüphane veya kod kullanarak işlemek için d3.text() komutunu kullanabilirsiniz. Hem d3.csv() hem de d3.json() veriyi yüklerken, yüklenmekte olan dosyanın yolunu bildirerek ve geri çağırma (callback) fonksiyonunu tanımlayarak aynı biçimde kullanılır:

d3.csv("sehirler.csv", function (error, data) {
  console.log (error, data);
}); 

Hata değişkeni isteğe bağlıdır ve yalnızca tek bir değişken yazarsak, bu veriler değişkeni olacaktır:

d3.csv("sehirler.csv", function (d) {
  console.log (d)
}); 

Önce geri arama (callback) işlevindeki verilere erişirsiniz ve verileri başka bir yerde kullanabilmeniz için bir genel değişken olarak bildirmek isteyebilirsiniz.

2) Veriyi Formatlamak

Farklı veri formatlarıyla ilgilenirken, daha iyi kullanabilmek için verileri bir türden diğerine değiştirirsiniz. Elinizdeki veriler sayısal, metin veya tarih verileri olabilir fakat bunlar string olarak saklıysa bunları JS’in doğru kullanabilmesi için öncelikle dönüştürmeniz gerekir. Birkaç basit örnek:

parseInt('12')
parseFloat('1.23')
Date.parse('Wed, 12 Aug 2019 10:00:00 GMT')
var text = 'mavi,sarı,yeşil'.split(',')

2.1) Ölçekler ve Ölçeklendirme

Sayısal veriler, nadiren doğrudan ekrandaki grafik öğelerin konumuna ve boyutuna karşılık gelir. Bir ekranda sunum için verilerinizi normalleştirirken d3.scale() işlevlerini kullanabilirsiniz. Bakacağımız ilk ölçek, bir sayı dizisi ile diğeri arasında doğrudan bir ilişki kuran d3.scale().linear()‘dır. Örneğin, sehirler.csv’deki en küçük nüfus değerini ve en büyük nüfus değerini alırsanız, en küçüğünden en büyüğüne ölçeklenen bir rampa oluşturabilir, böylece aralarındaki farkı 500 piksellik bir grafikte kolayca görüntüleyebilirsiniz. 500.000’den 13.000.000’e kadar aynı doğrusal değişim oranının 0’dan 500’e kadar bir doğrusal değişim oranına eşlediğini görebilirsiniz.

var newRamp = d3.scale.linear().domain([500000, 13000000]).range([0, 500]);
newRamp(1000000); // 20
newRamp(9000000); // 340
newRamp.invert(313); // 8325000 

.invert() fonksiyonu ile tersine dönüşüm yapabilirsiniz. Önceden aldığınız küçük değerin gerçekte ki karşılığını öğrenmek için tekrar kullanılabilir.

.scale fonksiyonu renkler içinde kullanılabilir. Örneğin:

var newRamp = d3.scale.linear().domain([500000, 13000000]).range(["blue", "red"]);
newRamp(1000000);  // #0a00f5
newRamp(9000000);  // #ad0052
newRamp.invert("#ad0052");  // NaN 

.invert fonksiyonu sadece sayısal değerlerde kullanılır. Renk için kullanıldığında NaN değerini döner. Ayrıca, bu ölçeklerin veri kümenize daha uygun olduğu verileri eşlemek için d3.scale.log(), d3.scale.pow(), d3.scale.ordinal() ve daha az yaygın olan diğer ölçekleri de kullanabilirsiniz. d3.time.scale(), tarih veri türleriyle uğraşmak üzere tasarlanmış doğrusal bir ölçek sağlar.

2.2) Kategorize Etmek

Nicel verileri kategorilere ayırmak, değerleri bir aralığa koymak veya değerleri bir araya getirmek için “kutuya” yerleştirmek faydalıdır. Bir yöntem, diziyi eşitlenmiş parçalara bölerek nicelikleri kullanmaktır. D3’teki nicelik ölçeği d3.scale.quantile() olarak adlandırılır ve diğer ölçeklerle aynı ayarlara sahiptir. Parçaların ve etiketlerinin sayısı .range() ayarıyla belirlenir.

Diğer ölçeklerden farklı olarak, .domain() değerleri ile .range() değerleri arasında niceliksel bir ölçekle uyumsuzluk olması durumunda hata vermez, çünkü etki alanındaki değerleri otomatik olarak aralık içinde daha az sayıda değere göre sıralar ve bunları bağlar. Ölçek, .domain() içindeki sayı dizisini en küçükten en büyüğe sıralar ve gerekli kategorileri oluşturmak için değerleri uygun noktada otomatik olarak böler.

var qScale = d3.scale
  .quantile()
  .domain([423, 124, 66, 424, 58, 10, 900, 44, 1])
  .range([0, 1, 2]);

qScale(423); // 2
qScale(20); // 0
qScale(10000); // 2

Yukarıda domain fonksiyonuna verilen değerler küçükten büyüğe sıralandıktan sonra range içerisindeki değerlere karşılık gelecek şekilde gruplanırlar. Yukarıdaki örnek için:

3) Veriyi Hesaplamak

Veri dizinizi yükledikten sonra yapmanız gereken ilk şeylerden biri, onu ölçmek ve sıralamaktır. Belirli niteliklerin değerlerinin dağılımını, ayrıca minimum ve maksimum değerlerini bilmek gerekebilir. D3 verilerinizi anlamanıza yardımcı olacak bir birkaç liste işlevi sunar. Örnek bir sayısal değer içeren veri listesi:

const test = [88, 10000, 1, 75, 12, 35];

d3.min(test, d => d); // 1
d3.max(test, d => d); // 10000
d3.mean(test, d => d); // 1701.833

min ve max değerini tek seferde almak için extent fonksiyonu kullanılabilir.

d3.extent(test, d => d); // [1, 10000] 

4) Veriyi Görüntülemek

Elimizdeki veriyi yükleyip düzenledikten sonra nasıl görüntüleyeceğimizi gösteren basit bir örnek.
Cities.csv dosya içeriği.

San Francisco
Fresno
Lahore
Karachi
Rome
Naples
Rio
Sao Paolo

Örnek kod:

d3.csv("cities.csv", function(error,data) {
  dataViz(data);
});

function dataViz(data) {
  d3.select("body").selectAll("div.cities")
    .data(data)
    .enter()
    .append("div")
    .attr("class","cities")
    .html(function(d,i) { return d.label; });
}

Çıktı:

<body>
  <div class="cities">San Francisco</div>
  <div class="cities">Fresno</div>
  <div class="cities">Lahore</div>
  <div class="cities">Karachi</div>
  <div class="cities">Rome</div>
  <div class="cities">Naples</div>
  <div class="cities">Rio</div>
  <div class="cities">Sao Paolo</div>
</body>

d3.selectAll()

Herhangi bir seçimin ilk kısmı, DOM’nin bir kısmına karşılık gelen bir CSS tanımlayıcısına sahip d3.select() veya d3.selectAll()‘dır. Belirli bir DOM öğesinin alt öğelerinin nasıl oluşturulacağını ve değiştirileceğini belirlemek için bir seçim yapabilirsiniz. Bir alt seçimin otomatik olarak bir üst element oluşturmayacağını unutmayın. Üst element zaten var olmalı, yoksa .append() kullanarak bir tane oluşturmanız gerekir.

.data()

Burada bir diziyi, seçtiğiniz DOM öğeleriyle ilişkilendirirsiniz. Veri kümemizdeki her şehir, seçimdeki bir DOM öğesiyle ilişkilendirilir ve bu ilişkili veriler, öğenin veri niteliğinde depolanır. Bu değerlere JavaScript kullanarak manuel olarak erişebildik:

document.getElementsByClassName("cities")[0].__data__

.enter() ve .exit()

Verileri seçimlere bağlarken, daha fazla, daha az veya veri değerleriyle aynı sayıda DOM öğesi olacaktır. Seçimdeki DOM öğelerinden daha fazla veri değeriniz varsa, seçimde karşılık gelen bir DOM öğesi olmayan her değer için gerçekleştirilecek davranışı tanımlamanıza izin veren .enter() işlevini kullanırsınız. Bu durumumuzda .enter() sekiz kez çalışır, çünkü hiçbir DOM öğesi “div.cities”e karşılık gelmez ve data dizimiz sekiz değer içerir. Daha az veri öğesi olduğunda, .exit() davranışı tetiklenir ve bir seçimde eşit veri değerleri ve DOM öğeleri olduğunda, .exit() veya .enter() çalışmaz.

.append() ve .insert()

DOM öğesinden daha fazla veri değeri olduğunda neredeyse her zaman DOM’ye öğe eklemek isteyeceksiniz. .append() işlevi, daha fazla öğe eklemenizi ve hangi elemanları ekleyeceğinizi tanımlamanızı sağlar. Örneğimizde <div> öğelerini ekliyoruz, ancak bu bölümde daha sonra SVG şekillerini ekleyeceğiz ve diğer bölümlerde tablolar ve butonlar ve HTML’de desteklenen başka bir öğe türü ekleyeceğiz. .insert() işlevi, .append() işlevinin bir benzeridir, ancak .insert(), DOM’da yeni öğeyi nereye ekleyeceğinizi belirlemenize izin verir.

.attr()

D3 sözdizimini kullanarak stilleri ve nitelikleri değiştirebilirsiniz. Unutulmaması gereken tek şey, burada tanımladığınız işlevlerin her birinin sayfaya eklenen her yeni öğeye uygulanacağıdır. Örneğimizde dört yeni <div> öğemizin her biri class="cities" ile oluşturulacak.

.html()

DOM öğelerinde, içeriği .html() işleviyle ayarlarsınız. Bu örnekde elimizdeki verinin label değerini div elementlerine ekledik.

https://www.manning.com/books/d3js-in-action-second-edition