|
gsap.registerPlugin(MotionPathPlugin, Draggable); |
|
|
|
let [outer, inner, alignFrom, alignTo] = gsap.utils.toArray("#outer, #inner, #align-from, #align-to"); |
|
|
|
function bad() { |
|
let fromBounds = alignFrom.getBoundingClientRect(), |
|
toBounds = alignTo.getBoundingClientRect(), |
|
deltaX = toBounds.left - fromBounds.left, |
|
deltaY = toBounds.top - fromBounds.top; |
|
|
|
gsap.to(alignFrom, { |
|
x: "+=" + deltaX, |
|
y: "+=" + deltaY, |
|
duration: 1 |
|
}); |
|
drawGlobal(); |
|
drawLocalBad(); |
|
} |
|
|
|
|
|
|
|
// here is where the magic is... |
|
function good() { |
|
let p = MotionPathPlugin.getRelativePosition(alignFrom, alignTo, [0, 0], {x: 100, y: 50}); |
|
gsap.to(alignFrom, { |
|
x: "+=" + p.x, |
|
y: "+=" + p.y, |
|
duration: 1 |
|
}); |
|
drawLocalGood(); |
|
} |
|
|
|
|
|
Draggable.create(alignTo, {type: "rotation", onRelease: good, zIndexBoost: false}); |
|
|
|
|
|
|
|
gsap.to(outer, {skewX: -20, scale: 0.85, x: -80}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let global = {}, |
|
local = {}, |
|
boundsElements = gsap.utils.toArray(".bounds"), |
|
boundsTween = gsap.to(".bounds", {autoAlpha: 1, reversed: true, duration: 0.3}), |
|
transformTween = gsap.to(inner, {rotation: 25, scale: 0.7, y: -25, x: -30, duration: 1, ease: "power1.inOut", reversed: true}).progress(0), |
|
xy = document.querySelector("#xy"), |
|
deltaX, deltaY, fromBounds, toBounds, moveTween, localDif; |
|
function setMeasurements() { |
|
fromBounds = alignFrom.getBoundingClientRect(); |
|
toBounds = alignTo.getBoundingClientRect(); |
|
localDif = MotionPathPlugin.getRelativePosition(alignFrom, alignTo); |
|
global.startX = fromBounds.left; |
|
global.startY = fromBounds.top; |
|
global.deltaX = toBounds.left - fromBounds.left; |
|
global.deltaY = toBounds.top - fromBounds.top; |
|
local.startX = alignFrom.offsetLeft + gsap.getProperty(alignFrom, "x"); |
|
local.startY = alignFrom.offsetTop + gsap.getProperty(alignFrom, "y"); |
|
gsap.set(boundsElements[0], {left: global.startX, top: global.startY, width: fromBounds.width, height: fromBounds.height}); |
|
gsap.set(boundsElements[1], {left: toBounds.left, top: toBounds.top, width: toBounds.width, height: toBounds.height}); |
|
} |
|
|
|
function showBounds() { |
|
(!moveTween || !moveTween.progress()) && setMeasurements(); |
|
boundsTween.reversed( !boundsTween.reversed() ); |
|
} |
|
|
|
function drawGlobal() { |
|
setMeasurements(); |
|
deltaX = global.deltaX; |
|
deltaY = global.deltaY; |
|
xy.innerHTML = "x: " + gsap.utils.snap(0.1, deltaX) + "<br>y: " + gsap.utils.snap(0.1, deltaY); |
|
boundsTween.play(); |
|
|
|
moveTween = gsap.getTweensOf(alignFrom)[0]; |
|
|
|
return gsap.timeline() |
|
.fromTo("#x-global", {x: global.startX, y: global.startY, scaleX: 0, transformOrigin: "left top", visibility: "visible"}, {scaleX: (deltaX + 6) / 100, duration: 1}) |
|
.fromTo("#y-global", {x: global.startX + deltaX, y: global.startY - 94, scaleY: 0, transformOrigin: "left bottom", visibility: "visible"}, {scaleY: (deltaY - 6) / -100, duration: 1}); |
|
} |
|
|
|
function drawLocalBad() { |
|
setMeasurements(); |
|
deltaX = global.deltaX; |
|
deltaY = global.deltaY; |
|
var startX = global.startX - 2, |
|
startY = global.startY - 52; |
|
xy.innerHTML = "x: " + gsap.utils.snap(0.1, deltaX) + "<br>y: " + gsap.utils.snap(0.1, deltaY); |
|
return gsap.timeline().fromTo("#x-local-bad", {x: startX, y: startY, scaleX: 0, transformOrigin: "left top", visibility: "visible"}, {scaleX: (deltaX + 6) / 100, duration: 1}) |
|
.fromTo("#y-local-bad", {x: startX + deltaX, y: startY - 94, scaleY: 0, transformOrigin: "left bottom", visibility: "visible"}, {scaleY: (deltaY - 6) / -100, duration: 1}); |
|
} |
|
|
|
function drawLocalGood() { |
|
setMeasurements(); |
|
deltaX = localDif.x; |
|
deltaY = localDif.y; |
|
xy.innerHTML = "x: " + gsap.utils.snap(0.1, deltaX) + "<br>y: " + gsap.utils.snap(0.1, deltaY); |
|
return gsap.timeline().fromTo("#x-local-good", {x: local.startX, y: local.startY, scaleX: 0, transformOrigin: "left top", visibility: "visible"}, {scaleX: (deltaX + 6) / 100, duration: 1}) |
|
.fromTo("#y-local-good", {x: local.startX + deltaX, y: local.startY - 94, scaleY: 0, transformOrigin: "left bottom", visibility: "visible"}, {scaleY: (deltaY - 6) / -100, duration: 1}); |
|
} |
|
|
|
function transform() { |
|
transformTween.reversed( !transformTween.reversed() ); |
|
} |
|
|
|
function move() { |
|
if (!moveTween || !moveTween.progress()) { |
|
moveTween && moveTween.progress(0).kill(); |
|
fromBounds || setMeasurements(); |
|
moveTween = gsap.to(alignFrom, { |
|
x: "+=" + deltaX, |
|
y: "+=" + deltaY, |
|
ease: "power1.inOut", |
|
duration: 1 |
|
}); |
|
} else { |
|
moveTween.reversed( !moveTween.reversed() ); |
|
} |
|
} |
|
|
|
function reset() { |
|
transformTween.reversed(true).progress(0); |
|
moveTween && moveTween.reversed(false).progress(0); |
|
boundsTween.reversed(true).progress(0); |
|
gsap.set(".bounds, .bar", {visibility: "hidden"}); |
|
gsap.set(alignFrom, {x:0, y:0, overwrite: true}); |
|
gsap.set([inner, outer, alignTo], {x:0, y:0, scale:1, rotation:0, skewX: 0, skewY: 0}); |
|
setMeasurements(); |
|
xy.innerHTML = ""; |
|
} |
|
|
|
document.querySelector("#btn-bounds").addEventListener("click", showBounds); |
|
document.querySelector("#btn-global").addEventListener("click", drawGlobal); |
|
document.querySelector("#btn-bad").addEventListener("click", drawLocalBad); |
|
document.querySelector("#btn-good").addEventListener("click", drawLocalGood); |
|
document.querySelector("#btn-transform").addEventListener("click", transform); |
|
document.querySelector("#btn-move").addEventListener("click", move); |
|
document.querySelector("#btn-reset").addEventListener("click", reset); |
|
|
|
|
|
function buildGrid(container, vars) { |
|
vars = vars || {}; |
|
let {width = 200, height = 200, rows = 2, colums = 3, colors = ["#161616", "#2F2F2F"], offset = 0} = vars, |
|
cells = [], |
|
y = 0, |
|
x, c, r, el, colorIndex; |
|
for (r = 0; r < rows; r++) { |
|
x = 0; |
|
y = r * height + offset; |
|
colorIndex = r % 2; |
|
for (c = 0; c < colums; c++) { |
|
el = document.createElement("div"); |
|
gsap.set(el, {position: "absolute", left: c * width + offset, top: y, width: (c === 2) ? width - 2 : width, height: height, backgroundColor: colors[colorIndex++ % 2], zIndex: -1 }); |
|
container.insertBefore(el, container.firstChild); |
|
cells.push(el); |
|
} |
|
} |
|
return cells; |
|
} |
|
|
|
buildGrid(inner); |