Aşağıda paylaşacağım linkte yapacağımız uygulamanın demosunu görüyor olacaksınız. Yazımızda bu çalışmanın kodlamasının nasıl olması gerektiğini öğretirken aynı zamanda github kodları ile son ürünü de sizinle paylaşmış olacağız.
Demo : GeoJSON and IndexedDB Usage
Github Repository : indexeddb-geojson
Öğreneceğiniz Konular
- GeoJSON Dosyası Okuma
- Openlayers ile Haritaya GeoJSON Ekleme
- Openlayers ile Vektörel Çizim Yapma
- IndexedDB oluşturma
- IndexedDB’de Tablo Oluşturma
- IndexedDB Tablolarına Kayıt Ekleme, Silme, Değiştirme
Eğer hazırsanız işte başlıyoruz!…
GeoJSON bünyesinde geometri ve öznitelik bilgileri barındıran bir JSON yapısıdır. Bu dosya yapısı okunabilir ve basit bir text editör ile düzenlenebilir durumdadır. Günümüzde bu kadar popüler olmasının sebebi ise JSON veri yapısının javascript ile birlikte rahat bir şekilde kullanılması, nesnel yönelimli yazılımların kullanımına benzerlik göstermesi ve geliştirilen API’lerin XML yerine json kullanıldığında daha hızlı başarı elde etmesidir.
IndexedDB ise web tarayıcılarda veritabanı niteliğinde çalışan bir HTML5 API ‘dir. Kullanıma yeni başlayanlar için kafa karıştırıcı olsada kullanıcılarına 50mb kadar bir bellek sunması web tarayıcı içerisinde yapılan işlemlerin ürününü kayıt altında tutmak adına CBS yazılımları açısından önemli bir özellik haline gelmiştir.
Yapacağımız örnekte ise basit bir web sayfasında haritaya GeoJSON dosyası ekleyip silmeyi, farklı tiplerde çizim yapıp bu çizimi silmeyi ve bu işlemleri yaparken bir yandan da indexedDB de kayıt altında tutmayı öğreneceğiz. Anlatacağımız örnek basit bir kullanım şekli olup kendi çalışmalarınızda daha kompleks hale getirebilirsiniz.
GISLayer ekibi ile geliştirdiğimiz projelerde bizler kullanıcılarımızın yapmış olduğu geometrik çizim, düzenleme, silme ve eklenmiş mekansal dosyaları korumak adına kendi tarayıcıları üzerinde kayıt altına alıyoruz. Şimdi ise bu kısmı sizlerle paylaşmak istedik.
Adım 1 : Örnek GeoJSON Dosyası Oluşturma
Kullanacağımız GeoJSON dosyasını oluşturalım. Bu işlem için elinizde bir dosya varsa kullanabilirsiniz. Yoksa editor.gislayer.com adresinden öncelikle yeni bir katman oluşturun. Nasıl yapacağınızı öğrenmek istiyorsanız aşağıda ki sırayı takip ederek hızlı bir şekilde dosyanızı oluşturabilirsiniz
- Yeni Bir Katman Oluşturma
- Çizim Yapma
- GeoJSON Dosyasını İndirme veya Katman Kutusu kullanarak indirebilirsiniz.
Adım 2 : index.html dosyasının oluşturulması
Yazacağımız kodu inceleyebilmek için bir HTML sayfasına ihtiyaç duymaktayız. İşlemleri harita üzerinde gösterebilmek için en hızlı şekilde yönetebileceğimiz Openlayers harita kütühanesini kullanacağız. Siz alterlatif olarak leafletjs, mapbox veya diğer harita kütüphanelerini kullanabilirsiniz. Ancak GeoJSON ile çalışabilir olması önemlidir. Hazırladığımız bu örnek çalışma Openlayers için geliştirilmiştir.
Öncelikle üzerinde çalışacağınız boş bir klasörünüz olsun ve bu klasör içerisinde index.html sayfası oluşturun.
Bu dosyanın head etiketi içerisinde Openlayers’in css ve js kaynak kodlarını direkt olarak kendi sitelerinde sunmuş oldukları kaynaktan ekledik. Kullanacağımız butonlar ve konumları için style tanımladık. body etiketleri içerisinde haritayı yayınlamak için map id bilgisine sahip div elementi ekledik ve bu eğitimin asıl amacını oluşturan 6 adet buton ekleyerek index dosyasında daha fazla bir değişikliğe ihtiyaç duymadan kullanacağız.
- Add GeoJSON : Haritaya GeoJSON dosyası eklemek için
- Remove GeoJSON : Eklenmiş GeoJSON dosyasını silmek için
- Polygon : Harita üzerinde yeni bir kapalı alan çizmek için
- Line : Harita üzerinde yeni bir çizgi çizmek için
- Point : Harita üzerinde yeni bir nokta çizmek için
- Clear All : Yapılan çizimleri silmek için oluşturulmuştur.
Sayfanın en altında tanımlanacak şekilde map.js ve indexedDB.js dosyalarını proje klasörünüz içerisinde oluşturup daha sonra kullanmak için bekletebilirsiniz. İlerleyen adımlarda hepsini öğrenerek ekleyeceğiz.
Adım 3 : map.js Harita Fonksiyonlarını Hazırlama
Şimdi proje klasöründe oluşturduğumuz map.js dosyasının ilk halini oluşturalım. Bu dosyada harita fonksiyonlarımız olacak ve belirli bir sırayı takip ederek tamamlayacağız. Bu dosyada aşağıdaki listede yer alan işlemleri sırası ile yapacağız. Bu sırayı takip ederken paylaşılan kodları sırası ile map.js dosyanıza eklemenız gerekmektedir.
- Altlık haritayı ekleme
- Kullanacağımız vektör katmanları ekleme
- GeoJSON verilerini vektör veriye çevirme
- Vektör verileri GeoJSON’a çevirme
- Vektör verileri katmana ekleme
- Katmana zoom yapma
- Çizim fonksiyonlarını oluşturma
- Bir GeoJSON dosyasını okuma
- Okunan GeoJSON dosyasını Silme
- Tüm geometrileri silme
3.1 Altlık Haritayı Ekleme
Kullanacağımız altlık harita XYZ tile olarak nitelendirilmektedir ve eğer kendinize ait bir XYZ tile servisiniz var ise burada ki URL adresini değiştirerek yayınlayabilir, zoom seviyesi ve merkez enlem, boylamı tanımlayabilirsiniz. Aşağıda ki kodları eklemeniz durumunda ekran görüntüsünü takip ederek kendi durumunuz ile kontrol edebilirsiniz.
3.2 Kullanacağımız Vektör Katmanları Eklemek
Proje kapsamında iki vektör katman kullanacağız, birincisi haritaya eklenen GeoJSON dosyaları için olacak bir diğeri ise haritada yapacağımız çizimleri kayıt altında tutacak. Bu katmanların görünümünü style içerisinde yer alan bilgilere göre kendiniz belirleyebilirsiniz. Bu kodları ekledikten sonra herhangi bir ekran görünümü değişmez, boş iki katmanı haritanıza eklemiş olursunuz.
3.3 GeoJSON Verilerini Vektör Verilere Çevirmek
Dışarıdan haritamıza yüklemek istediğimiz GeoJSON verilerini doğrudan kullanamayız. Bu nedenle Openlayers’in hoşuna gidecek hale getirmeliyiz. Yani vektör verilere çevirmeliyiz. Bunun için ol.format.GeoJSON metodundan yararlanacağız. Gelecek olan GeoJSON verilerinin EPSG:4326 projeksiyon sisteminde olacağını varsayarak Openlayers’ın default ayarlarında kabul ettiği EPSG:3857 projeksiyon sistemine çeviriyoruz.
3.4 Vektör Verileri GeoJSON’a Çevirme
Herşey çok güzel gidiyor. Bu noktadan sonra da indexedDB nin hoşuna gidecek şekilde çalışmamız gerekiyor. Çünkü Openlayers katmanlarından elde edeceğimiz vektörleri doğrudan indexedDB içerisine atamayız. Onları kullanabileceğimiz duruma getirmemiz gerekiyor. Bu da bizim için GeoJSON’a çevirmek oluyor. Bunun için ol.format.GeoJSON metodunu tekrardan kullanmamız gerekiyor. Bu metod bizim için format dönüştürcü diyebiliriz.
3.5 Vektör Verileri Katmana Ekleme
Daha önceki fonksiyonlarda GeoJSON verisini vektör verilere çevirmiştik. Şimdi bunları katmana ekleyecek olan fonksiyonu hazırlamamız gerekiyor. Aşağıda yer alan kod içerisine eklenmesi istenilen vektör katmanın içini temizlerken gelecek olan verileride bir yandan ekliyor. Böylece katmanız her zaman temiz bir şekilde istediğimiz GeoJSON dosyasını bize gösteriyor.
3.6 Katmana Zoom Yapma
Haritaya ekleyeceğimiz GeoJSON verilerinin nerede olduğunu kestiremeyebiliriz. Bu nedenle her eklenen katman için katmanın BBOX alanına yaklaşmamız gerekiyor. Aşağıda ki kod bunun için.
3.7 Çizim Fonksiyonlarını Oluşturma
Openlayers harika bir kütüphanedir. İçerisinde hayat kurtaran fonksiyonları ile birlikte bizlere eşsiz bir CBS projesi geliştirme imkanı sunar. Hatırlarsanız index.html dosyası içerisinde kapalı alan, çizgi ve nokta çizmek için butonlar koymustuk ve onclick eventi draw adında bir metoda yönlendirilmişti. Bu metodun aldığı parametre de çizilmesi istenilen geometrinin tipiydi. Bu butonlar bu fonksiyon ile beraber işlerini yapıyorlar. İşlemin sonunda da yeni bir çizime başlamak için tekrar bu butonları tıklamamız gerekiyor. Kod içerisinde açıklama satırına alınmış kısım daha sonra aktif edilecek. Şimdilik sessiz bir şekilde beklesin ve indexedDB de yazacağımız zamana kadar sabırsızca beklesin. Artık haritamız üzerinde biraz çizim yapabiliriz. Açıklama satırını 4.6 anlatımı ile birlikte kaldırabilirsiniz.
3.8 Bir GeoJSON Dosyasını Okumak
index.html Dosyasında Add GeoJSON butonu eklemiştik. O butonun click eventi bu fonksiyona bağlıdır ve çalıştığında sanal bir DOM oluşturarak kullanıcılar için bir file dialog açar. Kullanıcılar haritaya yüklemek istedikleri GeoJSON dosyasını seçip onayladıklarında dosya içerisinde yer alan bilgiler artık bizde demektir.
Bu noktadan sonra senaryo gereği bu veriyi önce indexedDB eklememiz gerekiyor. Ancak şu an için bu kısımı açıklama satırına almış bir şekilde sunuyoruz. İhtiyacımız olan metodu yazdıktan sonra bu açıklama satırlarını kaldırabilirsiniz. Açıklama satırını 4.5 ve 4.7 numaralı kısımları öğrendikten sonra kaldırabilirsiniz.
3.9 Okunan GeoJSON Dosyasını Silmek
Daha önce bir GeoJSON dosyası okumuştuk. Kullanıcı başka bir GeoJSON dosyası yüklemek isteyebilir. Bu durumda ilgili katman daha önce indexedDB de kayıt altında olması gerektiği için oradan da silmemiz gerekiyor. Haritadan silinmesini gerektiren kısım map.js dosyasında geliştiriyorken indexedDB de silinmesi gereken kısım bir sonraki adımda anlatılacaktır.
Şimdi acilen katmanın içerisini boşaltmamız gerekiyor. Burada Katmanın içerisini boşaltan fonksiyonun adı clearLayer dir. removeGeoJSON önce indexedDB den kayıtları silip daha sonra işlem olumlu ise bu fonksiyonu kullanmaktadır. Açıklama satırını 4.7 numaralı konuyu öğrendikten sonra kaldırabilirsiniz.
3.10 Tüm Geometrileri Temizleme
Bir önceki konudan tek farkı çizilmiş olan katmanı da kapsamasıdır. Yani bu proje için haritamızda var olan tüm katmanlar anlamına geliyor. Adım sırasını takip etmeden içerisinde yer alan indexedDB updateLayer metodunu öğrenmek için lütfen Adım 4 te yer alan kısıma ilerleyiniz. Bu adım ile beraber 3. Adımı geçmiş oluyoruz. Buraya kadar geldiyseniz sizler de bizim gibi GIS aşığısınız demektir. Bu adımdan sonra artık Javascript aşığı olmanız gerekiyor.
Adım 4: indexedDB.js Dosyası ile Tarayıcı Veritabanını Hazırlama
Artık indexedDB dosyamızı geliştirmeye başlayabiliriz. IndexedDB halihazırda HTML5 ile birlikte gelen zaten tarayıcınızda var olan ancak çoğu kişinin kullanmaya çekindiği bir API diyebiliriz. Biz korkmadık çünkü kendimize güveniyoruz. Sizlerde kendinize güvenin hiçte zor değil.
Bu adımda yazacağımız metodların kullanım şeklini map.js dosyası içerisinde gördünüz. Şimdi orada tanımlanan fonksiyonları yazmaya başlarken aşağıda yer alan sırayı takip edelim.
- Global bir indexedDB değişkeni oluşturma ve IDBGeoJSON class’ı oluşturma
- Versiyon Bilgisi Alış/Verişi
- Kuyruk Yapısı Oluşturma
- Veritabanı Oluşturma
- Katman Ekleme
- Katman Düzenleme
- Katman Silme
- Katman Gösterme
- Sayfa Yenilenmesinde Kayıtlı Katmanları Gösterme
4.1 Globalde Tanımlama ve Class Oluşturma
Öncelikle her tarayıcıda çalışması için globalde indexedDB mizi tanımlamalıyız. Bu tanımlamanın ardından değişkeni her yerden çağırabiliriz. Oluşturacağımız nesnenin kurucu fonksiyonunu oluşturalım ve bu adımdan sonra her yeni fonksiyonu class kod bloğu içerisinde ve kurucu constructor fonksiyonu altında tanımlayalım. Açıklama satırına alınan kısım ilerleyen başlıklarda 4.4 numaralı kısmı oluşturduktan sonra kullanmak için açabilirsiniz.
4.2 Versiyon Bilgisi Alış/Verişi
IndexedDB’ye veritabanı yapısını değiştiren her işlemde version bilgisini bir artırmanız gerekmektedir. Çünkü veritabanında bir değişiklik olması durumunda veritabanı bir sonraki versiyona geçmiş olur ve sizin versiyon numarasını biliyor olmanız gerekir. Bu nedenle bu bilgiyi localStorage de kayıt altına alıyoruz. setVersion ile yeni version bilgisini tanımlarken kullanıyoruz. Mevcut versiyon bilgisini de getVersion ile alıyoruz.
4.3 Kuyruk Yapısı Oluşturma
IndexedDB çalıştırılırken aynı anda birden fazla transaction benzer versiyonda çakışmaması için kuyruk yapısını oluşturmamız gerekiyor. Yani veritabanı bir sonraki versiyona geçmez ise siz bir önceki sistemde değişiklik yapamazsınız. Durumun esnek olmaması bizi de üzüyor ancak localStorage in limiti düşük kotası ile zaman kaybetmektense böyle bir yöntemle çalışmak zorundayız.
Oluşturulacak olan bu kuyruk yapısı aynı zamanda bir işlem bitmeden diğerine geçmenin önüne geçecektir. O zaman artık bu işlemleri yapabilmemiz için ihtiyacımız olan kuyruk yapısını hazırlayalım.
Aşağıda ki metodlarda add listeye yeni bir iş eklerken aynı zamanda çalışmayı tetikler ve next metodu da iş bitene kadar tüm işleri doğru metoda yönlendirir. Artık asıl işi yapması gereken metodları yazıp switch içerisinde ki case bloklarına yazabiliriz.
next metodu bir obje parametresi alır ve type property bilgisine kullanacağınız asıl metodun adını yazacak şekilde tanımlıyoruz. Prop property bilgisine kullanacağımız parametreleri tanımlıyoruz. Metod işini bitirdikten sonra geri dönüş bekliyorsanız eğer isteğe bağlı olarak callback property tanımlaması yaparak true/false şeklinde bir geri dönüş almanızı mümkün kılacak şekilde kodluyoruz. Bu metodun kullanım örnekleri map.js dosyasını oluştururken göstermiştik.
4.4 Veritabanı Oluşturma
Class’ın kurucu fonksiyonunda oluşturacağımız veritabanının adını tanımlamıştık. Artık veritabanını oluşturabiliriz. Aşağıda biz indexedDB de sadece katmanlarımızı kayıt altında tutan bir ‘layers’ tablosu oluşturmak istedik. Bu tablonun birincil sütunu katmanın ad bilgisini tutarken GeoJSON sütunu ise ilgili katmanın GeoJSON bilgisini kayıt altına alacak şekilde tasarlandı. Fonksiyonların parametresinde yer alan callback fonksiyonu yapılan işlemin sonucunu size bildirmesi için bulunmaktadır.
Ancak bu metodu oluşturmanız yetmez. Öncelikle kurucu fonksiyon içerisinde ki createDb için oluşturulmuş açıklama satırını artık aktif hale getirirken next metodu içerisinde yeni bir case oluşturmanız gerekiyor. Örnek kod aşağıda ki gibi olması gerekmektedir.
Bu haliyle oluşturduğunuz sayfayı yenilediğinizde tarayıcınızın Application kısmında indexedDB ye ait tabloları görebilirsiniz.
4.5 Katman Oluşturma / Ekleme
Artık veritabanında layers adlı bir tablo bulunuyor ve bizim bu tabloya kayıt eklememiz gerekiyor. Bu bölümde indexedDB ye kayıt eklemeyi öğrenmiş olacağız. Bu metod’da tanımlayacagımız transaction’a add metodu ile katmanımızın kayıt bilgisini ekliyoruz
Bu metodumuzu class içerisine ekledikten sonra next metodunun case kısmına gerekli kod bloğunu ekleyebiliriz.
Artık sayfamız açılır açılmaz oluşması gereken layer2 katmanımızı layers tablosuna ekleyebiliriz. layer2 çizimleri kayıt altına alan bir katman olduğunu unutmayınız. Aşağıda belirttiğim kod bloğu oluşturduğumuz class’ın altında olması gerekmektedir. Bu kod ile birlikte boş bir layer2 kayıdını indexedDb de yer alan layers tablomuza ekliyoruz.
bu kodu yazdıktan sonra sayfanızı yenilemeniz durumunda aşağıda ki kaydı görebilirsiniz.
Ayrıca sayfanızın Add GeoJSON butonunu kullanmanız durumunda bir sefere mahsus eklemek istediğiniz dosyayı katman olarak ekleyecek ve gösterecektir. Bu özelliği tekrar kullanmanız durumunda bu katman zaten var olduğu için işlem yapmayacak hata verecektir. Bu sorunu da çözeceğiz.
4.6 Katman Düzenleme / Kayıt Düzenleme
Artık katmanlarımızı sisteme ekleyebildiğimize göre sabit olmayan katman yapımızı her değişimde tekrardan ilgili kayıtlarını indexedDB içerisinde güncellemek gerekmektedir. Bu işlem için updateLayer metodu oluşturuyoruz ve içerisinde yer alan transaction’a put ile düzenlemek istediğimiz veriyi tanımlıyoruz. Keypath değeri katmanın adı olduğu için sadece bu kaydı değiştirecek şekilde çalışacaktır.
Bu metod hazır olduktan sonra artık next metodumuzun case bloğuna updateLayer için tanımlama yapabiliriz.
Artık 3.7 de belirttiğimiz kod bloğu içerisinde ki açıklama satırlarını kaldırabilir ve harita üzerinde çizimler yapabilirsiniz. Her çizim aynı zamanda layers tablosunun layer2 kaydını güncelleyecektir.
Aşağıda yapılmış olan çizimlerin kayıt altında olduğunu görebilirsiniz.
4.7 Katman Silme / Kayıt Silme
Haritaya eklemiş olduğumuz GeoJSON dosyasını daha önce sadece bir sefere mahsus ekleyebiliyorduk. Artık var olan kaydı silebilir ve tekrar ekleyebiliriz. Kolaya kaçmak istesek layerUpdate ile de bunu yapabilirdik ancak bu konu kayıt silme konusu olduğu için bu şekilde bir proje geliştirdik.
Aşağıda yer alan kod bloğunda tanımladığımız transaction’a ait delete metodunu kullanarak adını bildiğimiz katmanı kayıtlardan siliyoruz.
Bu metodu ekledikten sonra next metoduna aşağıda yer alan case bloğunu eklememiz ile birlikte artık haritanıza istediğiniz kadar GeoJSON dosyası ekleyebiliyor olacaksınız
Şimdi haritanıza farklı GeoJSON dosyalarını ekleyebilirsiniz.
4.8 Katman Gösterme / Kayıt Okuma
Artık herşey daha temiz ve yazdığımız kodlar bir karşılık buluyor. Artık kullanıcılarımıza yükledikleri kayıtları sayfayı yenileseler bile kaybetmediğimizi kanıtlamamız gerekiyor.
Bu metod ile birlikte sayfayı yenilediğimizde daha önce kayıt edilmiş olan katmanlar otomatik olarak haritaya yüklenecek ve kullanıcıyı sevindiren gelişmeyi başarmış olacaksınız. Çünkü Web kullanıcıları yaptıkları işlerin kaybolmasından ve boşa gitmesinden hoşlanmazlar.
Aşağıda yer alan kod bloğunun diğer metodlardan farkı readonly yöntemi ile verilerin çekilmesi ve cursor kullanarak bu verileri teker teker bize sunması. Böylece buradan elde ettiğimiz kayıtları callback kullanarak geri alabilir duruma geliyoruz.
Yukarıda yer alan kod bloğunu ekledikten sonra aşağıda yer alan kodu next metodunun case bloklarına yeni bir case olarak eklememiz gerekiyor.
Böylece kodumuz neredeyse hazır hale geliyor.
4.9 Sayfa Yenilenmesinde Kayıtlı Katmanları Gösterme
Artık bizi başarıya götürdüğünü kanıtlayacağımız adıma geldik. Bu adımda kullanıcı sayfasını yenilese bile oluşturduğu katmanları, çizdiği geometrik verileri kaybetmediğini göstermemiz gerekiyor. Aşağıda yer alan kod ile birlikte tamamlamış olacağız. Bu kod 4.5 konusunda gösterdiğimiz son kod bloğunda yer alan ve class dışında olacak şekilde sisteme eklenmesi gerekmektedir. Yani diğer bir deyişle indexedDB.js dosyasının en altına eklemeniz yeterli.
index.html sayfasında yer alan clear butonu ise 3.10 konusunda anlatılmıştı. Açıklama satırında unuttuğunuz bir kod var ise lütfen açınız. Birşeylerin yanlış gittiğine inanıyorsanız lütfen github kodundan yardım alınız.
Adım 5 : İşte Hazırız!
Umarım elimden geleni yapabilmişimdir. Sorularınız olması durumunda aşağıya yazmaktan çekinmeyin. Beni takip ederseniz eğer önümüzde ki zamanlarda birbirinden güzel yazılar paylaşmaya devam edeceğim.
Danışmanlık Hizmeti Almak İstiyorsanız : Bize Ulaşabilirsiniz
Bazı Takip Etmenizi Önerdiğim Sayfalarımız
- Kişisel Linkedin Sayfam : Tıkla ve Bağlantı Kur
- GISLayer Linkedin Sayfası : Tıkla ve Takip Et
- Web Sitemiz : Tıkla ve Ürünlerimizi Kullan
- Github Sayfamız : Tıkla ve Kod Desteği Al