纯Javascript实现翻页效果

5

我正在为一款电子书阅读器Web应用程序设计一个像iPad和iPhone上的iBooks一样的花哨的书籍查看器。

我发现了一个非常棒的jQuery插件,正是我想要达到的效果。唯一的问题是,它是一个jQuery插件,所以我无法使用它。如何在纯JavaScript中实现类似的效果呢?

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


2
当Stackoverflow用户看到你努力尝试着去做某事时,他们更愿意回答你的问题。你是否尝试过某些东西却卡住了?你有一段无法解决的代码吗?通常情况下,我们不会为别人所需的编程而不让他们先尝试。 - John Riselvato
2
如果你不能向我们证明你已经尝试过,那么我们也会要求 $ $。 :) - Sanchit
3
好的,我到目前为止没有尝试过任何事情的原因是,我真的不知道如何开始制作一张纸的物理效果等等。我想也许有人知道一个好的教程或者提示从哪里开始... - David Fariña
1
jQuery不会使您的代码性能降低,这是胡说八道。只要可能,jQuery就会回退到本地API。此外,即使现代浏览器也存在大量错误,如果您的要求是跨浏览器兼容性,则使用本地API会成为一场噩梦。也许您不在意,但库开发人员在意。 - mpm
你有没有构建过这个? - John Riselvato
显示剩余7条评论
2个回答

14
尽管你可能认为使用JavaScript独立完成这个任务更好,但你应该明白,如果没有适当的数学理解,这可能会非常困难,可能需要比上面展示的插件更长的时间来弄清楚。总之,在Google上,我找到了几个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
好的,这不完全是我想要的,但比我预期的要多。感谢你为我花费时间。 - David Fariña

7

2
这应该是对原始答案的评论,而不是答案。 - froggomad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接