CSS 영역 및 3D 변환을 사용하여 플립형 책 작성

일마리 헤익키넨

자. 그럼, 날이 왔네요. 마침내 긴 두루마리의 텍스트에 지루해져 새로운 형식을 찾고 있습니다. 우아한 분위기. 컴팩트한 디자인. 긴 두루마리처럼 깔끔한 작은 직사각형을 잘라서 하나로 묶는 무언가를 말합니다. 이 발명품을 '책'이라고 합니다.

CSS 지역 (CanIUse, chrome://flags에서 CSS 지역 사용 설정)과 CSS 3D 변환을 활용하여 최신 브라우저에서 도서 기술을 사용할 수 있게 되었습니다. 몇 줄의 자바스크립트와 여러 가지 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-, Firefox의 경우 -moz-로 바꿉니다.

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

이제 #book-content 스팬 의 콘텐츠가 .book-pages div로 이동합니다. 이 책은 조금 형편없는 책입니다. 좀 더 책을 갈고닦은 책을 만들려면 퀘스트를 시작해야 합니다. 우리의 여정은 CSS 변환의 무지개 다리를 지나 JavaScript의 왕국으로 이어져야 합니다. 정비사 페어릴르드의 홀에서 위대한 전환 마법을 발휘하여 오버월드 인터페이스를 제어하는 전설의 열쇠 3개를 손에 넣는다.

레인보우 브리지의 수호자가 세련된 구조 선택기의 지혜를 알려주고, 이를 통해 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을 위한 다소 종이 모양의 스타일을 만드는 과정에서 1조 개 정도의 노력으로 구성된 자바스크립트 왕국의 문에 이르게 됩니다. 문을 통과하려면 플랫 책을 적절한 볼륨으로 바꿔야 합니다. 책에 볼륨을 추가하기 위해 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 영역이 없으면 예제가 엉망으로 표시됩니다. 이 경우 이 예를 대신 시도해 보세요.