tarafından

Raphael JavaScript Kütüphanesi

Kütüphane: Raphael JS
Versiyon: 1.0
Deneyim: Başlangıçdan Orta Seviyeye
Yaklaşık Uygulama Süresi: 30 Dakika

1. Hazırlık

İşe Raphael JavaScript Kütüphanesini indirerek başlayalım. Açılan pencerede, ekranın sağ üst köşesindeki sıkıştırılmış ve sıkıştırılmamış seçeneklerinden sıkıştırılmamış olanı indirin. Başlangıç olarak sıkıştırılmamış versiyonu indirmekle, dökümantasyondan daha net şekilde faydalanabilirsiniz.

raphael js download

İndirdiğimiz dosya ile birlikte basit bit HTML dosyası oluşturalım ve Raphael.js dosyasını kodlara dahil edelim. Ayriyetten “our_script.js” (dosya isimlerini orjinal halde geçiriyorum) adında bir boş dosya daha oluştup onuda sayfamıza dahil edelim. Örnek kodlarımızı bu boş sayfa içine yazp çalıştıracağız. HTML dosyasının gövdesi olarak “canvas_container” ID’sine sahip bir DIV oluşturup, en minimal olacak şekilde bir CSS şablonu atayalım. Çalışmalarımız bu DIV’in içinde oluşturulacaktır.

<html>
<head>
<title>Raphael Play</title>
// <![CDATA[
javascript" src="path/to/raphael.js">
// ]]>
// <![CDATA[
javascript" src="path/to/our_script.js">
// ]]>
<style type="text/css">
#canvas_container {
width: 500px;
border: 1px solid #aaa;
}
</style>
</head>
<body>
<div id="canvas_container"></div>
</body>
</html>

Önemli Not: Raphael JS kütüphanesinin 1.0, en güncel sürümü 7 Ekim 2009  tarihinde yayınlanmıştır. Eğer elinizde daha önceki sürüm bulunuyorsa, en güncel sürümü indirmenizde fayda var. Zira çizim araçlarında önemli değişiklikler olmuş durumda.

2. Kendi Çizim Alanımızı Oluşturalım

Raphael JS ile çizim yaparken bir çizim alanına ihtiyacımız olacak. Bu alanı sayfamızda “Raphael()” nesnesiyle oluşturduğumuz “paper” referansıyla kullanacağız. Bu çizim alanının genişlik ve yüksekliğini belirlememiz gerek, ayriyetten isteğe bağlı olarak bu alanın bağımsız (absolute) bir pozisyona mı sahip olacağını veya bir elemente bakılarak mı konumlandırılacağını da belirleyebiliriz.

var paper = new Raphael(x, y, width, height);
var paper = new Raphael(element, width, height);

Biz 2. seçenek olan, bir elementi örnek alma yöntemini kullanacağız. Hali hazırda sayfamızda yer alan “canvas_container” DIV’ini kullanarak 500 x 500 boyutlarında bir çizim alanı oluşturalım. (Aşağıdaki kodu “our_script.js” içerisine yazıyoruz.)

window.onload = function() {
var paper = new Raphael(document.getElementById('canvas_container'), 500, 500);
}

Bu şekilde; içinde çizim yapabileceğimiz bir alan ve bu alanı referans eden “paper” adında bir değişkenimiz oldu.

3. Yerleşik Şekiller

Şimdi, alanımıza birkaç şekil çizdirelim. Alanımızın orijin (origin) noktası, yani başlangıç noktası, sol üst köşedir. Yani çizim yaparken belirleyeceğimiz her X ve Y koordinatı, sol üst köşeye göre çizilir.
İlk olarak daire çizimi ile başlayalım:

window.onload = function() {
var paper = new Raphael(document.getElementById('canvas_container'), 500, 500);
var circle = paper.circle(100, 100, 80);
}

Bu kod ekrana, yarıçapı 80 piksel olan ve merkezi X ve Y koordinatlarında 100. piksellere gelen bir daire çizer ve bu daireyi “circle” değişkenine referans eder. Yaptığmız çizimleri illa ki bir değişkene referans vermemiz de gerekmez. Doğrudan çizim fonksiyonunu çağırarak da ekrana çizim yaptırabilirsiniz.

for(var i = 0; i < 5; i+=1) {
var multiplier = i*5;
paper.circle(250 + (2*multiplier), 100 + multiplier, 50 - multiplier);
}

Sırada kare çizimi var: ekrana kare çizdirmek için “rect()”  fonksiyou kullanılır. Sırasıyla, X ve Y koordinatlarını ve karenin genişlik-yükseklik değerlerini parametre alır.

var rectangle = paper.rect(200, 200, 250, 100);

Son olarak elips çizimi: dairenin parametrelerine benzer olarak; X ve Y koordinatlarının, yarı çapın veya dikey-yatay yarıçapların belirtilmesi gereklidir.

var ellipse = paper.ellipse(200, 400, 100, 50);

Bu kod ekrana; X=200, Y=400 koordinatlarına yatayda yarı çapı 100, dikeyde yarıçapı 50 olan bir elips çizer.

Bu 3 çizim tekniğin uyguladıkdan sonra, “our_script.js” dosyamız şu şekilde olmalı.

window.onload = function() {
var paper = new Raphael(document.getElementById('canvas_container'), 500, 500);
var circle = paper.circle(100, 100, 80);
for(var i = 0; i < 5; i+=1) {
var multiplier = i*5;
paper.circle(250 + (2*multiplier), 100 + multiplier, 50 - multiplier)
}
var rectangle = paper.rect(200, 200, 250, 100);
var ellipse = paper.ellipse(200, 400, 100, 50);
}

Eğer “index.html” dosyasını, tarayıcınızda açarsanız görüntü aşağıdakine benzer bir şekilde olacaktır.

4. Çizim Yolları

Tümleşik şekilleri kullanmak çoğu zaman kullanışlı fakat esas serbest çizim rahatlığını sağlayan şey “yollar” (paths). Bir yol çizerken kalem veya fırçanızın ekrana iz bıraktğını hayal edersek; Çizim alanımızı ilk oluşturduğumuzda kalem/fırça varsayılan olarak ekranın sol üst köşesine konumlandırılır. Yapmamız gereken ilk şey kalemimizi çizim yapacağımız alana konumlandırmak.
Örnek olarak kalemimizi, XY=0 noktasından X=250, Y=250 noktasına taşıyalım:

Bu hareket “yol bildirimi” (path string) olarak adlandırılmış.

Yol bildirimi, birden fazla metin formatında değerin, sıralı bir halde birbiri ardına yazılarak çalıştırılmasıyla yapılır. Örneğimizde kalemi X=250, Y=250’ye taşıma istiyoruz, öyleyse:

"M 250 250"

“M” harfi, “Move” yani taşımak anlamına gelir, bizim kodumuzda “Çizim yapma, sadece yerini değiştir” anlamında kullanılıyor. Sonraki “250 250” ise sırasıyla X ve Y koordinatlarıdır.

Şimdi, kalemimiz istediğmiz koordinatlarda olduğuna göre bir çizgi çalışması yapalım. Bunun için “l” (Küçük L) yani Line komutunu kullanıyoruz, ve her zaman ki gibi XY koordinatlarını veriyoruz.

"M 250 250 l 0 -50"

Bu kod sadece Y koordinatında yukarıya doğru 50 piksellik çizgi çizer. Biraz daha komplike olması açısından aşağıdaki satırı da yazabiliriz. Tetris oyunundan bir nesnenin çizimi.

"M 250 250 l 0 -50 l -50 0 l 0 -50 l -50 0 l 0 50 l -50 0 l 0 50 z"

Satırın sonundaki “z” çizim işleminin bittiğini gösterir. Son çizgi nerede olursa olsun “z“‘den sonra, çizgi “M” ile belirttiğimiz noktaya tamamlanır.

Bu yol bildirimi satırlarını HTML sayfasında çalıştırmak için ise, Raphel JS’nin “path()” fonksiyonunu kullanırız. Örneği çalıştırmak için “our_script.js” dosyamızın aşağıdaki gibi olması lazım.

window.onload = function() {
var paper = new Raphael(document.getElementById('canvas_container'), 500, 500);
var tetronimo = paper.path("M 250 250 l 0 -50 l -50 0 l 0 -50 l -50 0 l 0 50 l -50 0 l 0 50 z");
}

Kodları çalıştırdığınızda sayfanın görüntüsü aşağıdaki gibi olmalı.

Path() fonksyionu ve yol bildirimi (path string) yönteminin kullanımı, Curve ve Arc (Kavis ve Yay) komutları kullanılarak daha da karmaşıklaştırılabilir. Bu tür komutların devamını ve açıklamalarını SVG Path Specification (Yol Tanımları) sayfasında bulabilirsiniz.

5. Nitelikler ile Stil Verme

Yukarıda çizdiğimiz tetris parçası, ilk çizim için güzel görünebilir ama hiç estetik durmuyor mu?. Bunun çözümü ise nitelikler yardımı ile çizime stil vermekten geçiyor.
Attr() fonksiyonu, nesnenin niteliklerini “başlık-değer” şeklinde ele alıp, bu değerleri değiştirebilmemizi sağlar. Yukarıdaki çizimimizi “tetronimo” adlı bir değişkende tutuyorduk, bu demektir ki, biz bu değişkene dolayısıyla çizime attr() ile yeni değerler verebiliriz. Attr() fonksiyonunu Path() ile birlikte kullanıp, yol bildirimi yaptığımız satırın sonuna ekliyoruz.

window.onload = function() {
var paper = new Raphael(document.getElementById('canvas_container'), 500, 500);
var tetronimo = paper.path("M 250 250 l 0 -50 l -50 0 l 0 -50 l -50 0 l 0 50 l -50 0 l 0 50 z");tetronimo.attr({fill: '#9cf', stroke: '#ddd', 'stroke-width': 5});
}

Sonuç:

Daha anlaşılır bir kod bloğu:

window.onload = function() {
var paper = new Raphael(document.getElementById('canvas_container'), 500, 500);
var tetronimo = paper.path("M 250 250 l 0 -50 l -50 0 l 0 -50 l -50 0 l 0 50 l -50 0 l 0 50 z");tetronimo.attr(
{
gradient: '90-#526c7a-#64a0c1',
stroke: '#3b4449',
'stroke-width': 10,
'stroke-linejoin': 'round',
rotation: -90
}
);
}

Raphael JS’nin kendi dökümanları arasında Attr() fonksiyonu, oldukça geniş olarak anlatılmış. Nesnelerin diğer nitelikleriyle oynayarak daha farklı çalışmalar yapılabilir.

6. Animasyonlar

Animate()” fonksiyonu, Raphael’in en güzel özelliklerinden bir tanesi. Bize jQoery’nin esque kütüphanesini (bir animasyon kütüphanesi) kullanarak nesnelerin nitelikleri ile animasyonlar oluşturmamızı sağlıyor ve istersek Easing denilen, animasyonun hızını, yönünü vb. değerleri değiştirmemizi sağlayan yardımcı yöntemleride kullanabiliriz. (Nesneler diyorum çünkü bahsi geçen nesneler doğdurdan çizimlerimize bağlı).
Örnek olarak yine yukarıda çizdiğimiz “tetronimo” nesnesini kullanalım ve “rotation” yani rotasyon niteliğini değiştirerek 360 derece dönmesini sağlayalım. “our_script.js” dsoyasına yazacağımız kod:

window.onload = function() {
var paper = new Raphael(document.getElementById('canvas_container'), 500, 500);
var tetronimo = paper.path("M 250 250 l 0 -50 l -50 0 l 0 -50 l -50 0 l 0 50 l -50 0 l 0 50 z");
tetronimo.attr(
{
gradient: '90-#526c7a-#64a0c1',
stroke: '#3b4449',
'stroke-width': 10,
'stroke-linejoin': 'round',
rotation: -90
}
);tetronimo.animate({rotation: 360}, 2000, 'bounce');
}

Koddaki 2000 değeri, animasyonun 2000 milisaniye(2 saniye)’de tamamlanacağını gösterir. Son olarak “bounce” ile de animasyonun nasıl bir ek-efektle tamamlanacağını belirtiyoruz.
Yukarıdaki kodun canlı bir örneğini görmek için buraya tıklayın.

Ayriyetten animasyonumuz bittikden sonra çalıştırılmak üzere bir fonksiyon belirleyebiliriz, buna “callback” denir.
Örnek olarak yukarıdaki animasyonumuz çalıştıkdan sonra “tetronimo“‘yu eski haline geri getiren bir “callback” fonksiyonu tanımlayalım:

tetronimo.animate({rotation: 360, 'stroke-width': 1}, 2000, 'bounce', function() {
/* callback after original animation finishes */
this.animate({
rotation: -90,
stroke: '#3b4449',
'stroke-width': 10
}, 1000);
});

Buradaki “this” komutu, o an animasyonun içinde bulunan “tetronimo” nesnesini gösterir.
Canlı örnek burada.

Animasyonun Yönü ve Tipi

Raphael, Flash’daki gibi; çizdiğiniz şekilleri eğip bükmek gibi olayların aynısı olmasada bezner türde olayları yapabilir (shape tweening). Bu yöntemi “animate()”‘in içinde “path()” kullanarak gerçekleştiriyoruz. Bu sefer ki örneğimizde yine tetris’den bir örnek olarak “Z” şeklinde bir çizim yapıp onun üzerinde çalışacağız.
İlk önce şeklimizi çizelim:

"M 250 250 l 0 -50 l -50 0 l 0 -50 l -100 0 l 0 50 l 50 0 l 0 50 z"

Aşağıdakine benzer bir görüntü olması lazım:

Şimdi bu minimal düzeyde stillendirilmiş nesnemizi kullanarak “animate()” fonksiyonunu çağıracağız ve parametre olarak yeni bir “path()” nesnesi göndereceğiz.

tetronimo.attr(
{
stroke: 'none',
fill: 'blue'
}
);tetronimo.animate({
path: "M 250 250 l 0 -50 l -50 0 l 0 -50 l -100 0 l 0 50 l 50 0 l 0 50 z"
}, 5000, 'elastic');

Kodu çalıştırıp baktğınızda, orjinal şeklin eğilip bükülerek vermiş olduğumuz yeni path nesnesine dönüştüğünü görürsünüz.
Canlı örnek burada.

7. DOM’a Erişebilirlik

Eğer HTML sayfamızdaki DOM elementlerine erişmek istiyorsak, bunu Raphael’in “Node” özelliği ile kolaylıkla yapabiliriz. bunu kullanarak çizimlerimize kullanıcı ile etkileşim geçecek olay fonksiyonları yazabiliriz.
Örnek için ilk önce bir daire çizelim:

window.onload = function() {
var paper = new Raphael(document.getElementById('canvas_container'), 500, 500);var circ = paper.circle(250, 250, 40);
circ.attr({fill: '#000', stroke: 'none'});
}

Şimdi, dairenin ortasına “Raphael Js” yazdıracak fonksiyonu hazırlayalım:

var text = paper.text(250, 250, 'Raphael JS')
text.attr({opacity: 0, 'font-size': 12}).toBack();

Opacity=0” yani varsayılan olarak sayfa ilk açıldığında, yazımız ekranda görünmeyecektir. Bu satırın hemen arkasından gelen “.toBack()” komutu ekrana yazdırığmız yazıyı, çizim alanındaki her nesnenin arkasına itecektir. Yani bu örnekde dairenin üzerine yazdırdığımız yazı aslında .toBack ile dairenin arkasına yerleştirilmiştir. Benzer şekilde “.toFront()” komutuda nesneyi diğer nesnelerin önüne getirmekte kullanılır.
Çizmiş olduğumuz dairede “MouseOver” olayını yakalamak için “node” özelliğini kullanarak bir fonksiyon yazalım ve fare’nin daire üzerine geldiğinde el işareti olmasını sağlayalım:

circ.node.onmouseover = function() {
this.style.cursor = 'pointer';
}

Kodumuzun HTML tarafındaki karşılığı aşağıdaki gibidir:

<circle cx="250.5" cy="250.5" r="40" fill="#000000" stroke="none" style="fill: #000000; stroke: none; cursor: pointer">
</circle>

Son olarak daire nesnemize fare ile tıklandığında çalışacak bir kod bloğu yazalım:

circ.node.onclick = function() {
text.animate({opacity: 1}, 2000);
circ.animate({opacity: 0}, 2000, function() {
this.remove();
});
}

Kodda da görüldüğü üzere, daireye tıkladığımızda ilk önce görünmez olan yazımız 2 saniye içerisinde görünür olacak ve hemen ardından daire 2 saniye içinde görünmez olacaktır. Tanımladığımız callback fonksiyonu sayesine 2 saniye sonunda görünmez olan daire, “this.remove()” kodu ile sayfadan tamamen silinir.
Canlı örnek burada.

8. Örnek Uygulama: Beğeni Ölçme Bileşeni

Buraya kadar ki öğrendiklerimizi, tek bir uygulamada hep birlikte uygulamak adına ufak bir beğendimbeğenmedim bileşeni yapalım:
Yapacağımız çalışmanın sonucu buradaki gibi olacak.

Başlangıç için kod bloğumuz aşağıdaki gibidir:

window.onload = function() {
var paper = new Raphael(document.getElementById('canvas_container'), 500, 500);
var circ = paper.circle(250, 250, 20).attr({fill: '#000'});
var mood_text = paper.text(250, 250, 'My\nMood').attr({fill: '#fff'});
}

bu kod yarıçapı 20 piksel ve XY koordinatları 250 olan siyah bir daire çizer. Daha sonra içine “My \nMood” yazısı yazılır (My Mood’un kelime anlamı “Benim düşüncem”‘e denk gelmektedir). Kodların arasındaki “\n” ise özel karakterdir ve bir alt satıra geçmek anlamına gelir. Yani “My”‘dan sonra bir alt satıra geçilir ve “Mood” yazılır.
Şimdi, sıra geldi değerlendirme bilgilerini hazırlamaya; Kullanıcının seçebileceği her seçeneğe karşılık bir metin ve renk hazırlayalım.

moods = ['Çöplük', 'Güzel Değil', 'Orta', 'İyi Sayılır', 'Harika'];
colors = ['#cc0000', '#a97e22', '#9f9136', '#7c9a2d', '#3a9a2d']; //varsayılan olarak 1. seçeneği aktif yap.
var my_mood = 1;

Şimdi kullanıcının seçtiği değere göre yukarıdaki dizilerden, uygun olanları seçip ekranda gösterecek fonksiyonu yazalım:

function show_mood() {
for(var i = 0; i < my_mood; i+=1) {
(function(i) {
setTimeout(function() {
paper.circle(250, 250, 20).attr({
stroke: 'none',
fill: colors[my_mood - 1]
}).animate({translation: '0 ' + (-42 * (i+1))}, 2000, 'bounce').toBack();
}, 50*i);
})(i);
}
paper.text(250, 300, moods[my_mood - 1]).attr({fill: colors[my_mood - 1]});
mood_text.node.onclick = function() {
return false;
}
circ.node.onclick = function() {
return false;
}
}

“show_mood()” fonksiyonu içerisinde, kullanıcının seçtiği değeri her 50*i milisaniyede çizime dönüştüren anonim bir fonksiyon var. Her yeni daire oluşturulduğunda fonksiyon kendini çalıştırarak en son çizilen dairenin hemen üstüne yeni bir daire çiziyor ve bunu seçilen değer kadar tekrarlıyor. Her daire 2 saniye içerisinde bir öncekinin Y ekseninde üzerine ve görüntü olarak arkasına yerleştiriliyor.
son olarak ekrana çizilen dairelerin ve yazıların click olayları kaldırılarak her tıklamada yukarıdaki kodun tekrar çalışmasının önüne geçiliyor.

Son olarak fonksiyonumuzu sayfaya entegre edelim, aşağıdaki kod ile yukarıda yazmış olduğumuz fonksiyonu ekrana ilk çizdirdiğimiz siyah daire ve içindeki yazıya bağlayalım:

circ.node.onclick = show_mood;
mood_text.node.onclick = show_mood;

Bu örneğimizi modifiye ederek ekolayzır benzeri bir bileşende yapabilirsiniz.

Kapanış

Umuyorum ki şimdiden Raphael JS’yi ve birbirinden ilginç çizim araçlarını kurcalamaya biraz daha meraklısınız.
Hepinize iyi günler, iyi çalışmalar.

Kurtman Çelik
kurtman.celik@hotmail.com
https://kurtmancelik.wordpress.com/
Kaynak: http://net.tutsplus.com/tutorials/javascript-ajax/an-introduction-to-the-raphael-js-library/
(Bu yazıyı Web programlama ile ilgili olmasından çok, ingilizce pratiği yapmak için çevirdim.)

Yorum bırakın