Files
heinstrom.com/js/main.js
2022-05-28 13:59:04 -04:00

223 lines
6.1 KiB
JavaScript

(function (window) {
"use strict";
// Helper vars and functions.
function extend(a, b) {
for (var key in b) {
if (b.hasOwnProperty(key)) {
a[key] = b[key];
}
}
return a;
}
function getMousePos(e) {
var posx = 0,
posy = 0;
if (!e) var e = window.event;
if (e.pageX || e.pageY) {
posx = e.pageX;
posy = e.pageY;
} else if (e.clientX || e.clientY) {
posx =
e.clientX +
document.body.scrollLeft +
document.documentElement.scrollLeft;
posy =
e.clientY +
document.body.scrollTop +
document.documentElement.scrollTop;
}
return { x: posx, y: posy };
}
/**
* TiltFx obj.
*/
function TiltFx(el, options) {
this.DOM = {};
this.DOM.el = el;
this.options = extend({}, this.options);
extend(this.options, options);
this._init();
}
TiltFx.prototype.options = {
movement: {
wrapper: {
translation: { x: 0, y: 0, z: 0 },
rotation: { x: -5, y: 5, z: 0 },
reverseAnimation: {
duration: 1200,
easing: "easeOutElastic",
elasticity: 600,
},
},
shine: {
translation: { x: 50, y: 50, z: 0 },
reverseAnimation: {
duration: 1200,
easing: "easeOutElastic",
elasticity: 600,
},
},
},
};
/**
* Init.
*/
TiltFx.prototype._init = function () {
this.DOM.animatable = {};
this.DOM.animatable.wrapper = this.DOM.el.querySelector(".card__figure");
this.DOM.animatable.shine = this.DOM.el.querySelector(
".card__deco--shine > div"
);
this._initEvents();
};
/**
* Init/Bind events.
*/
TiltFx.prototype._initEvents = function () {
var self = this;
this.mouseenterFn = function () {
for (var key in self.DOM.animatable) {
anime.remove(self.DOM.animatable[key]);
}
};
this.mousemoveFn = function (ev) {
requestAnimationFrame(function () {
self._layout(ev);
});
};
this.mouseleaveFn = function (ev) {
requestAnimationFrame(function () {
for (var key in self.DOM.animatable) {
if (self.options.movement[key] == undefined) {
continue;
}
anime({
targets: self.DOM.animatable[key],
duration:
self.options.movement[key].reverseAnimation != undefined
? self.options.movement[key].reverseAnimation.duration || 0
: 1,
easing:
self.options.movement[key].reverseAnimation != undefined
? self.options.movement[key].reverseAnimation.easing || "linear"
: "linear",
elasticity:
self.options.movement[key].reverseAnimation != undefined
? self.options.movement[key].reverseAnimation.elasticity || null
: null,
scaleX: 1,
scaleY: 1,
scaleZ: 1,
translateX: 0,
translateY: 0,
translateZ: 0,
rotateX: 0,
rotateY: 0,
rotateZ: 0,
});
}
});
};
this.debounceLeaveFn = function (e) {
e.stopPropagation();
clearTimeout(self.timeout);
self.timeout = setTimeout(() => {
self.mouseleaveFn();
}, 25);
};
this.DOM.el.addEventListener("mousemove", this.mousemoveFn);
this.DOM.el.addEventListener("mouseleave", this.mouseleaveFn);
this.DOM.el.addEventListener("mouseenter", this.mouseenterFn);
this.DOM.el.addEventListener("touchend", this.debounceLeaveFn);
};
TiltFx.prototype._layout = function (ev) {
// Mouse position relative to the document.
var mousepos = getMousePos(ev),
// Document scrolls.
docScrolls = {
left: document.body.scrollLeft + document.documentElement.scrollLeft,
top: document.body.scrollTop + document.documentElement.scrollTop,
},
bounds = this.DOM.el.getBoundingClientRect(),
// Mouse position relative to the main element (this.DOM.el).
relmousepos = {
x: mousepos.x - bounds.left - docScrolls.left,
y: mousepos.y - bounds.top - docScrolls.top,
};
// Movement settings for the animatable elements.
for (var key in this.DOM.animatable) {
if (
this.DOM.animatable[key] == undefined ||
this.options.movement[key] == undefined
) {
continue;
}
var t =
this.options.movement[key] != undefined
? this.options.movement[key].translation || { x: 0, y: 0, z: 0 }
: { x: 0, y: 0, z: 0 },
r =
this.options.movement[key] != undefined
? this.options.movement[key].rotation || { x: 0, y: 0, z: 0 }
: { x: 0, y: 0, z: 0 },
setRange = function (obj) {
for (var k in obj) {
if (obj[k] == undefined) {
obj[k] = [0, 0];
} else if (typeof obj[k] === "number") {
obj[k] = [-1 * obj[k], obj[k]];
}
}
};
setRange(t);
setRange(r);
var transforms = {
translation: {
x: ((t.x[1] - t.x[0]) / bounds.width) * relmousepos.x + t.x[0],
y: ((t.y[1] - t.y[0]) / bounds.height) * relmousepos.y + t.y[0],
z: ((t.z[1] - t.z[0]) / bounds.height) * relmousepos.y + t.z[0],
},
rotation: {
x: ((r.x[1] - r.x[0]) / bounds.height) * relmousepos.y + r.x[0],
y: ((r.y[1] - r.y[0]) / bounds.width) * relmousepos.x + r.y[0],
z: ((r.z[1] - r.z[0]) / bounds.width) * relmousepos.x + r.z[0],
},
};
this.DOM.animatable[key].style.WebkitTransform = this.DOM.animatable[
key
].style.transform =
"translateX(" +
transforms.translation.x +
"px) translateY(" +
transforms.translation.y +
"px) translateZ(" +
transforms.translation.z +
"px) rotateX(" +
transforms.rotation.x +
"deg) rotateY(" +
transforms.rotation.y +
"deg) rotateZ(" +
transforms.rotation.z +
"deg)";
}
};
window.TiltFx = TiltFx;
})(window);