纯Javascript中的页面翻转效果

时间:2013-04-09 14:24:06

标签: javascript flip turnjs

对于电子书阅读器网络应用程序,我试图为电子书制作一个看上去像书的浏览器,如iBooks for iPad和iPhone。

我发现了优秀的jQuery插件,这正是我想要达到的目标。唯一的问题是,它是一个jQuery插件,所以我不能使用它。怎么可能在纯Javascript中完成?

链接到jQuery页面翻转插件:Turn JS jQuery Plugin

2 个答案:

答案 0 :(得分:11)

尽管您可能认为单独使用JavaScript会更好,但您应该明白,如果没有正确的数学理解,这可能会非常困难,所有这些都可能会花费您更多时间来弄清楚插件你已经在上面展示了无论如何,我发现了一些可以让你朝着正确的方向前进的jsfiddles。

纯JavaScript翻转效果:http://jsfiddle.net/maitrekaio/nuUNd/

// 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) {
        drawDroppedShadow(foldX, foldWidth, strength);
    }

    context.restore();
}


// Draw the folded piece of paper
function drawFoldedPaper(foldX, foldWidth, verticalOutdent, fill) {
    context.beginPath();
    context.moveTo(foldX, 0);
    context.lineTo(foldX, PAGE_HEIGHT);
    context.quadraticCurveTo(foldX, PAGE_HEIGHT + (verticalOutdent * 2), foldX - foldWidth, PAGE_HEIGHT + verticalOutdent);
    context.lineTo(foldX - foldWidth, -verticalOutdent);
    context.quadraticCurveTo(foldX, -verticalOutdent * 2, foldX, 0);

    if (fill) {
        // Gradient applied to the folded paper (highlights & shadows)
        var paperShadowWidth = (PAGE_WIDTH * 0.5) * Math.max(Math.min(1 - progress, 0.5), 0);
        var foldGradient = context.createLinearGradient(foldX - paperShadowWidth, 0, foldX, 0);
        foldGradient.addColorStop(0.35, '#fafafa');
        foldGradient.addColorStop(0.73, '#eeeeee');
        foldGradient.addColorStop(0.9, '#fafafa');
        foldGradient.addColorStop(1.0, '#e2e2e2');
        context.fillStyle = foldGradient;
        context.fill();
    }
    context.strokeStyle = 'rgba(0,0,0,0.06)';
    context.lineWidth = 2;
    context.stroke();
}

// Draw a sharp shadow on the left side of the page
function drawSharpShadow(foldX, foldWidth, verticalOutdent, strength) {
    context.strokeStyle = 'rgba(0,0,0,'+(0.05 * strength)+')';
    context.lineWidth = 30 * strength;
    context.beginPath();
    context.moveTo(foldX - foldWidth, -verticalOutdent * 0.5);
    context.lineTo(foldX - foldWidth, PAGE_HEIGHT + (verticalOutdent * 0.5));
    context.stroke();
}

function drawDroppedShadow(foldX, foldWidth, strength) {    
    // Right side drop shadow
    var rightShadowWidth = (PAGE_WIDTH * 0.5) * Math.max(Math.min(strength, 0.5), 0);
    var rightShadowGradient = context.createLinearGradient(foldX, 0, foldX + rightShadowWidth, 0);
    rightShadowGradient.addColorStop(0, 'rgba(0,0,0,'+(strength*0.2)+')');
    rightShadowGradient.addColorStop(0.8, 'rgba(0,0,0,0.0)');

    context.fillStyle = rightShadowGradient;
    context.beginPath();
    context.moveTo(foldX, 0);
    context.lineTo(foldX + rightShadowWidth, 0);
    context.lineTo(foldX + rightShadowWidth, PAGE_HEIGHT);
    context.lineTo(foldX, PAGE_HEIGHT);
    context.fill();


    // Left side drop shadow
    var leftShadowWidth = (PAGE_WIDTH * 0.5) * Math.max(Math.min(strength, 0.5), 0);
    var leftShadowGradient = context.createLinearGradient(foldX - foldWidth - leftShadowWidth, 0, foldX - foldWidth, 0);
    leftShadowGradient.addColorStop(0, 'rgba(0,0,0,0.0)');
    leftShadowGradient.addColorStop(1, 'rgba(0,0,0,'+(strength*0.15)+')');

    context.fillStyle = leftShadowGradient;
    context.beginPath();
    context.moveTo(foldX - foldWidth - leftShadowWidth, 0);
    context.lineTo(foldX - foldWidth, 0);
    context.lineTo(foldX - foldWidth, PAGE_HEIGHT);
    context.lineTo(foldX - foldWidth - leftShadowWidth, PAGE_HEIGHT);
    context.fill();    
}

jQuery翻转效果(这不应该是转换为纯JavaScript的问题):http://jsfiddle.net/pixelass/TW43V/61/

另一个jQuery翻转效果:http://jsfiddle.net/wdm954/DkZsY/2/

因为你想要纯JavaScript知道你需要弄清楚如何自己做这件事。使用这些示例作为指导将有所帮助,即使它们不是纯粹的js。

答案 1 :(得分:6)

这个问题相当陈旧,但我会提供一个参考资料,其中已经获得了批准答案的想法 - http://www.html5rocks.com/en/tutorials/casestudies/20things_pageflip/。带有解释和示例的好教程。