wp_back/wp-content/plugins/visual-portfolio/assets/js/items-style-fly.js
2024-05-20 15:37:46 +03:00

166 lines
4.3 KiB
JavaScript

import $ from 'jquery';
const $wnd = $(window);
/**
* Check if lines cross
*
* @param {Object} a - first point of the first line
* @param {Object} b - second point of the first line
* @param {Object} c - first point of the second line
* @param {Object} d - second point of the second line
*
* @return {boolean} cross lines
*/
function isCrossLine(a, b, c, d) {
// Working code #1:
//
// var common = (b.x - a.x)*(d.y - c.y) - (b.y - a.y)*(d.x - c.x);
// if (common === 0) {
// return false;
// }
//
// var rH = (a.y - c.y)*(d.x - c.x) - (a.x - c.x)*(d.y - c.y);
// var sH = (a.y - c.y)*(b.x - a.x) - (a.x - c.x)*(b.y - a.y);
//
// var r = rH / common;
// var s = sH / common;
//
// return r >= 0 && r <= 1 && s >= 0 && s <= 1;
// Working code #2:
const v1 = (d.x - c.x) * (a.y - c.y) - (d.y - c.y) * (a.x - c.x);
const v2 = (d.x - c.x) * (b.y - c.y) - (d.y - c.y) * (b.x - c.x);
const v3 = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
const v4 = (b.x - a.x) * (d.y - a.y) - (b.y - a.y) * (d.x - a.x);
return v1 * v2 <= 0 && v3 * v4 <= 0;
}
// Init Events.
$(document).on('initEvents.vpf', (event, self) => {
if (event.namespace !== 'vpf' || self.options.itemsStyle !== 'fly') {
return;
}
const evp = `.vpf-uid-${self.uid}`;
// determine cursor position
let lastCursorPos = {};
$wnd.on(`mousemove${evp}`, (e) => {
lastCursorPos = {
x: e.clientX,
y: e.clientY,
};
});
self.$item.on(
`mouseenter${evp} mouseleave${evp}`,
'.vp-portfolio__item',
function (e) {
const $this = $(this);
const itemRect = $this[0].getBoundingClientRect();
const $overlay = $this.find('.vp-portfolio__item-overlay');
const enter = e.type === 'mouseenter';
let endX = '0%';
let endY = '0%';
const curCursorPos = {
x: e.clientX,
y: e.clientY,
};
// find the corner that placed on cursor path.
let isUp = isCrossLine(
{ x: itemRect.left, y: itemRect.top },
{ x: itemRect.left + itemRect.width, y: itemRect.top },
curCursorPos,
lastCursorPos
);
let isDown = isCrossLine(
{ x: itemRect.left, y: itemRect.top + itemRect.height },
{
x: itemRect.left + itemRect.width,
y: itemRect.top + itemRect.height,
},
curCursorPos,
lastCursorPos
);
let isLeft = isCrossLine(
{ x: itemRect.left, y: itemRect.top },
{ x: itemRect.left, y: itemRect.top + itemRect.height },
curCursorPos,
lastCursorPos
);
let isRight = isCrossLine(
{ x: itemRect.left + itemRect.width, y: itemRect.top },
{
x: itemRect.left + itemRect.width,
y: itemRect.top + itemRect.height,
},
curCursorPos,
lastCursorPos
);
// Sometimes isCrossLine returned false, so we need to check direction manually (less accurate, but it is not a big problem).
if (!isUp && !isDown && !isLeft && !isRight) {
const x =
(itemRect.width / 2 - curCursorPos.x + itemRect.left) /
(itemRect.width / 2);
const y =
(itemRect.height / 2 - curCursorPos.y + itemRect.top) /
(itemRect.height / 2);
if (Math.abs(x) > Math.abs(y)) {
if (x > 0) {
isLeft = true;
} else {
isRight = true;
}
} else if (y > 0) {
isUp = true;
} else {
isDown = true;
}
}
if (isUp) {
endY = '-100.1%';
} else if (isDown) {
endY = '100.1%';
} else if (isLeft) {
endX = '-100.1%';
} else if (isRight) {
endX = '100.1%';
}
if (enter) {
$overlay.css({
transition: 'none',
transform: `translateX(${endX}) translateY(${endY}) translateZ(0)`,
});
// Trigger a reflow, flushing the CSS changes. This need to fix some glithes in Safari and Firefox.
// Info here - https://stackoverflow.com/questions/11131875/what-is-the-cleanest-way-to-disable-css-transition-effects-temporarily
// eslint-disable-next-line no-unused-expressions
$overlay[0].offsetHeight;
}
$overlay.css({
transition: '.2s transform ease-in-out',
transform: `translateX(${enter ? '0%' : endX}) translateY(${
enter ? '0%' : endY
}) translateZ(0)`,
});
}
);
});
// Destroy Events.
$(document).on('destroyEvents.vpf', (event, self) => {
if (event.namespace !== 'vpf' || self.options.itemsStyle !== 'fly') {
return;
}
const evp = `.vpf-uid-${self.uid}`;
$wnd.off(`mousemove${evp}`);
self.$item.off(`mouseenter${evp} mouseleave${evp}`);
});