Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save harunpehlivan/dba7b212f7bb191c742e89ddf225ca3f to your computer and use it in GitHub Desktop.

Select an option

Save harunpehlivan/dba7b212f7bb191c742e89ddf225ca3f to your computer and use it in GitHub Desktop.
Coordinate Conversion Demo (Video)
<div id="outer">outer<br>
<div id="inner">inner<br>
<div id="align-from">alignFrom</div>
</div>
</div>
<div id="align-to">alignTo</div>
<div id="xy"></div>
<div id="buttons">
<button id="btn-global">Global</button>
<button id="btn-bad">Local (bad)</button>
<button id="btn-good">Local (good)</button>
<button id="btn-move">Move</button>
<button id="btn-transform">Transform</button>
<button id="btn-bounds">Bounds</button>
<button id="btn-reset">Reset</button>
</div>
<div id="x-global" class="bar"></div>
<div id="y-global" class="bar"></div>
<a href="https://harunpehlivantebimtebitagem.site123.me/"><img class="gsap-3-logo" src="https://res.cloudinary.com/tercuman-b-l-m-merkez/image/upload/v1606081378/logo_transparent_ru2klx.png" width="150" /></a>
<div class="bounds"></div>
<div class="bounds"></div>
<script>
document.querySelector("#inner").innerHTML = 'inner<br><div id="align-from">alignFrom</div><div id="x-local-bad" class="bar"></div><div id="y-local-bad" class="bar"></div><div id="x-local-good" class="bar"></div><div id="y-local-good" class="bar"></div>';
</script>
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);
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.4/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.4/Draggable.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.4/MotionPathPlugin.min.js"></script>
body {
padding: 10px 15px;
overflow: hidden;
background-color: #111;
font-size: 24px;
color: #aaa;
}
* {
box-sizing: border-box;
}
#inner, #outer {
position: absolute;
border: 2px solid #555;
padding: 6px;
left: 0;
overflow: visible;
}
#outer {
width: 602px;
height: 454px;
top: 0;
left: 0;
}
#inner {
width: 602px;
height: 402px;
left: 0;
top: 50px;
border: none;
}
#align-from {
position: absolute;
background-color: #88ce02;
width: 160px;
line-height: 50px;
height: 50px;
color: black;
top: 200px;
left: 200px;
text-align: center;
z-index: 100;
}
#align-to {
background-color: purple;
width: 200px;
height: 200px;
line-height: 200px;
text-align: center;
color: white;
display: inline-block;
position: absolute;
top: 52px;
left: 602px;
z-index: -1;
}
.bar {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
top: 0;
left: 0;
z-index: 200;
visibility: hidden;
}
#x-global, #x-local-good, #x-local-bad {
height: 6px;
}
#y-global, #y-local-good, #y-local-bad {
width: 6px;
}
#x-local-good, #y-local-good, #x-local-bad, #y-local-bad {
background-color: orange;
z-index: 400;
}
#x-local-good, #y-local-good {
background-color: green;
}
#x-global, #y-global {
opacity: 0.6;
}
.bounds {
border: 2px solid blue;
position: absolute;
top: 0;
left: 0;
opacity: 0;
visibility: hidden;
z-index: 101;
pointer-events: none;
}
#buttons {
position: absolute;
text-align: left;
top: 45px;
right: 20px;
}
button {
font-size: 17px;
padding: 10px 16px;
display: block;
min-width: 160px;
margin: 5px;
color: #ccc;
outline: none;
border: none;
background: #414141;
background-image: linear-gradient(to bottom, #333, #222);
text-shadow: none;
box-shadow: none;
border-radius: 5px;
font-weight: 400;
}
#xy {
position: absolute;
top: 315px;
left: 620px;
font-weight: 300;
}
p {
font-weight: 300;
max-width: 900px;
display: inline-block;
text-align: left;
}
.gsap-3-logo {
width: 20vw;
max-width: 150px;
position: fixed;
bottom: 15px;
right: 15px;
}
<link href="https://codepen.io/GreenSock/pen/JGaKdQ" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment