pageFlip tutorial

Play with the parameters to see how the flip effect is working

by maitrekaio

HTML

<table>
    <tr>
        <td><label for="progress">Progress</label></td>
        <td><input id="progress" type="range" min="-1" max="1" step="0.1" value="1"/></td>
        <td ><label for="foldWidth">foldWidth</label></td>
        <td><input id="foldWidth" type="text" disabled></td>
        <td><label for="foldX">foldX</label></td>
        <td><input id="foldX" type="text" disabled></td>
    </tr>
    <tr>
        <td colspan="2"><label for="fill">Fill paper with gradient</label></td>
        <td><input id="fill" type="checkbox" checked/>
    </tr>
     <tr>
        <td colspan="2"><label for="droppedShadow">Drop shadows on both sides of the page</label></td>
        <td><input id="droppedShadow" type="checkbox" checked/>
    </tr>
     <tr>
        <td colspan="2"><label for="sharpShadow">Add sharp shadow on the left of the page</label></td>
        <td><input id="sharpShadow" type="checkbox" checked/>
    </tr>
</table>
<canvas id="pageflip-canvas"></canvas>

CSS

body, h2, p {
    margin: 0;
    padding: 0;
    color: white;
}

body {
    background-color: #444;
    
    font-family: Helvetica, sans-serif;
}

canvas {
    background-color: #e2e2e2;
    margin: 20px;
}

td {
    padding: 5px;
}
input[type=range]::before {
    content: attr(min);
}
input[type=range]::after {
    content: attr(max);
}

JavaScript

// Dimensions of the whole book
var BOOK_WIDTH = 630;
var BOOK_HEIGHT = 260;

// Dimensions of one page in the book
var PAGE_WIDTH = 300;
var PAGE_HEIGHT = 250;

// Vertical spacing between the top edge of the book and the papers
var PAGE_Y = (BOOK_HEIGHT - PAGE_HEIGHT) / 2;

// The canvas size equals to the book dimensions + this padding
var CANVAS_PADDING = 30;

var progress = 1;
var target = -1;

var canvas = document.getElementById("pageflip-canvas");
var context = canvas.getContext("2d");
var fillElt = document.getElementById("fill");
var droppedShadowElt = document.getElementById("droppedShadow");
var sharpShadowElt = document.getElementById("sharpShadow");
var progressElt = document.getElementById("progress");
var foldWidthElt = document.getElementById("foldWidth");
var foldXElt = document.getElementById("foldX");

// Resize the canvas to match the book size
canvas.width = BOOK_WIDTH;
canvas.height = BOOK_HEIGHT + (CANVAS_PADDING * 2);

progressElt.addEventListener("change", render, false);

function render() {

    // Reset all pixels in the canvas
    context.clearRect(0, 0, canvas.width, canvas.height);

    // Ease progress towards the target value 
    progress = progressElt.value;
    // Strength of the fold is strongest in the middle of the book
    var strength = 1 - Math.abs(progress);

    // Width of the folded paper
    var foldWidth = (PAGE_WIDTH * 0.5) * (1 - progress);

    // X position of the folded paper
    var foldX = PAGE_WIDTH * progress + foldWidth;

    // How far the page should outdent vertically due to perspective
    var verticalOutdent = 20 * strength;

    foldWidthElt.value = foldWidth;
    foldXElt.value = foldX;
    
    context.save();
    context.translate((BOOK_WIDTH / 2), PAGE_Y + CANVAS_PADDING);
    
    drawFoldedPaper(foldX, foldWidth, verticalOutdent, fillElt.checked);


    if (sharpShadowElt.checked) {
        drawSharpShadow(foldX, foldWidth, verticalOutdent, strength);
    }

    if (droppedShadowElt.checked)...