html5 canvas 制作相册动画,HTML5 Canvas GSAP 海盗相册

JavaScript

语言:

JaveScriptBabelCoffeeScript

确定

var container = document.getElementById('container'),

containerWidth = 768,

containerHeight = 768,

imageWidth = 768,

imageHeight = 512,

imageTop = (containerHeight - imageHeight) * 0.5,

imageBottom = imageTop + imageHeight,

imageTopLeft = new Point(0, imageTop),

imageTopRight = new Point(imageWidth, imageTop),

imageBottomLeft = new Point(0, imageBottom),

imageBottomRight = new Point(imageWidth, imageBottom);

var lineCanvas = document.getElementById('line_canvas'),

lineCtx = lineCanvas.getContext('2d'),

cuttingLine,

cutDelta = new Point();

var leftCanvas = document.getElementById('left_canvas'),

leftCtx = leftCanvas.getContext('2d'),

rightCanvas = document.getElementById('right_canvas'),

rightCtx = rightCanvas.getContext('2d');

var animating = false;

var images,

image,

imageIndex = 0;

var prevBtn = document.getElementById('prev_btn'),

nextBtn = document.getElementById('next_btn');

window.onload = function() {

getImages();

setupNavigation();

createCuttingLine();

updateButtonStates();

cut();

animate();

};

function getImages() {

images = document.getElementsByTagName('img');

image = images[imageIndex];

image.style.visibility = 'visible';

}

function setupNavigation() {

prevBtn.onclick = function() {

if (animating) return;

imageIndex--;

cut('prev');

animate();

updateButtonStates();

};

nextBtn.onclick = function() {

if (animating) return;

imageIndex++;

cut('next');

animate();

updateButtonStates();

};

}

function updateButtonStates() {

prevBtn.className = 'btn ' + (imageIndex === 0 ? 'disabled' : 'enabled');

nextBtn.className = 'btn ' + (imageIndex === (images.length - 1) ? 'disabled' : 'enabled');

}

function createCuttingLine() {

cuttingLine = new Line(new Point(), new Point(), '#fff');

}

function cut(dir) {

// hide image, reset canvases

image.style.visibility = 'hidden';

TweenMax.set([leftCanvas, rightCanvas], {

x: 0,

y: 0,

rotation: 0,

alpha: 1

});

leftCtx.clearRect(0, 0, imageWidth, imageHeight);

leftCtx.restore();

rightCtx.restore();

rightCtx.clearRect(0, 0, imageWidth, imageHeight);

// get random points on top and bottom line

if (dir == 'next') {

lerp(imageTopLeft, imageTopRight, randomRange(0.2, 0.4), cuttingLine.start);

lerp(imageBottomLeft, imageBottomRight, randomRange(0.6, 0.8), cuttingLine.end);

} else {

lerp(imageTopLeft, imageTopRight, randomRange(0.6, 0.8), cuttingLine.start);

lerp(imageBottomLeft, imageBottomRight, randomRange(0.2, 0.4), cuttingLine.end);

}

// clip left and right canvas

leftCtx.save();

leftCtx.beginPath();

leftCtx.moveTo(0, 0);

leftCtx.lineTo(cuttingLine.start.x, 0);

leftCtx.lineTo(cuttingLine.end.x, imageHeight);

leftCtx.lineTo(0, imageHeight);

leftCtx.closePath();

leftCtx.clip();

leftCtx.drawImage(image, 0, 0);

rightCtx.save();

rightCtx.beginPath();

rightCtx.moveTo(cuttingLine.start.x, 0);

rightCtx.lineTo(imageWidth, 0);

rightCtx.lineTo(imageWidth, imageHeight);

rightCtx.lineTo(cuttingLine.end.x, imageHeight);

rightCtx.closePath();

rightCtx.clip();

rightCtx.drawImage(image, 0, 0);

// get deltas

cutDelta.x = cuttingLine.end.x - cuttingLine.start.x;

cutDelta.y = cuttingLine.end.y - cuttingLine.start.y;

// make lines a little longer

cuttingLine.start.x -= cutDelta.x * 0.25;

cuttingLine.start.y -= cutDelta.y * 0.25;

cuttingLine.end.x += cutDelta.x * 0.25;

cuttingLine.end.y += cutDelta.y * 0.25;

}

function animate() {

animating = true;

var tl = new TimelineMax({

onComplete: function() {

animating = false

}

}),

firstCanvas,

secondCanvas,

rotationOrigin,

targetRotation;

if (cutDelta.x < 0) {

firstCanvas = leftCanvas;

secondCanvas = rightCanvas;

rotationOrigin = 'right top';

targetRotation = -45;

} else {

firstCanvas = rightCanvas;

secondCanvas = leftCanvas;

rotationOrigin = 'left top';

targetRotation = 45;

}

tl.append(cuttingLine.animateIn());

tl.to(container, 0.1, {

x: -16,

y: 16,

ease: RoughEase.ease

}, '+=0.2');

tl.to(container, 0.1, {

x: 16,

y: -16,

ease: RoughEase.ease

});

tl.to(container, 0.05, {

x: 0,

y: 0,

ease: RoughEase.ease

});

tl.append(cuttingLine.animateOut());

tl.to(firstCanvas, 0.6, {

x: '+=' + cutDelta.x,

y: '+=' + cutDelta.y,

ease: Quint.easeIn,

delay: 0.2

});

tl.to(firstCanvas, 0.4, {

alpha: 0,

ease: Quint.easeOut

}, '-=0.2');

tl.to(secondCanvas, 1, {

rotation: targetRotation,

transformOrigin: rotationOrigin,

ease: Back.easeOut

}, '+=0.1');

tl.to(secondCanvas, 0.6, {

y: '+=' + cutDelta.y,

ease: Quint.easeIn

}, '-=0.4');

tl.to(secondCanvas, 0.4, {

alpha: 0,

ease: Quint.easeOut

}, '-=0.2');

tl.fromTo(prepNextImage(), 0.5, {

y: -100,

alpha: 0

}, {

y: 0,

alpha: 1,

ease: Back.easeOut

});

}

function prepNextImage() {

image = images[imageIndex];

image.style.visibility = 'visible';

return image;

}

//

// Line and Point

//

function Line(start, end, color) {

this.start = start;

this.end = end;

this.color = color;

this.p0 = new Point();

this.p1 = new Point();

}

Line.prototype = {

animateIn: function() {

var tl = new TimelineMax({

onUpdate: this.draw,

onUpdateScope: this

});

this.p0.x = this.p1.x = this.start.x;

this.p0.y = this.p1.y = this.start.y;

tl.to(this.p1, 0.2, {

x: this.end.x,

y: this.end.y,

ease: Cubic.easeIn

});

return tl;

},

animateOut: function() {

var tl = new TimelineMax({

onUpdate: this.draw,

onUpdateScope: this

});

tl.to(this.p0, 0.2, {

x: this.end.x,

y: this.end.y,

ease: Cubic.easeIn

});

return tl;

},

draw: function() {

lineCtx.clearRect(0, 0, containerWidth, containerHeight);

lineCtx.lineWidth = 4;

lineCtx.lineCap = 'round';

lineCtx.strokeStyle = this.color;

lineCtx.beginPath();

lineCtx.moveTo(this.p0.x, this.p0.y);

lineCtx.lineTo(this.p1.x, this.p1.y);

lineCtx.stroke();

}

};

function Point(x, y) {

this.x = x || 0;

this.y = y || 0;

}

///

// UTILS

///

function lerp(p0, p1, t, tp) {

tp = tp || new Point();

tp.x = p0.x + t * (p1.x - p0.x);

tp.y = p0.y + t * (p1.y - p0.y);

return tp;

}

function randomRange(min, max) {

return min + Math.random() * (max - min);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值