Skip to content

Instantly share code, notes, and snippets.

@ryandejaegher
Last active May 19, 2021 18:47
Show Gist options
  • Select an option

  • Save ryandejaegher/f519c71b5999ea34b084441b1570e1cd to your computer and use it in GitHub Desktop.

Select an option

Save ryandejaegher/f519c71b5999ea34b084441b1570e1cd to your computer and use it in GitHub Desktop.
Image Follow Mouse #web-component #needs-work
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="h-full"></div>
<div class="row">
<hover-text image="https://source.unsplash.com/random?surfer" imageSize="35%" aspect="1/1"><a href="#">SURF</a></hover-text>
<hover-text image="https://source.unsplash.com/random?surfers" imageSize="35%" aspect="9/16"><a href="#">SURF LIFE</a></hover-text>
<hover-text image="https://source.unsplash.com/random?surf" imageSize="35%" aspect="9/16"><a href="#">SURFERS</a></hover-text>
<hover-text image="https://source.unsplash.com/random?surfing" imageSize="35%" aspect="9/16"><a href="#">SURF RENTALS</a></hover-text>
</div>
<div class="h-full"></div>
</body>
</html>
{
"scripts": [],
"styles": []
}
(function () {
var template = document.createElement('template');
template.innerHTML = /*html*/ `
<style>
:host {
--imageSize: 50%;
display: inline-block;
background: #fbb88d;
color: white;
font-family: sans-serif;
font-weight: 300;
letter-spacing:2px;
min-width: 6em;
text-align: center;
}
:host([aspect="1/1"]) figure {
--aspect-ratio: 100%;
}
:host([aspect="16/9"]) figure {
--aspect-ratio: 56.25%;
}
:host([aspect="3/2"]) figure {
--aspect-ratio: 66.7%;
}
:host([aspect="4/3"]) figure {
--aspect-ratio: 75%;
}
:host([aspect="9/16"]) figure {
--aspect-ratio: 177%;
}
figure {
position: relative;
padding-bottom: var(--aspect-ratio);
display: block;
visibility:hidden;
margin: 0;
opacity: 0;
transition-property: opacity, transform;
transition-duration: .2s, .5s, .5s;
transition-timing-function: cubic-bezier(0.22, 1, 0.36, 1),cubic-bezier(0.22, 1, 0.36, 1),cubic-bezier(0.22, 1, 0.36, 1);
}
img {
display: block;
position: absolute;
width: 100%;
max-width: 100%;
height: 100%;
display: block;
object-fit: cover;
z-index:-1;
transform: translate(-50%,-50%);
}
div {
position:absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
/* Change this to change image size */
width: var(--imageSize);
z-index:-2;
pointer-events: none;
}
::slotted(*) {
z-index: 10000;
display: inline-block;
padding: 12px 36px;
margin: 0;
font-size: 24px;
cursor: pointer;
color: white
}
</style>
<slot></slot>
<div><figure><img src=""></figure></div>
`;
// TODO: Add aspect ratio support for images
// TODO: Add image size support
// TODO: See if I can stop using top and left and switch to transform
// TODO: Add event listeners and consider adding a wrapper for the links
class HoverText extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.appendChild(template.content.cloneNode(true));
this._shadow = this.shadowRoot;
this.hoverImage = this.shadowRoot.querySelector('img');
this.addEventListener('mousemove', e => {
console.log(this.getBoundingClientRect())
// console.log(e);
setTimeout(() => {
this.updatePosition(e.clientX, e.clientY);
}, 60);
this._shadow.querySelector('figure').style.opacity = '1';
});
this.addEventListener('mouseleave', e => {
var figure = this.shadowRoot.querySelector('figure');
console.log(figure);
console.log(this.getBoundingClientRect())
figure.style.opacity = '0';
console.log(this)
//figure.style.transform = `translate(${this.getBoundingClientRect().x}px,${this.getBoundingClientRect().y}px,)`
//figure.style.left = this.getBoundingClientRect().x + 'px';
});
}
showImage() {
this._shadow.querySelector('figure').style.opacity = '1';
}
updatePosition(x, y) {
var figure = this.shadowRoot.querySelector('figure');
figure.style.transform = `translate(${x}px, ${y}px)`;
figure.style.visibility = 'visible';
//wow
}
static get observedAttributes() {
return ['image'];
}
get image() {
return this.hasAttribute('image');
}
set image(val) {
// Reflect the value of the image property as an HTML attribute.
if (val) {
this.setAttribute('image', val);
} else {
this.removeAttribute('image');
}
}
get imageSize() {
return this.hasAttribute('imageSize');
}
set imageSize(val) {
// Reflect the value of the imageSize property as an HTML attribute.
if (val) {
this.setAttribute('imageSize', val);
} else {
this.removeAttribute('imageSize');
}
}
checkImageSize() {
this.shadowRoot.querySelector('div').style.setProperty('--imageSize', this.getAttribute('imageSize'));
}
connectedCallback() {
this.hoverImage.src = this.getAttribute('image');
console.log(this.getAttribute('imageSize'));
this.checkImageSize();
}
}
window.customElements.define('hover-text', HoverText);
})();
body {
width: 100%;
height: 100%;
}
body > * + * {
margin-left: 36px;
}
.h-full {
height:100vh;
}
.row {
display: flex;
justify-content: center;
width: 100%;
grid-template-columns: 1fr 1fr;
grid-gap: 48px;
}
.block {
position: absolute;
top: 0%;
left: 0%;
bottom: 0%;
right: 0%;
width: 400px;
height: 400px;
z-index:-1;
background: lightblue;
transform:translate(-50%,-50%);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment