I have managed to put together a custom cursor that changes when hovering on different data-type. For this example, when you hover on the first image the cursor changes to a pause icon, when you hover on the second image the cursor changes to a play icon, I would like to change the play icon to just the text "play" instead of the icon.
const cursor = document.getElementById("cursor");
const animateCursor = (e, interacting) => {
const x = e.clientX - cursor.offsetWidth / 2,
y = e.clientY - cursor.offsetHeight / 2;
const keyframes = {
transform: `translate(${x}px, ${y}px) scale(${interacting ? 8 : 1})`
}
cursor.animate(keyframes, {
duration: 800,
fill: "forwards"
});
}
const getCursorClass = type => {
switch(type) {
case "video":
return "fa-solid fa-play";
case "image":
return "fa-solid fa-pause";
default:
return "fa-solid fa-arrow-up-right";
}
}
window.onmousemove = e => {
const interactable = e.target.closest(".interactable"),
interacting = interactable !== null;
const icon = document.getElementById("cursor-icon");
animateCursor(e, interacting);
cursor.dataset.type = interacting ? interactable.dataset.type : "";
if(interacting) {
icon.className = getCursorClass(interactable.dataset.type);
}
}
body {
background-color: rgb(20, 20, 20);
height: 100vh;
margin: 0px;
display: flex;
align-items: center;
justify-content: center;
gap: clamp(10px, 4vw, 100px);
}
body:hover > #cursor {
opacity: 1;
}
#cursor {
height: 20px;
width: 20px;
background-color: white;
border-radius: 20px;
position: fixed;
left: 0px;
top: 0px;
z-index: 10000;
pointer-events: none;
opacity: 0;
transition: opacity 500ms ease;
display: grid;
place-items: center;
}
#cursor:not([data-type=""]) > #cursor-icon {
opacity: 1;
}
#cursor-icon {
font-size: 6px;
line-height: 0px;
opacity: 0;
transition: opacity 400ms ease;
}
.interactable {
aspect-ratio: 1 / 1.5;
width: clamp(120px, 40vmin, 600px);
background-position: center 50%;
background-size: 100%;
opacity: 0.4;
transition: background-size 400ms ease, opacity 400ms ease;
}
.interactable:hover {
background-size: 105%;
opacity: 0.8;
}
<script src="https://kit.fontawesome.com/944eb371a4.js"></script>
<div id="cursor">
<i id="cursor-icon" class="fa-solid fa-arrow-up-right"></i>
</div>
<div
class="interactable"
data-type="image"
style="background-image: url(https://images.unsplash.com/photo-1657739774592-14c8f97eaece?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwyfHx8ZW58MHx8fHw%3D&auto=format&fit=crop&w=500&q=60)">
</div>
<div
class="interactable"
data-type="video"
style="background-image: url(https://images.unsplash.com/photo-1657779582398-a13b5896ff19?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwzNXx8fGVufDB8fHx8&auto=format&fit=crop&w=500&q=60)">
</div>
Add a new class named play in the css file
.play::after {
content: "Play";
font-style: normal;
}
Then add the new class name in the following portion of the JS file.
const getCursorClass = type => {
switch(type) {
case "video":
return "play"; // <--- add the class name here
case "image":
return "fa-solid fa-pause";
default:
return "fa-solid fa-arrow-up-right";
}
}
Codepen URL
There is no built-in way to do this, but it is possible with a little bit of CSS.
First, you need to add a span element after the cursor. This will be the element that contains the text that you want to display on hover.
<span class="cursor-text">Text that appears on hover</span>
Then, you need to add some CSS to position the span element and to hide it by default.
.cursor-text { position: absolute; top: 0; left: 0; opacity: 0; }
Finally, you need to add a CSS rule to show the span element on hover.
.cursor:hover .cursor-text { opacity: 1; }
Related
I am trying to add a material ripple effect to an element using pure javascript using the code below. The problem is that the effect works only for the first click.
If I try to click the button again, I get the message Uncaught TypeError: circle is undefined on my console.
function createRipple(event) {
const target = event.currentTarget;
const circle = target.classList.add("ripple");
const ripple = circle.getElementsByClassName("ripple")[0];
if (ripple) {
ripple.remove();
}
}
const buttons = document.getElementsByClassName("my-ripple");
for (const button of buttons) {
button.addEventListener("click", createRipple);
}
.my-ripple {
position: relative;
overflow: hidden;
display: inline-block;
width: auto;
padding: 1.2rem;
font-family: sans;
cursor: pointer;
border-radius: 10px;
}
.ripple::after {
content: "";
position: absolute;
border-radius: 50%;
transform: scale(0);
animation: ripple 600ms linear;
background-color: rgba(0, 0, 0, 0.5);
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
width: 100px;
height: 100px;
}
#keyframes ripple {
to {
transform: scale(4);
opacity: 0;
}
}
<div class="my-ripple">Click me</div>
classList does not return an object. And you do not need it actually, because you already have the target instance, so fetching it again by class is not necessary. Instead just remove the class from it directly with a timeout:
function createRipple(event) {
const target = event.currentTarget;
target.classList.add("ripple");
setTimeout(function() {
target.classList.remove("ripple");
}, 600);
}
THE WHOLE CODE IN JSFIDDLE
I have been struggling to effectively remove the code and css created in the function Seifenblasen_blasen()
function Seifenblasen_blasen(){
btn1.style.display = 'none';
document.getElementById("text").innerHTML="Bubble"
const section = document.querySelector('section')
const createElement = document.createElement('spawn')
var size = Math.random() * 60;
createElement.style.width = 30 + size + 'px';
createElement.style.height = 30 + size + 'px';
createElement.style.left = Math.random() * innerWidth + "px";
section.appendChild(createElement);
setTimeout(() => {
createElement.remove()
},8000)
}
const Blaseninterval = setInterval(Seifenblasen_blasen, 100)
created CSS:
section {
width: 100%;
height: 100vh;
overflow: hidden;
background: #1F69FA;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
section.text{
font-size: 10em;
color: #333;
margin: 0 auto;
text-align: center;
font-family: consolas;
background-color:#1F69FA;
pointer-events: none;
border: none;
}
section spawn {
position: absolute;
bottom: -80px;
background: transparent;
border-radius: 50%;
pointer-events: none;
box-shadow: inset 0 0 10px rgba(255, 255, 255, 0.5);
animation: animate 4s linear infinite;
}
section spawn:before {
content: '';
position: absolute;
width: 100%;
height: 100%;
transform: scale(0.25) translate(-70%, -70%);
background: radial-gradient(#fff, transparent);
opacity: 0.6;
border-radius: 50%;
}
#keyframes animate {
0% {
transform: translateY(0%);
opacity: 1;
}
99% {
opacity: 1;
}
100% {
transform: translateY(-2000%);
opacity: 0;
}
section span {
margin-top: 700px;
font-size: 1em;
color: #333;
margin: 0 auto;
font-family: consolas;
background-color: #1F69FA;
border: none;
position: absolute;
}
HTML:
<section id="section">
<div class="content">
<button id="btn"></button>
<button id="btn1"></button>
</div>
</section>
to then execute the next function function next(). This removal is needed because when I don't remove the elements from the first function the second wont work. I could just do document.head.innerHTML = "" but that would then also remove the css needed for the button appearing in the next function. So then I tried to make variables with const
const btn = document.getElementById('text');
const btn1 = document.getElementById('text1');
const section = document.querySelector('section')
// in function Seifenblasen_blasen()
btn1.style.display = 'none';
// in function next()
section.style.display = 'none';
btn.style.display = 'none';
btn1.style.display = 'block';
to hide and show only parts of the css without removing the css entirely to keep the styling intact, but now nothing works anymore.(the button on the next Screen doesn't show up at all and the first button does not contain any styling) My endgoal is that I can essentially switch between two screens one showing the bubbles and one the bouncy balls and when I click on the button it goes on. (for example start is bubbles. I click -> Bounce, click again -> back to Bubbles and so on)
I tried to find a solution for this one but I can't. There s something that I keep missing... not sure what.
I have a project that when I click a image, the image will get an translate and also a text description.
The text description has a smooth transition and it looks cool.
Well, the question is.. how to make the reset(click on body or another image) to have the same transition for that text description?
This is how it look right now: https://im3.ezgif.com/tmp/ezgif-3-5150d8ffbf.gif
function resetEnlargeEntityImage() {
if(enlargedEntity != null) {
enlargedEntity.style.transform = null;
enlargedEntity.style.transition = null;
enlargedEntity.classList.add("planet-svg-hover");
document.getElementById("planets-description-paragraph").innerHTML = null;
document.getElementById("planets-description-paragraph").classList.add("entity-description-js");
document.getElementById("planets-description-paragraph").classList.remove("entity-description-appear-js");
}
}
function enlargeEntityImage(clickedImage, clickedImageId) {
let mediaQuery = window.matchMedia('(max-width: 375px)');
if(mediaQuery.matches) {
window.location.href = `./${planetsName[clickedImageId]}.html`;
} else {
resetEnlargeEntityImage();
var xToMove = 260 - 130 * clickedImageId; //260
clickedImage.style.transform = "translate(" + xToMove + "px, 320px) scale(4.0)";
clickedImage.style.transition = "transform 1s ease-in-out";
clickedImage.classList.remove("planet-svg-hover");
document.getElementById("planets-description-paragraph").innerHTML = descriptionSpaceObjects[clickedImageId];
document.getElementById("planets-description-paragraph").classList.remove("entity-description-js");
document.getElementById("planets-description-paragraph").classList.add("entity-description-appear-js");
enlargedEntity = clickedImage;
}
}
.planets-description {
color: white;
font-family: "Barlow";
font-size: 30px;
width: 600px;
position: relative;
top: 100px;
left: 700px;
}
.entity-description-js {
position: absolute;
transition-delay: 1s;
transition: 1s;
width: 600px;
left: 0;
visibility: hidden;
opacity: 0;
}
.entity-description-appear-js {
position: absolute;
transition: 1s;
width: 600px;
left: 100px;
visibility: visible;
opacity: 1;
}
<div class="planets-description">
<p id="planets-description-paragraph" class="entity-description-js"></p>
</div>
The Code you provided isnt showing anything, but maybe you could try uesing the "transition" property in css.
I'm trying recoding the https://www.orizon.co/ following dot. The code I've written to asure the dot rising effect when the pointer fly over some elements seems correct, but when the dot's z-index is higher than the flew over element's one, there is a kind of bug than make me crazy.
class CursorFollower {
constructor() {
this.follower = document.getElementById("cursor-follower");
this.topGap = 12;
this.leftGap = 4;
window.addEventListener("mousemove", this.follow.bind(this));
this.eventsSet();
}
// The function doing the dot follows the pointer
follow() {
setTimeout(function () {
cursorFollower.follower.style.left = (this.clientX - cursorFollower.topGap) + "px";
cursorFollower.follower.style.top = (this.clientY - cursorFollower.leftGap) + "px";
}.bind(window.event), 100);
}
eventsSet() {
// Adding events to button
var button = document.querySelector(".follower-over");
button.addEventListener("pointerenter", this.overOn.bind(this));
button.addEventListener("pointerleave", this.overOff.bind(this));
}
overOn() {
// The effects to apply when the pointer flies over the button
this.follower.style.opacity = 0.3;
this.follower.style.width = "50px";
this.follower.style.height = "50px";
this.follower.style.backgroundColor = "black";
this.topGap = 25;
this.leftGap = 25;
}
overOff() {
// The effects to apply when the pointer leave the button
this.follower.style.opacity = 1;
this.follower.style.width = "7px";
this.follower.style.height = "7px";
this.follower.style.backgroundColor = "rgba(42, 0, 212, 1)";
this.topGap = 12;
this.leftGap = 4;
}
}
let cursorFollower = new CursorFollower();
/* Some styling */
.contact-us{
padding: 25px 40px;
width: 200px;
display: flex;
align-items: center;
color: white;
background-color: #2b00d4 ;
height: 60px;
position: relative;
z-index: 1;
}
#cursor-follower{
z-index: 999;
position: fixed;
background-color: #2b00d4;
height: 7px;
width: 7px;
border-radius: 50%;
transition: opacity 0.3s , width 0.3s , height 0.3s, background-color 0.3s;
}
<div id="cursor-follower"></div>
<div class="contact-us follower-over">
<p>CONTACT US</p>
</div>
When the button's z-index is higher than the dot's one, the effects works. Else, it bugs
This is because your follower element is getting under cursor, triggering overOff than when its shrinks it triggers overOn and so on.
The simplest solution is to add pointer-events: none; into the follower so it doesn't trigger overOn/overOff:
class CursorFollower {
constructor() {
this.follower = document.getElementById("cursor-follower");
this.topGap = 12;
this.leftGap = 4;
window.addEventListener("mousemove", this.follow.bind(this));
this.eventsSet();
}
// The function doing the dot follows the pointer
follow() {
setTimeout(function() {
cursorFollower.follower.style.left = (this.clientX - cursorFollower.topGap) + "px";
cursorFollower.follower.style.top = (this.clientY - cursorFollower.leftGap) + "px";
}.bind(window.event), 100);
}
eventsSet() {
// Adding events to button
var button = document.querySelector(".follower-over");
button.addEventListener("pointerenter", this.overOn.bind(this));
button.addEventListener("pointerleave", this.overOff.bind(this));
}
overOn() {
// The effects to apply when the pointer flies over the button
this.follower.style.opacity = 0.3;
this.follower.style.width = "50px";
this.follower.style.height = "50px";
this.follower.style.backgroundColor = "black";
this.topGap = 25;
this.leftGap = 25;
}
overOff() {
// The effects to apply when the pointer leave the button
this.follower.style.opacity = 1;
this.follower.style.width = "7px";
this.follower.style.height = "7px";
this.follower.style.backgroundColor = "rgba(42, 0, 212, 1)";
this.topGap = 12;
this.leftGap = 4;
}
}
let cursorFollower = new CursorFollower();
/* Some styling */
.contact-us {
padding: 25px 40px;
width: 200px;
display: flex;
align-items: center;
color: white;
background-color: #2b00d4;
height: 60px;
position: relative;
z-index: 1;
}
#cursor-follower {
pointer-events: none; /* added */
z-index: 999;
position: fixed;
background-color: #2b00d4;
height: 7px;
width: 7px;
border-radius: 50%;
transition: opacity 0.3s, width 0.3s, height 0.3s, background-color 0.3s;
}
<div id="cursor-follower"></div>
<div class="contact-us follower-over">
<p>CONTACT US</p>
</div>
However there is even simpler solution with much less javascript:
window.addEventListener("mousemove", e => {
setTimeout(s => {
document.documentElement.style.setProperty("--cursorX", e.clientX + "px");
document.documentElement.style.setProperty("--cursorY", e.clientY + "px");
}, 100);
});
/* Some styling */
:root
{
--cursorX: -100px;
--cursorY: -100px;
}
.contact-us {
padding: 25px 40px;
width: 100px;
display: flex;
align-items: center;
color: white;
background-color: #2b00d4;
height: 40px;
position: relative;
z-index: 1;
}
.cursor-follower {
--size: 7px;
--gapLeft: 12px;
--gapTop: 4px;
pointer-events: none;
position: fixed;
background-color: #2b00d4;
width: var(--size);
height: var(--size);
border-radius: 50%;
transition: opacity 0.3s, width 0.3s, height 0.3s, background-color 0.3s;
top: calc(var(--cursorY) - var(--gapTop));
left: calc(var(--cursorX) - var(--gapLeft));
}
.follower-over:hover~.cursor-follower {
--size: 50px;
--gapLeft: 25px;
--gapTop: 25px;
opacity: 0.3;
background-color: black;
z-index: 2;
}
/* extra */
.follower-over.green:hover~.cursor-follower {
background-color: green;
opacity: 0.7;
--size: 80px;
--gapLeft: 40px;
--gapTop: 40px;
}
.contact-us:not(.follower-over) {
background-color: pink;
}
.contact-us {
display: inline-block;
margin: 1em;
}
<div class="contact-us follower-over">
<p>CONTACT US</p>
</div>
<div class="contact-us follower-over">
<p>Another button</p>
</div>
<div class="contact-us">
<p>No follower</p>
</div>
<div class="contact-us follower-over green">
<p>Large green</p>
</div>
<div class="cursor-follower"></div>
The only caveat with this method is the .cursor-follower must be last element and has the same parent as all .follower-over elements
This is my new clear site: www.talas.me
And this is what i want to copy: Awesome Link Hover Effect / Animated Cursor
(function () {
const link = document.querySelectorAll('nav > .hover-this');
const cursor = document.querySelector('.cursor');
const animateit = function (e) {
const span = this.querySelector('span');
const { offsetX: x, offsetY: y } = e,
{ offsetWidth: width, offsetHeight: height } = this,
move = 25,
xMove = x / width * (move * 2) - move,
yMove = y / height * (move * 2) - move;
span.style.transform = `translate(${xMove}px, ${yMove}px)`;
if (e.type === 'mouseleave') span.style.transform = '';
};
const editCursor = e => {
const { clientX: x, clientY: y } = e;
cursor.style.left = x + 'px';
cursor.style.top = y + 'px';
};
link.forEach(b => b.addEventListener('mousemove', animateit));
link.forEach(b => b.addEventListener('mouseleave', animateit));
window.addEventListener('mousemove', editCursor);
})();
html, body {
margin: 0;
padding: 0;
cursor: none;
}
.nav-wrapper {
width: 100%;
height: 100vh;
background: #161616;
}
nav {
width: 100%;
margin: 0 auto;
text-align: center;
position: absolute;
top: 50%;
}
.hover-this {
transition: all 0.3s ease;
}
span {
display: inline-block;
font-family: "Monument Extended";
font-weight: 300;
color: #fff;
font-size: 36px;
text-transform: uppercase;
pointer-events: none;
transition: transform 0.1s linear;
}
.cursor {
pointer-events: none;
position: fixed;
padding: 0.3rem;
background-color: #fff;
border-radius: 50%;
mix-blend-mode: difference;
transition: transform 0.3s ease;
}
.hover-this:hover ~ .cursor {
transform: translate(-50%, -50%) scale(8);
}
#media(min-width: 900px) {
nav {
display: flex;
justify-content: space-around;
}
}
#media(max-width: 900px) {
nav {
top: 30%;
}
.hover-this {
width: 100%;
padding: 20px 0;
display: inline-block;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="nav-wrapper">
<nav>
<span>Home</span>
<span>Our Story</span>
<span>Studio</span>
<span>Contact</span>
<div class="cursor"></div>
</nav>
</div>
There is problem somewhere and i can't figure out where. As you can see now (when i copy this code correctly) we can't see the cursor on my site.
Can someone tell me what is the problem and how to fix it?
This is very important for my site because the site will be black and white, and this cursor effect is so important to me.
Thank you!
as far as i know that Divi theme provide a option in theme settings where we can add custom jQuery or javascript so you can directly add over there
this below link may help you to resolve issue
https://divi.space/tutorials/how-to-add-javascript-and-jquery-to-divi/