CSS Bölgeleri ve 3D dönüşümleri kullanarak çevrilebilir kitap yazma

Ilmari Heikkinen

O gün geldi çattı. Sonunda uzun metin kaydırmalarından sıkıldınız ve yeni bir biçim arıyorsunuz. Şık bir şey. Kompakt bir şey. Uzun parşömeni alıp düzgün küçük dikdörtgenler halinde kesen ve bunları birbirine bağlayan bir şey. Bu icadı "kitap" olarak adlandırıyorum.

CSS bölgelerinin (CanIUse, chrome://flags adresine gidip CSS Bölgeleri'ni etkinleştirme) ve CSS 3D dönüşümlerinin gücü sayesinde artık modern tarayıcılarda en yeni kitap teknolojisi kullanıma sunuldu. Tek ihtiyacınız olan birkaç satır JavaScript ve bir sürü CSS'dir.

Kitap yapımızı tanımlayarak başlayalım. Kitap sayfalardan oluşur ve sayfalar iki taraftan oluşur. Kenarlarda kitap içeriği yer alır:

<div class="book">
    <div> <!-- first page -->
    <div> <!-- front cover -->
        # My Fancy Book
    </div>
    <div> <!-- backside of cover -->
        # By Me I. Myself
        ## 2012 Bogus HTML Publishing Ltd
    </div>
    </div>
    <!-- content pages -->
    <div>
    <!-- front side of page -->
    <div class="book-pages"></div>
    <!-- back side of page -->
    <div class="book-pages"></div>
    </div>
    <div>
    <div class="book-pages"></div>
    <div class="book-pages"></div>
    </div>
    <div>
    <div class="book-pages"></div>
    <div class="book-pages"></div>
    </div>
</div>

Kitap metnini kitap sayfalarına akışı için CSS bölgelerini kullanacağız. Ama önce kitap metnine ihtiyacımız var.

<span id="book-content">
    blah blah blah ...
</span>

Artık kitabımızı yazdığınıza göre CSS akışını tanımlayalım. Tedarikçi firma ön eki yer tutucusu olarak + karakterini kullanıyorum. Onu WebKit tarayıcıları için -webkit-, Firefox için -moz- vb. ile değiştiriyorum:

#book-content {
    +flow-into: book-text-flow;
}
.book-pages {
    +flow-from: book-text-flow;
}

Artık #book-content aralığından içerik, bunun yerine .book-pages div öğelerine gider. Yine de bu oldukça kötü bir kitap. Daha kitap gibi bir kitap için bir göreve çıkmalıyız. Yolculuğumuz CSS'nin gökkuşağı köprüsünden JavaScript'in saat krallığına dönüşecek. Mekanik peri bürosu salonlarında efsanevi geçiş sihirlerini ortaya çıkaracak ve dünya genelindeki arayüzü kontrol eden efsanevi üç anahtarı ele geçireceğiz.

Gökkuşağı Köprüsü'nün koruyucusu bize şık yapılı seçicilerin tecrübesini aktarıyor ve böylece HTML kitap yapımızı daha kitap benzeri bir biçime dönüştürebiliyoruz:

html {
    width: 100%;
    height: 100%;
}
body {
    /* The entire body is clickable area. Let the visitor know that. */
    cursor: pointer;
    width: 100%;
    height: 100%;
    /* Set the perspective transform for the page so that our book looks 3D. */
    +perspective: 800px;
    /* Use 3D for body, the book itself and the page containers. */
    +transform-style: preserve-3d;
}
.book {
    +transform-style: preserve-3d;
    position: absolute;
}
/* Page containers, contain the two sides of the page as children. */
.book > div {
    +transform-style: preserve-3d;
    position: absolute;
}
/* Both sides of a page. These are flat inside the page container, so no preserve-3d. */
.book > div > div {
    /* Fake some lighting with a gradient. */
    background: +linear-gradient(-45deg, #ffffff 0%, #e5e5e5 100%);
    width: 600px;
    height: 400px;
    overflow: hidden;
    /* Pad the page text a bit. */
    padding: 30px;
    padding-bottom: 80px;
}
/* Front of a page */
.book > div > div:first-child {
    /* The front side of a page should be slightly above the back of the page. */
    +transform: translate3d(0px, 0px, 0.02px);
    /* Add some extra padding for the gutter. */
    padding-left: 40px;
    /* Stylish border in the gutter for visual effect. */
    border-left: 2px solid #000;
}
/* Back of a page */
.book > div > div:last-child {
    /* The back side of a page is flipped. */
    +transform: rotateY(180deg);
    padding-right: 40px;
    border-right: 2px solid #000;
}
/* Front cover of the book */
.book > div:first-child > div:first-child {
    /* The covers have a different color. */
    background: +linear-gradient(-45deg, #8c9ccc 0%, #080f40 100%);
    /* Put a border around the cover to make it cover the pages. */
    border: 2px solid #000;
    /* And center the cover. */
    margin-left: -1px;
    margin-top: -1px;
}
/* Back cover of the book */
.book > div:last-child > div:last-child {
    background: +linear-gradient(-45deg, #8c9ccc 0%, #080f40 100%);
    border: 2px solid #000;
    margin-left: -1px;
    margin-top: -1px;
}

Böylece, HTML'miz için kağıt biçiminde bir stil oluştururken, JavaScript krallığının trilyon dişli kapılarına ulaşırız. Kapıdan geçmek için düz kitabımızı uygun bir cilde dönüştürmemiz gerekir. Kitaba biraz cilt eklemek için, her sayfanın z ekseninde belirli uzaklıkta kopyasını oluştururuz.

(function() {
var books = document.querySelectorAll('.book');
for (var i = 0; i < books.length; i++) {
    var book = books[i];
    var pages = book.childNodes;
    for (var j = 0; j < pages.length; j++) {
    if (pages[j].tagName == "DIV") {
        setTransform(pages[j], 'translate3d(0px, 0px, ' + (-j) + 'px)');
    }
    }
}
})();

Masalları etkilemek için geçiş sihri oluşturmak, en zor çağrılar değildir. Yine de sonuçlar, kitabımızın sayfalarının sorunsuz bir şekilde dönmesini sağlıyor.

.book > div {
    +transition: 1s ease-in-out;
}

Son olarak, sayfaların gerçekten dönmesini sağlamak için olayların kendilerini amacımıza bağlamamız gerekir.

(function(){
    // Get all the pages.
    var pages = document.querySelectorAll('.book > div');
    var currentPage = 0;
    // Go to previous page when clicking on left side of window.
    // Go to the next page when clicking on the right side.
    window.onclick = function(ev) {
        if (ev.clientX < window.innerWidth/2) {
        previousPage();
        } else {
        nextPage();
        }
        ev.preventDefault();
    };
    var previousPage = function() {
        if (currentPage > 0) {
        currentPage--;
            // Rotate the page to closed position and move it to its place in the closed page stack.
        setTransform(pages[currentPage], 'translate3d(0px,0px,' + (-currentPage) + 'px) rotateY(0deg)');
        }
    };
    var nextPage = function() {
        if (currentPage < pages.length) {
            // Rotate the page to open position and move it to its place in the opened stack.
        setTransform(pages[currentPage], 'translate3d(0px,0px,' + currentPage + 'px) rotateY(-150deg)');
        currentPage++;
        }
    };
})();

Bununla, "kitap" teknolojisini edindik ve dünyanın yeryüzündeki kristal kulelerini tahliye edebiliyor, bunların kör parlamalarını ve yerküredeki bağın büyük mavi yıldızı Achenar'ın alevli nükleer ateşlerini geride bırakabiliyoruz. Kitaplarımızı başlarımızın üzerinde sallayarak evlerimize zaferle geri dönüyor ve onurumuza yapılan kaçınılmaz geçit törenlerine ve kutlamalara hazır oluyoruz.

İnternet üzerinden bir örneği burada görebilir ve örneklerle ilgili tam kaynağı inceleyebilirsiniz. Tarayıcınızda CSS Bölgeleri yoksa örnek oldukça bozuk görünür. Bu durumda, bu örneği deneyebilirsiniz.