D3.js ile Halka Grafiği Oluşturma

Merhaba, bu yazıda D3.js kütüphanesini kullanarak basit bir halka grafiği oluşturacağız. Aynı zamanda attrTween fonksiyonu kullanarak grafiğe animasyon ekleyeceğiz.

Grafikte görselleştireceğimiz veri seti aşağıdadır.

var dataset = [
	{ name: 'IE', percent: 39.10 },
	{ name: 'Chrome', percent: 32.51 },
	{ name: 'Safari', percent: 13.68 },
	{ name: 'Firefox', percent: 8.71 },
	{ name: 'Others', percent: 6.01 }
];

Aşağıdaki kod ile grafiğimizi oluşturuyoruz.

padAngle() fonksiyonu ile grafik arayüzüne padding ekliyoruz. Renk ataması için d3.scale.category10() fonksiyonunu kullanıyoruz. Ayrıca arc bileşenine innerRadius() ekleyerek grafiğimizin pasta dilim yerine halka grafik olmasını sağlıyoruz.

var pie=d3.layout.pie()
        .value(function(d){return d.percent})
        .sort(null)
        .padAngle(.03);
 
var w=300,h=300;
 
var outerRadius=w/2;
var innerRadius=100;
 
var color = d3.scale.category10();
 
var arc=d3.svg.arc()
        .outerRadius(outerRadius)
        .innerRadius(innerRadius);
 
var svg=d3.select("#chart")
        .append("svg")
        .attr({
            width:w,
            height:h,
            class:'shadow'
        }).append('g')
        .attr({
            transform:'translate('+w/2+','+h/2+')'
        });
var path=svg.selectAll('path')
        .data(pie(dataset))
        .enter()
        .append('path')
        .attr({
            d:arc,
            fill:function(d,i){
                return color(d.data.name);
            }
        });

Grafik için yazdığımız HTML.

<div class="widget">
    <div class="header">Browser Market Share</div>
    <div id="chart" class="chart-container"></div>
</div>

Artık attrTween() fonksiyonu ile grafiğe animasyon ekleyebiliriz. Animasyon için ara adımları hesaplama işleminde d3.interpolate() metodunu kullanıyoruz. Animasyon geçiş süresini ise 1 saniye olarak belirledik. Aşağıdaki kod bloğunu HTML ‘ e ekleyip sayfayı yenileyin. Animasyon eklendi.

path.transition()
    .duration(1000)
    .attrTween('d', function(d) {
        var interpolate = d3.interpolate({startAngle: 0, endAngle: 0}, d);
        return function(t) {
            return arc(interpolate(t));
        };
    });

Animasyon tamamlandıktan sonra legend yani grafik etiketlerini ekliyoruz.

setTimeout() fonksiyonu ile grafik etiketlerini 1 saniye sonra ekleme komutu veriyoruz. Böylelikle animasyon tamamlandığında etiketler eklenmiş oluyor.

Öncelikle text’i arc ın ortasına ekliyoruz, ardından text’e animasyon ekliyoruz. bu örnek text ‘ ler yüzdeler olmuş oluyor.

var text=svg.selectAll('text')
  .data(pie(dataset))
  .enter()
  .append("text")
  .transition()
  .duration(200)
  .attr("transform", function (d) {
      return "translate(" + arc.centroid(d) + ")";
  })
  .attr("dy", ".4em")
  .attr("text-anchor", "middle")
  .text(function(d){
      return d.data.percent+"%";
  })
  .style({
      fill:'#fff',
      'font-size':'10px'
  });

Legend‘ ı eklemek için etiket yazılarını ve bir de dikdörtgen oluşturuyoruz. Aşağıdaki kod ile legend içerisine önce group (g) ekliyoruz. Sonrasında group içerisine text (etiket yazıları) ve rect (dikdörtgen) ekliyoruz.

group ‘un pozisyonu dinamik olarak hesaplanıyor. Ayrıca data() fonksiyonunun içerisine color.domain() metodunu gönderiyoruz.

var legendRectSize=20;
var legendSpacing=7;
var legendHeight=legendRectSize+legendSpacing;
 
 
var legend=svg.selectAll('.legend')
  .data(color.domain())
  .enter()
  .append('g')
  .attr({
      class:'legend',
      transform:function(d,i){
          //Just a calculation for x and y position
          return 'translate(-35,' + ((i*legendHeight)-65) + ')';
      }
  });

legend.append('rect')
  .attr({
      width:legendRectSize,
      height:legendRectSize,
      rx:20,
      ry:20
  })
  .style({
      fill:color,
      stroke:color
  });
 
legend.append('text')
  .attr({
      x:30,
      y:15
  })
  .text(function(d){
      return d;
  }).style({
      fill:'#929DAF',
      'font-size':'14px'
  });

Aşağıda demoyu çalıştırabilirsiniz.

Kaynak Kodları aşağıda yer alıyor.

HTML

<div class="widget">
    <div class="header">Browser Market Share</div>
    <div id="chart" class="chart-container"></div>
</div>

JavaScript

var dataset = [
    { name: 'IE', percent: 39.10 },
    { name: 'Chrome', percent: 32.51 },
    { name: 'Safari', percent: 13.68 },
    { name: 'Firefox', percent: 8.71 },
    { name: 'Others', percent: 6.01 }
];
 
var pie=d3.layout.pie()
  .value(function(d){return d.percent})
  .sort(null)
  .padAngle(.03);
 
var w=300,h=300;
 
var outerRadius=w/2;
var innerRadius=100;
 
var color = d3.scale.category10();
 
var arc=d3.svg.arc()
  .outerRadius(outerRadius)
  .innerRadius(innerRadius);
 
var svg=d3.select("#chart")
  .append("svg")
  .attr({
      width:w,
      height:h,
      class:'shadow'
  }).append('g')
  .attr({
      transform:'translate('+w/2+','+h/2+')'
  });
var path=svg.selectAll('path')
  .data(pie(dataset))
  .enter()
  .append('path')
  .attr({
      d:arc,
      fill:function(d,i){
          return color(d.data.name);
      }
  });
 
path.transition()
  .duration(1000)
  .attrTween('d', function(d) {
      var interpolate = d3.interpolate({startAngle: 0, endAngle: 0}, d);
      return function(t) {
          return arc(interpolate(t));
      };
  });
 
 
var restOfTheData=function(){
    var text=svg.selectAll('text')
        .data(pie(dataset))
        .enter()
        .append("text")
        .transition()
        .duration(200)
        .attr("transform", function (d) {
            return "translate(" + arc.centroid(d) + ")";
        })
        .attr("dy", ".4em")
        .attr("text-anchor", "middle")
        .text(function(d){
            return d.data.percent+"%";
        })
        .style({
            fill:'#fff',
            'font-size':'10px'
        });
 
    var legendRectSize=20;
    var legendSpacing=7;
    var legendHeight=legendRectSize+legendSpacing;
 
 
    var legend=svg.selectAll('.legend')
        .data(color.domain())
        .enter()
        .append('g')
        .attr({
            class:'legend',
            transform:function(d,i){
                //Just a calculation for x & y position
                return 'translate(-35,' + ((i*legendHeight)-65) + ')';
            }
        });
    legend.append('rect')
        .attr({
            width:legendRectSize,
            height:legendRectSize,
            rx:20,
            ry:20
        })
        .style({
            fill:color,
            stroke:color
        });
 
    legend.append('text')
        .attr({
            x:30,
            y:15
        })
        .text(function(d){
            return d;
        }).style({
            fill:'#929DAF',
            'font-size':'14px'
        });
};
 
setTimeout(restOfTheData,1000);

CSS

body {
    background-color: #1B1F2A;
    width: 100%;
    font-family: 'Roboto', sans-serif;
    height: 100%;
}
 
.widget {
    margin: 0 auto;
    width:350px;
    margin-top:50px;
    background-color: #222D3A;
    border-radius: 5px;
    box-shadow: 0px 0px 1px 0px #06060d;
 
}
 
.header{
    background-color: #29384D;
    height:40px;
    color:#929DAF;
    text-align: center;
    line-height: 40px;
    border-top-left-radius: 7px;
    border-top-right-radius: 7px;
    font-weight: 400;
    font-size: 1.5em;
    text-shadow: 1px 1px #06060d;
}
 
.chart-container{
    padding:25px;
}
 
.shadow {
    -webkit-filter: drop-shadow( 0px 3px 3px rgba(0,0,0,.5) );
    filter: drop-shadow( 0px 3px 3px rgba(0,0,0,.5) );
}

Kaynak :

Yorum bırakın