كتابة كتاب قابل للقلب باستخدام مناطق CSS وعمليات التحويل الثلاثية الأبعاد

إلماري هيكينين

لقد جاء اليوم. لقد شعرت أخيرًا بالملل من قراءة فقرات نصية طويلة وكنت تبحث عن تنسيق جديد. شيء أنيق. شيء مكثف. شيء يستغرق التمرير الطويل، ويقسمه إلى مستطيلات صغيرة أنيقة ويربطها معًا. وأطلق على هذا الاختراع اسم "الكتاب".

بفضل إمكانيات مناطق CSS (CanIUse، الانتقال إلى chrome://flags وتفعيل مناطق CSS) وعمليات تحويل CSS الثلاثية الأبعاد، تتوفّر أحدث تقنيات الكتب أخيرًا على المتصفّحات الحديثة. كل ما تحتاجه هو بضعة أسطر من JavaScript والكثير من ملفات CSS.

لنبدأ بتحديد بنية كتابنا. يتكون الكتاب من صفحات وتتكون الصفحات من جانبين. تحتوي الجوانب على محتوى الكتاب:

<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>

سنستخدم مناطق CSS لتدفق نص الكتاب إلى صفحات الكتاب. لكننا نحتاج أولاً إلى نص الكتاب.

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

الآن بعد أن كتبنا كتابنا، دعنا نعرّف تدفق CSS. أستخدم الحرف + كعنصر نائب لبادئة المورّد، واستبدله بالرمز -webkit- لمتصفحات WebKit و-moz- في متصفّح Firefox، وما إلى ذلك:

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

الآن سينتقل المحتوى من نطاق #book-content إلى قسم divs .book بدلاً من ذلك. هذا كتاب رديء إلى حد ما. للحصول على كتاب مليء بالكتب، علينا أن نبدأ المهمة. ستقود رحلتنا إلى جسر قوس قزح في CSS لتحوّلات إلى مملكة سير عمل JavaScript. سنطلق العنان لسحر الانتقالات الملحمية في قاعات عالم الميكانيكا الخيالي، ونحصل على المفاتيح الثلاثة الأسطورية التي تتحكم في الواجهة حول العالم.

الحارس على جسر قوس قزح يزوّدنا بحكمة من أدوات التحديد الهيكلية الأنيقة، حتى نتمكن من تحويل بنية كتاب HTML إلى شكل كتاب على شكل أكثر:

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;
}

ومن ثم، تمكنا من إنشاء نمط على شكل ورق للغة HTML، وصلنا إلى تريليون بوابات موجهة لمملكة JavaScript. ولعبور البوابة، يجب أن نحول كتابنا المسطّح إلى حجم مناسب. لإضافة جزء من المجلد إلى الكتاب، نعوض كل صفحة قليلاً على المحور z.

(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)');
    }
    }
}
})();

إنّ إضفاء مؤثرات حركية مذهلة على الشخصيات الخيالية ليست الأصعب من حيث الاستدعاءات. ومع ذلك، تؤدي النتائج إلى جعل صفحات كتابنا تتحرك بشكل سلس.

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

وأخيرًا، لكي تتقلب الصفحات، نحتاج إلى ربط الأحداث نفسها بقضيتنا.

(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++;
        }
    };
})();

بهذه الطريقة، حصلنا على تقنية "الكتاب" وتمكنا من نزع الأبراج البلورية حول العالم وترك وهجها الغامض والنيران النووية الشرسة لـ "أتشينار"، النجم الأزرق العظيم الذي يؤدي إلى وجود الرابط بين أنحاء العالم. نعود بانتصار إلى منازلنا ونرفع كُتبنا عالية فوق رؤوسنا، في استعداد لمتابعات المسيرات والاحتفالات الحتمية تكريمًا لنا.

يمكنك الاطّلاع على مثال على الإنترنت هنا والحصول على المصدر الكامل للأمثلة. إذا لم يكن لديك مناطق CSS في المتصفح، فسيبدو المثال معطّلاً إلى حد كبير. وفي هذه الحالة، يمكنك تجربة هذا المثال بدلاً من ذلك.