Skip to content

Instantly share code, notes, and snippets.

@joeynimu
Created Mar 13, 2017
Embed
What would you like to do?
A Mousy module; moves element on mouse move.
var MousyModule = function () {
function MousyModule(opt) {
classCallCheck(this, MousyModule);
opt = opt || {};
this.name = 'mousy';
this.rotation = opt.rotation || 10.0;
this.parallax = {
enabled: true,
distance: 10,
scale: 1.1
};
}
createClass(MousyModule, [{
key: 'run',
value: function run() {
$(document).ready(this.attach.bind(this));
}
}, {
key: 'attach',
value: function attach() {
var _this = this;
if (window.ismobile) return;
this.$elements = $('.mousy');
this.$elements.mouseenter(function (e) {
return _this.enters(e);
});
this.$elements.mousemove(function (e) {
return _this.moved(e);
}); // faster than bind? maybe
this.$elements.mouseleave(function (e) {
return _this.exit(e);
}); // faster than bind? maybe
this.$elements.each(function (i, el) {
el.mousy = {
state: {
norm: { x: 0, y: 0 }, // normal vector, axis to rotate on
degree: 1 // how much should we rotate, based on distance to mid point => mid point equals zero degree
},
over: false, // check current mouse state
manipulatee: $(el).children('.mousy-target').get(0), // to be manipulated
animations: new AnimationStack(), // enter and exit animations
parallax: $(el).find('.mousy-parallax').toArray()
};
for (var i = 0; i < el.mousy.parallax.length; i++) {
$(el.mousy.parallax[i]).css('transform', 'scale(' + _this.parallax.scale + ')');
}
});
}
}, {
key: 'enters',
value: function enters(e) {
var _this2 = this;
var target = e.currentTarget,
mousy = target.mousy;
if (mousy.over || !window.hasfocus) // mouse is already over element
return;
mousy.animations.terminateAll(); // stop all running animations
mousy.over = true;
this.updateNormal(e);
animateByInterpolation(mousy.manipulatee, 600, {
easing: Easing.cubicBezier(0.175, 0.885, 0.32, 1.275),
tags: ['enter'],
interpolate: function interpolate(x) {
_this2.rotate(mousy, x); // el contains normX and normY
}
}).addToStack(mousy.animations).go();
}
// event handler: mouseleave
}, {
key: 'exit',
value: function exit(e) {
var _this3 = this;
var target = e.currentTarget,
mousy = target.mousy;
if (!mousy.over || !window.hasfocus) return;
mousy.animations.terminateAll(); // stop all running animations
mousy.over = false;
animateByInterpolation(mousy.manipulatee, 600, {
easing: Easing.cubicBezier(0.175, 0.885, 0.32, 1.275),
tags: ['exit'],
interpolate: function interpolate(x) {
_this3.rotate(mousy, 1.0 - x);
}
}).addToStack(mousy.animations).go();
}
// event handler: mousemove
}, {
key: 'moved',
value: function moved(e) {
var target = e.currentTarget,
mousy = target.mousy;
if (!window.hasfocus || !mousy.over) return;
this.updateNormal(e);
if (mousy.animations.length < 1) {
this.rotate(mousy, 1.0);
}
}
}, {
key: 'updateNormal',
value: function updateNormal(e) {
var target = e.currentTarget,
mousy = target.mousy,
state = mousy.state;
var parentOffset = $(target).parent().offset();
var parentWidth = $(target).parent().outerWidth();
var parentHeight = $(target).parent().outerHeight();
var relX = e.pageX - parentOffset.left;
var relY = e.pageY - parentOffset.top;
var X = Math.max(Math.min(2 * relX / parentWidth - 1.0, 1.0), -1.0);
var Y = Math.max(Math.min(2 * relY / parentHeight - 1.0, 1.0), -1.0);
state.norm.x = -Y; // calc normal vector, on which to rotate on
state.norm.y = X;
state.degree = Math.sqrt(X * X + Y * Y);
}
// helper: sets to transform of norm.normX and norm.normY and sets rotation to 10deg * ratio
}, {
key: 'rotate',
value: function rotate(m) {
var ratio = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1.0;
// set manipulatee transform
m.manipulatee.style.transform = 'perspective(1500px) rotate3d(' + m.state.norm.x + ',' + m.state.norm.y + ', 0, ' + this.rotation * m.state.degree * ratio + 'deg)';
// translate parralax items
for (var i = 0, dist = this.parallax.distance, scale = this.parallax.scale; i < m.parallax.length && this.parallax.enabled; i++) {
m.parallax[i].style.transform = 'translate3d(' + ratio * dist * -m.state.norm.y + 'px, ' + ratio * dist * m.state.norm.x + 'px, 0px) scale(' + scale + ')';
}
}
}]);
return MousyModule;
}();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment