כתיבת ספר ניתן להיפוך באמצעות אזורי 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 של הזרימה. אני משתמש בתו + בתור placeholder של קידומת ספק, מחליפים אותו ב--webkit- לדפדפני WebKit, -moz- ב-Firefox וכן הלאה:

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

כעת התוכן מתוך ה-span #book-content יעבור אל ה- .book-pages div במקום זאת. אבל זה ספר די גרוע. כדי לספר לנו ספר יותר, עלינו לצאת למסע. המסע שלנו יוביל אותך מעל גשר הקשת של 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, הדוגמה תיראה לא תקינה. במקרה כזה, אפשר לנסות במקום זאת את הדוגמה הזו.