Книга 3D

Сегодня мы развиваем что-то действительно интересное и полезное. Новый плагин jQuery — генератор для 3D книги. Книга состоит из страниц, каждая страница состоит из 2-х сторон (как в обычной книге), и по бокам есть кнопки для перелистывания страниц назад-вперёд, и когда мы переворачиваем страницу мы видим что страница в 3D на базе CSS3.

Оглавление:

Для того чтобы достичь 3D эффекта используются преобразования CSS3 (rotate3d, preserve-3d и rotateY) и эффекты перехода.

Демо

HTML

HTML разметка страницы текст с изображением как обложка книги. Но вы можете применить все что угодно.

<div class="book">
  <img src="book.jpg" alt="" style="display:block" />
<h2>заголовок</h2> 
<h4>заголовок</h4> 
<h4>заголовок</h4> 
  <div>текст</div> 
<h3>заголовок</h3> 
  <div>текст</div> 
  <div>текст</div> 
<h3>заголовок</h3> 
  <div>текст</div> 
</div>
к меню ↑

CSS

Стили CSS3 для нашей книги:

* {
  margin: 0;
  padding: 0;
  }
  header {
  background-color:rgba(33, 33, 33, 0.9);
  color:#fff;
  display:block;
  font: 14px/1.3 Arial,sans-serif;
  height:50px;
  position:relative;
  }
  header h2{
  font-size: 22px;
  margin: 0px auto;
  padding: 10px 0;
  width: 80%;
  text-align: center;
  }
  header a, a:visited {
  text-decoration:none;
  color:#fcfcfc;
  }

  body {
  background: url('background.png') no-repeat center center fixed;
  -webkit-background-size: cover;
  -moz-background-size: cover;
  -o-background-size: cover;
  background-size: cover;

  /* CSS3 perspective and transform */
  -webkit-perspective: 1800px;
  -moz-perspective: 1800px;
  -moz-transform-style: preserve-3d;
  -webkit-transform-style: preserve-3d;
  }

  .book {
  left: 530px;
  position: absolute;
  top: 70px;
  width: 400px;

  /* CSS3 transform */
  -webkit-transform: rotate3d(0, 0, 1, 0deg);
  -moz-transform: rotate3d(0, 0, 1, 0deg);
  -webkit-transform-style: preserve-3d;
  -moz-transform-style: preserve-3d;
  }
  .book img {width:330px; margin: 0 auto;}

  .page {
  background-color: #fff;
  position: absolute;

  /* CSS3 transform */
  -webkit-transition: all 1s ease-in-out 0s;
  -moz-transition: all 1s ease-in-out 0s;
  -webkit-transform-style: preserve-3d;
  -moz-transform-style: preserve-3d;
  }

  .side:first-child {
  background: -webkit-linear-gradient(-45deg, #fff 0%, #ddd 100%) repeat scroll 0 0 transparent;
  background: -moz-linear-gradient(-45deg, #fff 0%, #ddd 100%) repeat scroll 0 0 transparent;
  border-left: 2px solid #000;
  height: 500px;
  overflow: hidden;
  padding: 30px 35px 80px 35px;
  position: absolute;
  width: 400px;

  /* CSS3 transform */
  -webkit-transform: translate3d(0px, 0px, 0.5px);
  -moz-transform: translate3d(0px, 0px, 0.5px);
  }

  .side:last-child {
  background: -webkit-linear-gradient(-45deg, #fff 0%, #ddd 100%) repeat scroll 0 0 transparent;
  background: -moz-linear-gradient(-45deg, #fff 0%, #ddd 100%) repeat scroll 0 0 transparent;
  border-right: 2px solid #000;
  height: 500px;
  overflow: hidden;
  padding: 30px 35px 80px 35px;
  position: absolute;
  width: 400px;

  /* CSS3 transform */
  -webkit-transform: rotateY(180deg);
  -moz-transform: rotateY(180deg);
  }

  button {
  margin-top:10px;
  float:right;
  cursor:pointer;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 14px;
  color: #050505;
  padding: 10px 20px;
  background: -moz-linear-gradient(
  top,
  #fff 0%,
  #ebebeb 50%,
  #dbdbdb 50%,
  #b5b5b5);
  background: -webkit-gradient(
  linear, left top, left bottom,
  from(#fff),
  color-stop(0.50, #ebebeb),
  color-stop(0.50, #dbdbdb),
  to(#b5b5b5));
  -moz-border-radius: 10px;
  -webkit-border-radius: 10px;
  border-radius: 10px;
  border: 1px solid #949494;
  -moz-box-shadow:
  0px 1px 3px rgba(000,000,000,0.5),
  inset 0px 0px 2px rgba(255,255,255,1);
  -webkit-box-shadow:
  0px 1px 3px rgba(000,000,000,0.5),
  inset 0px 0px 2px rgba(255,255,255,1);
  box-shadow:
  0px 1px 3px rgba(000,000,000,0.5),
  inset 0px 0px 2px rgba(255,255,255,1);
  text-shadow:
  0px -1px 0px rgba(000,000,000,0.2),
  0px 1px 0px rgba(255,255,255,1);
  }
к меню ↑

JavaScript

Теперь самый важный шаг — код JavaScript (наш генератор плагина jQuery), создайте пустой файл script.js и вставьте следующий код:

// Goto page function
function gotoPage(i) {
    $('.page').eq(i).removeClass('active');
    if ((i-1) >= 0) {
        $('.page').eq(i-1).addClass('active');
    }
}

// Wrap everything as a jQuery plugin
(function($){
    $.fn.extend({
        EbookTransformer: function(options) {
            var defaults = {
                height: 400
            };
            var options = $.extend(defaults, options);

            // The book object
            var objBook = $(this);

            // Inner variables
            var vPages = new Array();
            var vSides = new Array();
            var vSubObj = new Array();
            var iTmpHeight = 0;

            // initialization function
            init = function() {
                // Walk through all the objects of the book, and prepare Sides (for Pages)
                objBook.children().each(function(i){
                    if (iTmpHeight + this.clientHeight > options.height && vSubObj.length) {
                        vSides.push(vSubObj);
                        vSubObj = new Array();
                        iTmpHeight = 0;
                    }

                    iTmpHeight += this.clientHeight;
                    vSubObj.push(this);
                });

                if (iTmpHeight > 0) {
                    vSides.push(vSubObj);
                }
                $(vSides).wrap('<div class="side"></div>');

                // Prepare Pages (each Page consists of 2 Sides)
                var iPage = 1;
                var vCouples = Array();
                objBook.children().each(function(i){
                    // Add Next and Prev buttons
                    if (vCouples.length == 0) {
                        $(this).append('<button onclick="gotoPage('+iPage+')">Далі</button>');
                    }
                    if (vCouples.length == 1) {
                        $(this).append('<button onclick="gotoPage('+(iPage-1)+')">Раніше</button>');
                    }
                    vCouples.push(this);

                    if (vCouples.length == 2) {
                        vPages.push(vCouples);
                        vCouples = new Array();
                        iPage++;
                    }
                });
                if (vCouples.length == 1) {
                    vCouples.push($('<div class="side"><h2>Край</h2><button onclick="gotoPage('+(iPage-1)+')">Раніше</button></div>')[0]);
                    vPages.push(vCouples);
                }
                $(vPages).wrap('<div class="page"></div>');

                // Add extra CSS for the pages
                var sExtraCSS = '';
                objBook.children().each(function(i){
                    //alert(i); // 0 .. 2
                    sExtraCSS += ''+
                    '.page:nth-child('+(i+1)+') {'+
                    '-moz-transform: translate3d(0px, 0px, -'+i+'px);'+
                    '-webkit-transform: translate3d(0px, 0px, -'+i+'px);'+
                    '}'+
                    '.active:nth-child('+(i+1)+') {'+
                    '-moz-transform: rotateY(-179deg) translate3d(0px, 0px, -'+i+'px);'+
                    '-webkit-transform: rotateY(-179deg) translate3d(0px, 0px, -'+i+'px);'+
                    '}';
                });
                $('.book').append('<style>'+sExtraCSS+'</style>');
            };

            // initialization
            init();
        }
    });
})(jQuery);

// Window onload
jQuery(window).load(function() {
    $('.book').EbookTransformer({height: 480});
});

Идея скрипта похожа в использовании пагинации страниц, чтобы разобрать все входные данные (наш исходный текст) составит новую структуру HTML для 3D-книги. На первом этапе мы проходим через все внутренние элементы, и превращаим их в Sides (в наших страницах). Мы должны проверить высоту внутренних элементов, и в случае, если общая высота боковых элементов больше чем максимально допустимый, мы начинаем сбор следующей стороны. На втором этапе мы обратимся к результатам сторон на странице. Каждая страница состоит из нескольких сторон. Также на втором этапе мы добавили кнопки навигации. И наконец для размещения страниц друг на другом, мы должны создавать дополнительные стили CSS (на лету). Мы используем свойства CSS3 translate3d для подготовки пользовательских стилей (с разным значением Z) для всех созданых страниц.