<img src="https://picsum.photos/200/200"
data-creepyface
data-src-hover="https://picsum.photos/150/150"
data-src-look-0="https://picsum.photos/210/210"
data-src-look-45="https://picsum.photos/180/180"
data-src-look-135="https://picsum.photos/300/300"
data-src-look-225="https://picsum.photos/60/60"
data-src-look-315="https://picsum.photos/170/170"
/>
body{ display: flex;
flex-direction: column;
align-items: center;
margin-top:100px;
}
img{width:200px;}
/*
https://github.com/4lejandrito/creepyface
*/
! function(e, n) {
"object" == typeof exports && "undefined" != typeof module ? module.exports = n() : "function" == typeof define && define.amd ? define(n) : (e = e || self).creepyface = n()
}(this, function() {
"use strict";
var s = function(o, c) {
var u = [];
o.forEach(function(e) {
var n, t, r;
n = e, t = function(e) {
u.push(e), u.length === o.length && c(u)
}, (r = new Image).src = n, r.onload = r.onerror = function() {
r.naturalWidth || console.error("Creepyface was unable to load ".concat(n)), delete r.onload, delete r.onerror, t(r)
}
})
};
var c = function(n) {
return {
subscribe: function(e) {
return {
unsubscribe: n({
next: e
})
}
}
}
}, t = [];
document.addEventListener("mousemove", function(n) {
return t.forEach(function(e) {
return e.next([n.clientX, n.clientY])
})
}, !0);
var u = c(function(e) {
return t.push(e),
function() {
t.splice(t.indexOf(e), 1)
}
}),
i = function(e, t) {
return e.map(function(e, n) {
return e + t[n]
})
}, a = function(e) {
return e * Math.PI / 180
}, f = function(e) {
return n = Math.atan2(e[1], e[0]), t = 2 * Math.PI, 180 * ((t + n % t) % t) / Math.PI;
var n, t
}, n = [];
document.addEventListener("touchmove", function(o) {
return n.forEach(function(e) {
for (var n = [0, 0], t = 0; t < o.touches.length; t++) {
var r = o.touches[t];
n = i(n, [r.clientX, r.clientY])
}
e.next(n)
})
}, !0);
var l = c(function(e) {
return n.push(e),
function() {
n.splice(n.indexOf(e), 1)
}
}),
d = function() {}, r = function(e) {
var n = e ? parseFloat(e) : NaN;
return isNaN(n) ? void 0 : n
}, v = function(e) {
return {
hover: e.getAttribute("data-src-hover") || void 0,
looks: function(e) {
for (var n = /data-src-look-(\d+)/i, t = [], r = 0; r < e.attributes.length; r++) {
var o = e.attributes[r],
c = n.exec(o.name);
c && t.push({
angle: parseFloat(c[1]),
src: o.value
})
}
return t.length ? t : void 0
}(e),
timeToDefault: r(e.getAttribute("data-timetodefault")),
throttle: r(e.getAttribute("data-throttle")),
fieldOfVision: r(e.getAttribute("data-fieldofvision")),
resetOnCancel: !("false" === e.getAttribute("data-resetoncancel"))
}
};
function h(e) {
var t, n = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {}, r = function(o) {
for (var e = 1; e < arguments.length; e++) {
var c = null != arguments[e] ? arguments[e] : {}, n = Object.keys(c);
"function" == typeof Object.getOwnPropertySymbols && (n = n.concat(Object.getOwnPropertySymbols(c).filter(function(e) {
return Object.getOwnPropertyDescriptor(c, e).enumerable
}))), n.forEach(function(e) {
var n, t, r;
n = o, r = c[t = e], t in n ? Object.defineProperty(n, t, {
value: r,
enumerable: !0,
configurable: !0,
writable: !0
}) : n[t] = r
})
}
return o
}({}, v(e), n),
o = e.getAttribute("src");
if (!o) throw new Error("A default URL must be specified");
return {
fieldOfVision: r.fieldOfVision || 150,
src: o,
hover: r.hover || "",
points: r.points || (t = [u, l], c(function(n) {
var e = t.map(function(e) {
return e.subscribe(n.next)
});
return function() {
return e.forEach(function(e) {
return e.unsubscribe()
})
}
})),
looks: r.looks || [],
timeToDefault: r.timeToDefault || 1e3,
resetOnCancel: !(!1 === r.resetOnCancel),
throttle: r.throttle || 100,
onDebug: r.onDebug || d,
onAttach: r.onAttach || d,
onDetach: r.onDetach || d
}
}
var b = function(e) {
var n = e.getBoundingClientRect(),
t = n.top + window.pageYOffset + n.height / 2,
r = n.left + window.pageXOffset + n.width / 2;
return {
y: t,
x: r
}
};
var m = function(e, n) {
return f((o = i([window.scrollX, window.scrollY], n), u = b(e), c = [u.x, u.y], t = o.map(function(e, n) {
return e - c[n]
}), r = 90, [t[0] * Math.cos(a(r)) - t[1] * Math.sin(a(r)), t[0] * Math.sin(a(r)) + t[1] * Math.cos(a(r))]));
var t, r, o, c, u
}, p = function(e) {
return 180 < Math.abs(e) ? e - 360 * ((n = e) ? n < 0 ? -1 : 1 : 0) : e;
var n
}, g = function(e, n) {
return n.slice(0).sort((t = e, function(e, n) {
return Math.abs(p(e.angle - t)) - Math.abs(p(n.angle - t))
}))[0];
var t
}, y = function(e, n, t) {
return n <= e && e <= t
}, O = function(e, n) {
return document.elementFromPoint ? document.elementFromPoint(n[0], n[1]) === e : (t = e.getBoundingClientRect(), r = [n[0], n[1]], o = t.left, c = t.top, u = t.right, i = t.bottom, y(r[0], o, u) && y(r[1], c, i));
var t, r, o, c, u, i
}, w = function(h, b) {
return c(function(r) {
var e, n, t, o, c, u, i, a, f, s, l, d = (e = function() {
return r.next({
src: b.src,
options: b
})
}, n = b.timeToDefault, (o = function() {
t && clearTimeout(t), t = setTimeout(function() {
t = null, e()
}, n)
}).clear = function() {
t && (clearTimeout(t), t = null)
}, o),
v = b.points.subscribe((c = function(e) {
var n = m(h, e),
t = function(e, n, t, r) {
var o = r.looks,
c = r.hover,
u = r.fieldOfVision,
i = r.src;
if (c && O(e, n)) i = c;
else {
var a = g(t, o);
Math.abs(p(a.angle - t)) < u / 2 && (i = a.src)
}
return i
}(h, e, n, b);
r.next({
point: e,
angle: n,
src: t,
options: b
}), d()
}, u = b.throttle, f = 0, s = function() {
f = Date.now(), i = null, c(a)
}, (l = function(e) {
var n = Date.now(),
t = u - (n - f);
a = e, t <= 0 || u < t ? (i && (clearTimeout(i), i = null), f = n, c(e)) : i || (i = setTimeout(s, t))
}).clear = function() {
i && clearTimeout(i), f = 0, i = null
}, l));
return function() {
d.clear(), v.unsubscribe()
}
})
}, M = function(t, e) {
var n, r, o, c, u = h(t, e),
i = function(e) {
t.src = e
}, a = !1,
f = function() {
a = !0
};
return n = t, r = function(e) {
if (!a) {
u.onAttach();
var n = w(t, u).subscribe(function(e) {
i(e.src), u.onDebug(e)
});
f = function() {
n.unsubscribe(), u.resetOnCancel && i(u.src), u.onDetach(), e()
}
}
}, s((c = (o = u).looks.map(function(e) {
return e.src
}), o.src && c.push(o.src), o.hover && c.push(o.hover), c), function(e) {
n.creepyfaceReachableImages = e, r(function() {
delete n.creepyfaceReachableImages
})
}),
function() {
return f()
}
}, o = function e(n, t) {
e.cancel(n);
var r = d,
o = function(t, n, r) {
var o = function(e) {
return e ? n() : r()
};
if (MutationObserver) {
var c = document.body && document.body.contains(t);
c && o(!0);
var e = new MutationObserver(function(e) {
var n = document.body && document.body.contains(t);
!n && c ? (o(!1), c = !1) : n && !c && (o(!0), c = !0)
});
return e.observe(document, {
childList: !0,
subtree: !0
}),
function() {
return e.disconnect()
}
}
return document.body && document.body.contains(t) && o(!0), t.addEventListener("DOMNodeInserted", function() {
return o(!0)
}, !1), t.addEventListener("DOMNodeRemoved", function() {
return o(!1)
}, !1), d
}(n, function() {
r = M(n, t)
}, function() {
return e.cancel(n)
});
return n.creepyfaceCancel = function() {
o(), r(), delete n.creepyfaceCancel
}
};
return o.cancel = function(e) {
var n = e.creepyfaceCancel;
n && n()
}, document.addEventListener("DOMContentLoaded", function() {
for (var e = document.querySelectorAll("img[data-creepy],img[data-creepyface]"), n = 0; n < e.length; n++) {
var t = e[n];
t instanceof HTMLImageElement && o(t)
}
}), o
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.