纯 Javascript 中的翻页效果

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15904594/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 02:31:42  来源:igfitidea点击:

Page Flip effect in pure Javascript

javascriptflipturnjs

提问by David Fari?a

For an ebook-reader webapp, im trying to make a fancy book-like viewer for the ebooks, like iBooks for iPad and iPhone.

对于电子书阅读器 web 应用程序,我正在尝试为电子书制作一个精美的书本查看器,例如 iPad 和 iPhone 的 iBooks。

I found that excellent jQuery Plugin which is exactly what im trying to reach. The only problem is, its a jQuery Plugin, so i cant use that. How could something like that'be done in pure Javascript?

我发现优秀的 jQuery 插件正是我想要达到的。唯一的问题是,它是一个 jQuery 插件,所以我不能使用它。像这样的事情怎么能用纯 Javascript 来完成?

Link to the jQuery page flip plugin: Turn JS jQuery Plugin

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

回答by John Riselvato

As much as you might think this is better to do with JavaScript alone, you should understand that it's might be very difficult and without the proper math understanding and all it's probably going to take you more time to figure out then the plug in you have shown above. In any case with Google I have found a couple jsfiddles that can possible get you in the right direction.

尽管您可能认为单独使用 JavaScript 会更好,但您应该明白这可能非常困难,并且没有正确的数学理解,并且所有这一切可能会花费您更多的时间来弄清楚您所展示的插件多于。在谷歌的任何情况下,我都找到了几个 jsfiddles 可以让你朝着正确的方向前进。

Pure JavaScript flip effect: http://jsfiddle.net/maitrekaio/nuUNd/

纯 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 flip effect (that shouldn't be an issue converting to pure JavaScript): http://jsfiddle.net/pixelass/TW43V/61/

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

Another jQuery flip effect: http://jsfiddle.net/wdm954/DkZsY/2/

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

because you want pure JavaScript know you'll need to figure out how to do this on your own. Using these examples as guidelines will be helpful even if they are not pure js.

因为您希望纯 JavaScript 知道您需要自己弄清楚如何做到这一点。使用这些示例作为指导将很有帮助,即使它们不是纯 js。

回答by eduard.dudar

This question is rather old but I'll place a reference where idea for approved answer has been taken from - http://www.html5rocks.com/en/tutorials/casestudies/20things_pageflip/. Good tutorial with explanation and examples.

这个问题相当古老,但我会在其中引用已批准答案的想法 - http://www.html5rocks.com/en/tutorials/casestudies/20things_pageflip/。很好的教程,有解释和例子。