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);
}