UNPKG

vue-hover-effect

Version:

This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.

221 lines (213 loc) 7.03 kB
import { defineComponent as q, ref as B, onMounted as N, onUnmounted as j, openBlock as $, createElementBlock as J, Fragment as K, createElementVNode as Q, normalizeClass as X, renderSlot as Y } from "vue"; import * as n from "three"; import V from "gsap"; function Z(t) { console.log( "%c Hover effect (Single) by Robin Delaporte – https://github.com/robin-dela/hover-effect", "color: #bada55; font-size: 0.8rem" ); function i(...o) { return o.find((r) => r !== void 0); } const e = t.parent, d = t.displacementImage, p = t.image1, h = t.image2; if (!e) { console.warn("SingleHoverEffect: no parent element provided."); return; } if (!d || !p || !h) { console.warn("SingleHoverEffect: displacementImage/image1/image2 missing."); return; } const u = i(t.imagesRatio, 1), x = i(t.intensity1, t.intensity, 1), F = i(t.intensity2, t.intensity, 1), v = i(t.angle, Math.PI / 4), W = i(t.angle1, v), M = i(t.angle2, -v * 3), D = i(t.speedIn, t.speed, 1.6), T = i(t.speedOut, t.speed, 1.2), U = i(t.hover, !0), S = i(t.easing, "expo.out"), C = i(t.video, !1), O = new n.Scene(), H = new n.OrthographicCamera( e.offsetWidth / -2, e.offsetWidth / 2, e.offsetHeight / 2, e.offsetHeight / -2, 1, 1e3 ); H.position.z = 1; const f = new n.WebGLRenderer({ alpha: !0, antialias: !1 }); f.setPixelRatio(window.devicePixelRatio), f.setClearColor(16777215, 0), f.setSize(e.offsetWidth, e.offsetHeight), e.appendChild(f.domElement); function c() { f.render(O, H); } const A = ` varying vec2 vUv; void main(){ vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); } `, k = ` varying vec2 vUv; uniform float dispFactor; uniform sampler2D disp; uniform sampler2D texture1; uniform sampler2D texture2; uniform float angle1; uniform float angle2; uniform float intensity1; uniform float intensity2; uniform vec4 res; mat2 getRotM(float angle){ float s = sin(angle); float c = cos(angle); return mat2(c, -s, s, c); } void main(){ // displacement vec4 dispTex = texture2D(disp, vUv); vec2 dispVec = dispTex.rg; // Simple approach vec2 uv = vUv; vec2 distortedPos1 = uv + getRotM(angle1) * dispVec * intensity1 * dispFactor; vec2 distortedPos2 = uv + getRotM(angle2) * dispVec * intensity2 * (1.0 - dispFactor); vec4 _texture1 = texture2D(texture1, distortedPos1); vec4 _texture2 = texture2D(texture2, distortedPos2); gl_FragColor = mix(_texture1, _texture2, dispFactor); } `, w = new n.TextureLoader(); w.crossOrigin = ""; const b = w.load(d, c); b.magFilter = b.minFilter = n.LinearFilter; let a, s; if (C) { const o = document.createElement("video"); o.autoplay = !0, o.loop = !0, o.muted = !0, o.src = p, o.load(); const r = document.createElement("video"); r.autoplay = !0, r.loop = !0, r.muted = !0, r.src = h, r.load(), a = new n.VideoTexture(o), s = new n.VideoTexture(r), a.magFilter = a.minFilter = n.LinearFilter, s.magFilter = s.minFilter = n.LinearFilter, o.addEventListener("loadeddata", () => { o.play(), a = new n.VideoTexture(o), a.magFilter = a.minFilter = n.LinearFilter, g.uniforms.texture1.value = a; }), r.addEventListener("loadeddata", () => { r.play(), s = new n.VideoTexture(r), s.magFilter = s.minFilter = n.LinearFilter, g.uniforms.texture2.value = s; }), requestAnimationFrame(function l() { requestAnimationFrame(l), f.render(O, H); }); } else a = w.load(p, c), s = w.load(h, c), a.magFilter = a.minFilter = n.LinearFilter, s.magFilter = s.minFilter = n.LinearFilter; let y = 1, E = 1; function R(o, r) { const l = o || e.offsetWidth, m = r || e.offsetHeight; m / l < u ? (y = 1, E = m / l / u) : (y = l / m * u, E = 1); } R(); const g = new n.ShaderMaterial({ uniforms: { dispFactor: { value: 0 }, disp: { value: b }, texture1: { value: a }, texture2: { value: s }, angle1: { value: W }, angle2: { value: M }, intensity1: { value: x }, intensity2: { value: F }, res: { value: new n.Vector4( e.offsetWidth, e.offsetHeight, y, E ) } }, vertexShader: A, fragmentShader: k, transparent: !0, opacity: 1 }), G = new n.PlaneGeometry(e.offsetWidth, e.offsetHeight, 1), z = new n.Mesh(G, g); O.add(z); function L() { V.to(g.uniforms.dispFactor, { duration: D, value: 1, ease: S, onUpdate: c, onComplete: c }); } function I() { V.to(g.uniforms.dispFactor, { duration: T, value: 0, ease: S, onUpdate: c, onComplete: c }); } U && (e.addEventListener("mouseenter", L), e.addEventListener("mouseleave", I), e.addEventListener("touchstart", L), e.addEventListener("touchend", I)); function P(o, r) { const l = o || e.offsetWidth, m = r || e.offsetHeight; f.setSize(l, m), R(l, m), g.uniforms.res.value.set( l, m, y, E ), z.geometry = new n.PlaneGeometry( l, m, 1 ), c(); } return window.addEventListener("resize", () => P()), { next: L, // image1 → image2 previous: I, // image2 → image1 resize: P }; } const te = /* @__PURE__ */ q({ __name: "SingleHoverEffect", props: { hoverOptions: { default: () => ({ image1: "/lib-images/images/Img22.webp", image2: "/lib-images/images/Img21.webp", displacementImage: "/lib-images/displacements/3.webp", hover: !0, speedIn: 0.8, speedOut: 0.8 }) }, distortionClass: { default: "" } }, setup(t) { const i = B(null); let e, d; N(() => { i.value && (e = Z({ ...t.hoverOptions, parent: i.value, image1: t.hoverOptions.image1, image2: t.hoverOptions.image2, displacementImage: t.hoverOptions.displacementImage, hover: t.hoverOptions.hover, speedIn: t.hoverOptions.speedIn, speedOut: t.hoverOptions.speedOut }), window.ResizeObserver && (d = new ResizeObserver((u) => { var x, F; for (const v of u) v.target === i.value && (e == null || e.resize((x = v.target) == null ? void 0 : x.clientWidth, (F = v.target) == null ? void 0 : F.clientHeight)); }), d.observe(i.value))); }); function p() { e == null || e.next(); } function h() { e == null || e.previous(); } return j(() => { e = void 0, d && i.value && (d.unobserve(i.value), d.disconnect()); }), (u, x) => ($(), J(K, null, [ Q("div", { ref_key: "container", ref: i, class: X(["distortion-container", u.distortionClass]) }, null, 2), Y(u.$slots, "controllers", { funcs: { goNext: p, goPrev: h } }) ], 64)); } }); export { te as SingleHoverEffect, Z as createSingleHoverEffect };