Yazılım.
CevapSitesi.com Beta!
Çözüm Noktası
Facebook, Twitter, Google+ veya e-posta ile paylaşın.
| Sorular | Makaleler | Üyeler | Etiketler  | İletişim
Soru sormak ya da cevap vermek için;
giriş yapın veya üye olun.

Sosyal medya hesaplarınızla da giriş yapabilirsiniz.

Yazılım Makaleleri

0

Canvas ile dönüşüm işlemleri 1: Tuvali kaydırma ve döndürme

Canvas çizimlerinde çizimleri döndürmek, kaydırmak, eğmek ve bükmek için birkaç yöntem bulunmaktadır. Burada döndürme işlemi açıklanacaktır.

Döndürme işlemi için rotate  yöntemi kullanılmaktadır. rotate yöntemi tuval kapsamını (örneklerimizde ctx ) sol üst köşeden belirtilen açıyla döndürür. Yöntem, tuvali (Canvas) değil kapsamı döndürür. Biz şekli kapsam düzmüş gibi çizeriz. rotate yöntemi, bizim koordinatlarını düz olarak verdiğimiz çizimleri dönmüş olarak çizer.

Bu işlemi iyi anlayabilmek için tuval ve kapsam hakkında şunu bilmemiz gerekir.

Kapsam, (örneklerde getContext("2d")  ile elde ettiğimiz nesne), tuvalin (Canvas etiketi) içine çizim yapmak için kullanılan bir nesnedir. Çizimleri kapsam nesnesini kullanarak, kapsam üzerine çizeriz, Canvas etiketine değil.

Tuval ile kapsamın ilişkisini resim programlarında kullanılan maskeleme tekniğindeki maskeleyen ve maskelenen ögeler arasındaki ilişkiye benzetebiliriz.

Bilindiği gibi maskeleme tekniğinde üstte pencere olarak kullanılan bir şekil ve altta da bir resim vardır. İkisi birbirinden bağımsız hareket ettirilebilir. Sonuç olarak da üstteki şeklin sınırları dahilinde alttaki resim görüntülenir. Alttaki resim kaydırılarak veya döndürerek farklı görüntüler elde edilebilir.

Alttaki resimde maskeleme tekniği kullanılmıştır.


Burada tuvali üstteki maskeleyen şekil (yıldız) olarak kabul edebiliriz. Kapsam ise alttaki fotoğrafa benzetilebilir. Kapsam tuvalden bağımsız olarak hareket ettirilebilir, döndürülebilir veya bükülebilir. Sonuç olarak kapsamın tuvalin sınırlarında kalan kısmını görürüz.

Normalde tuval ile kapsam aynı doğrultuda düz olarak durmaktadır. rotate yöntemi kapsamı döndürür. Döndürme işleminden sonra yapılan çizimler verilen açıya göre döndürülmüş olarak çizilir.

Alttaki resim tuval ve kapsamın normal durumunu ve kapsam 45 derece döndürüldüğündeki durumlarını göstermektedir.

Normal durum:

Kapsam 45 derece saat yönüne döndürüldüğündeki durum:


Sonuçta elde edilen görüntü şöyle olacaktır:

rotate yönteminin kullanımı şöyledir:

rotate(radyan cinsinden açı);
rotate yönteminde açı derece olarak değil, radyan cinsinden verilir. Radyan (rad), bir dairenin yarıçapı uzunluğundaki yay parçasının gördüğü açı miktarıdır. Bir dairede 2π radyan vardır (yaklaşık 6,28 rad). Buna göre 180 derece = π rad, 90 derece = π/2 rad, 45 derece = π/4 rad eder.

Radyan ve çizimlerde kullanımı hakkında daha ayrıntılı bilgi Canvas ile daire, çember, yay ve dilimler çizmek başlıklı makalemizde daha ayrıntılı olarak açıklanmaktadır.

Şimdi üstteki şekli oluşturan örneğimizi verelim:
<canvas id="cnTuval" width="200" height="200" style="border:solid 1px red">
    Tarayıcınız HTML5 desteklemiyor.
</canvas><br />
<input type="button" value="Çiz" onclick="ciz()" />

<script>

    function ciz() {

        var tuval = document.getElementById("cnTuval");
        var ctx = tuval.getContext("2d");

        ctx.lineWidth = 6;

        // Kapsamı 45 derece döndür.
        ctx.rotate(Math.PI / 4);

        // Kapsam düzmüş gibi normal şekilde çizimleri yap.
        // Çizimler kapsama 45 derece döndürülmüş olarak yapılacaktır.
        ctx.beginPath();
        ctx.moveTo(3, 100);
        ctx.lineTo(3, 3);
        ctx.lineTo(100, 3);
        ctx.stroke();
        ctx.fillRect(20, 20, 40, 40);


    }

</script>  

Tabiki şekli nasıl tuval içinde döndüreceğiz diye bir soru akla geliyor.

Yukarıda da belirtildiği ve şekilden de görüldüğü gibi döndürme işlemi kapsamın x=0, y=0 konumundan yapılmaktadır. Yani döndürme merkezi burasıdır.

Eğer bu nokta şekil döndüğünde şeklin tamamı görünecek başka bir yere taşınırsa şeklin tamamı döndürülmüş bir şekilde görüntülenebilir.

Döndürme noktasını (x=0, y=0) kaydırmak için translate yöntemi kullanılır.

translate yöntemi kapsamı belirtilen yatay ve dikey miktar kadar sağa, sola, yukarı ve aşağı kaydırır. Eğer kapsamın x=0, y=0 noktasını tuvalin ortasına kaydırır ve daha sonra rotate ile döndürürsek tuvalin ortasında dönmüş bir şekil elde ederiz.

Şimdi bir yelkovan şeklini tuvalin ortasında 45 derece dönmüş olarak görüntüleyelim.

Öncelikle şekildeki gibi, yelkovanın piminin (dönme noktasının) x=0, y=0 konumuna denk geldiği bir çizim oluşturalım.

Tabiki bu durumda köşede küçük bir üçgen olan bir görüntü elde edeceğiz.

Şimdi x=0, y=0 noktasının tuvalin ortasına kaydırıldığını düşünürsek (translate ile yapacağız) görüntü ve koordinat eksenleri şu şekilde olacaktır.


Son olarak kapsamın 45 derece döndürüldüğünü düşünürsek alttaki şekildeki gibi eksenler konumlanacak ve görüntü döndürülmüş olacaktır.



İşte bu işlemi yapan örnek:
<canvas id="cnTuval" width="200" height="200" style="border:solid 1px red">
    Tarayıcınız HTML5 desteklemiyor.
</canvas><br />
<input type="button" value="Çiz" onclick="ciz()" />

<script>

    function ciz() {

        var tuval = document.getElementById("cnTuval");
        var ctx = tuval.getContext("2d");

        // Kapsamı 100 piksel sağa, 100 piksel aşağı kaydır.
        ctx.translate(100, 100);

        // Kapsamı 45 derece döndür.
        ctx.rotate(Math.PI / 4);

        // Yelkovanı pim yeri (dönme noktası) x=0, y=0 konumuna
        // denk gelecek şekilde çiz.
        ctx.beginPath();
        ctx.moveTo(0, 7);
        ctx.lineTo(-7, 0);
        ctx.lineTo(0, -50);
        ctx.lineTo(7, 0);
        ctx.closePath();
        ctx.fill();

    }

</script>

Çıktı şöyle olacaktır:

Daha önce de söylemiştik ama yine hatırlatalım, çizimleri dönmeyi göz önüne almadan yapıyoruz.

Bir de şunu ekleyelim. translate  ve rotate işlemlerinden sonra önceki veya varsayılan duruma dönmek için en kolay yol save ve restore yöntemleridir. Yani kaydırılmış ve döndürülmüş kapsamı save ve restore kullanarak kolayca önceki haline getirebiliriz. Bunları tekrar eski durumuna getirmek için ayrı ayrı kodlar yazmayın.

Son olarak bu yelkovanı bir zamanlayıcı kullanarak döndüren şu örneği verelim.
<canvas id="cnTuval" width="200" height="200" style="border:solid 1px red">
    Tarayıcınız HTML5 desteklemiyor.
</canvas><br />
<input type="button" value="Çiz" onclick="baslat()" />

<script>

    var zamanlayici;

    var aci = 0;
    var tuval = document.getElementById("cnTuval");
    var ctx = tuval.getContext("2d");

    function ciz() {

        // Önceki çizimi temizle.
        ctx.clearRect(0, 0, 200, 200);

        // Kapsamın kaymamış ve dönmemiş durumunu sakla.
        ctx.save();

        // Açıyı 22.5 derece arttır. Saat yönünün tersine çevirmek isterseniz
        // açı değerini negatif verin.

        aci += Math.PI / 8;

        // Kapsamı 100 piksel sağa, 100 piksel aşağı kaydır.
        ctx.translate(100, 100);

        // Kapsamı açı kadar döndür.
        ctx.rotate(aci);

        // Yelkovanı pim yeri (dönme noktası) x=0, y=0 konumuna
        // denk gelecek şekilde çiz.
        ctx.beginPath();
        ctx.moveTo(0, 7);
        ctx.lineTo(-7, 0);
        ctx.lineTo(0, -50);
        ctx.lineTo(7, 0);
        ctx.closePath();
        ctx.fill();

        // Kapsamı kaydırılmadan ve döndürülmeden önceki durumuna getir.
        ctx.restore();

    }

    function baslat() {

        // Tuş tıklandığında ikinci bir zamanlayıcı kurulmasın diye
        // varsa önceki zamanlayıcıyı durdur (Daha önce zamanlayıcı
	// kurulmadıysa hiç bir işlem yapılmaz, hataya da neden olmaz).
        clearInterval(zamanlayici);

        // 100 milisaniyede bir ciz fonksiyonunu
        // çağıran bir zamanlayıcı kur.
        zamanlayici = setInterval(ciz, 100);

    }

</script>   

Örnekte dönme açısı her seferinden yeniden hesaplanmaktadır. Saat gibi bir şey yapmak isterseniz saniye kolu ve akrep de çizeceğinizden bu şekilde yapmak daha uygun. Ancak eğer sadece dönüş istiyorsanız bunun yerine hiç save ve restore kullanmadan açıyı her seferinde aynı miktar olarak verebilirsiniz. Bu şekilde verildiğinde kapsam bir önceki dönüş açısına göre verilen açı kadar daha döndürüleceğinden sürekli bir dönüş görüntülersiniz ve ekleme yapmanız da gerekmez.

Bu makalenin konusu değil ama aslına bakarsanız bu işlem daha derli toplu bir JavaScript kodlama ile aşağıdaki gibi yazılabilir. Bu yazım şekli (Closure kullanmak) JavaScript'de önemli bir kolaylıktır ve çokça kullanılır. Closure konusunu bilmiyorsanız JavaScript Fonksiyonları: Kapsanımlar - Closures ve Geri Çağırma Fonksiyonları - Callback yazımı okuyabilirsiniz.
<canvas id="cnTuval" width="200" height="200" style="border:solid 1px red">
    Tarayıcınız HTML5 desteklemiyor.
</canvas><br />
<input type="button" value="Çiz" onclick="ciz()" />

<script>

    var zamanlayici;


    function ciz() {

        clearInterval(zamanlayici);

        var aci = 0;

        zamanlayici = setInterval(function () {

            var tuval = document.getElementById("cnTuval");
            var ctx = tuval.getContext("2d");

            ctx.clearRect(0, 0, 200, 200);

            ctx.save();

            aci += Math.PI / 8;

            ctx.translate(100, 100);

            ctx.rotate(aci);

            ctx.beginPath();
            ctx.moveTo(0, 7);
            ctx.lineTo(-7, 0);
            ctx.lineTo(0, -50);
            ctx.lineTo(7, 0);
            ctx.closePath();
            ctx.fill();

            ctx.restore();

        }, 100);

    }

</script>

Bu da örneğin çalışan hali.




Artık saati de siz yaparsınız.

Bu kadar. Lütfen eksik görürseniz bildirin.



İlgili Makaleler



Yazan: 25.04.16 14:33
canora
101,387p 4ü