简体   繁体   中英

Cannot make the hover effect work for all children

I'm trying to apply a 3d rotation hover effect on the child elements of a container, but I'm having difficulty to make it work with for loop. Code works fine when I remove the loop and [i] tags, and use the effect on a single element, but it doesn't when I try to apply the effect on all child elements. Do you know what part I'm doing wrong?

let rotate = document.getElementsByClassName("group")[0].getElementsByTagName("a");
var i; 
for (i=0; i<rotate.length; i++) {
    const height = rotate[i].clientHeight;
    const width = rotate[i].clientWidth;
    rotate[i].addEventListener('mousemove', handleMove)

    function handleMove(e) {
        const xVal = e.layerX;
        const yVal = e.layerY;
        const yRotation = 20 * ((xVal - width / 2) / width);
        const xRotation = -20 * ((yVal - height / 2) / height);
        const string = 'perspective(500px) scale(1.1) rotateX(' + xRotation + 'deg) rotateY(' + yRotation + 'deg)';
        rotate[i].style.transform = string;
    }
    rotate[i].addEventListener('mouseout', function() {rotate[i].style.transform = 'perspective(500px) scale(1) rotateX(0) rotateY(0)'})
    rotate[i].addEventListener('mousedown', function() {rotate[i].style.transform = 'perspective(500px) scale(0.9) rotateX(0) rotateY(0)'})
    rotate[i].addEventListener('mouseup', function() {rotate[i].style.transform = 'perspective(500px) scale(1.1) rotateX(0) rotateY(0)'})
}

https://codepen.io/technokami/pen/abojmZa

You can use querySelectorAll() to get an array of selected elements (use css selector) then use forEach() loop on your previously created array.

Here's a working demo.

 /* Get elements and loop on*/ let elements = document.querySelectorAll(".group > a"); elements.forEach((el) => { /* Get the height and width of the element */ const height = el.clientHeight; const width = el.clientWidth; /* * Add a listener for mousemove event * Which will trigger function 'handleMove' * On mousemove */ el.addEventListener("mousemove", handleMove); /* Define function a */ function handleMove(e) { /* * Get position of mouse cursor * With respect to the element * On mouseover */ /* Store the x position */ const xVal = e.layerX; /* Store the y position */ const yVal = e.layerY; /* * Calculate rotation valuee along the Y-axis * Here the multiplier 20 is to * Control the rotation * You can change the value and see the results */ const yRotation = 20 * ((xVal - width / 2) / width); /* Calculate the rotation along the X-axis */ const xRotation = -20 * ((yVal - height / 2) / height); /* Generate string for CSS transform property */ const string = "perspective(500px) scale(1.1) rotateX(" + xRotation + "deg) rotateY(" + yRotation + "deg)"; /* Apply the calculated transformation */ el.style.transform = string; } /* Add listener for mouseout event, remove the rotation */ el.addEventListener("mouseout", function() { el.style.transform = "perspective(500px) scale(1) rotateX(0) rotateY(0)"; }); /* Add listener for mousedown event, to simulate click */ el.addEventListener("mousedown", function() { el.style.transform = "perspective(500px) scale(0.9) rotateX(0) rotateY(0)"; }); /* Add listener for mouseup, simulate release of mouse click */ el.addEventListener("mouseup", function() { el.style.transform = "perspective(500px) scale(1.1) rotateX(0) rotateY(0)"; }); });
 html { display: flex; justify-content: center; align-items: center; align-contents: center; height: 100%; } /* Styling purpose */ .group { display: block } /* Styles for the tilt block */ .group>a { display: inline-block; height: 200px; width: 300px; background-color: grey; margin: 0 auto; transition: box-shadow 0.1s, transform 0.1s; /* * Adding image to the background * No relation to the hover effect. */ background-image: url(http://unsplash.it/300/200); background-size: 100%; background-repeat: no-repeat; } .group a:hover { box-shadow: 0px 0px 30px rgba(0, 0, 0, 0.6); cursor: pointer; }
 <div class="group"> <a href="#" target="_blank"> <!-- Container for our block --> </a> <a href="#" target="_blank"> <!-- Container for our block --> </a> </div> <div class="group"> <a href="#" target="_blank"> <!-- Container for our block --> </a> <a href="#" target="_blank"> <!-- Container for our block --> </a> </div>

Instead of trying to retrieve data using an array and index (which have problems with scope) You should query the element itself when the event is handled. The below code does this via the this keyword, which in this context, with an event handler added via code, can be considered to refer to the element which triggered the event currently being handled.

So, I've grabbed the element's width and height each time the mousemove handler fires and in the other 3 handlers, i've used this in-place of self.rotate[i] .

 "use strict"; function qsa(sel,parent=document){return parent.querySelectorAll(sel)} window.addEventListener('load', onLoaded, false); function onLoaded(evt) { let targets = qsa('div'); targets.forEach( function(curTgt, index, collection) { curTgt.addEventListener('mousemove', onMouseMove); curTgt.addEventListener('mouseout', function(evt) {this.style.transform = 'perspective(500px) scale(1) rotateX(0) rotateY(0)'}) curTgt.addEventListener('mousedown', function(evt) {this.style.transform = 'perspective(500px) scale(0.9) rotateX(0) rotateY(0)'}) curTgt.addEventListener('mouseup', function(evt) {this.style.transform = 'perspective(500px) scale(1.1) rotateX(0) rotateY(0)'}) } ); function onMouseMove(evt) { let height = this.clientHeight; let width = this.clientWidth; let xVal = evt.layerX; let yVal = evt.layerY; let yRotation = 20 * ((xVal - width / 2) / width); let xRotation = -20 * ((yVal - height / 2) / height); let string = 'perspective(500px) scale(1.1) rotateX(' + xRotation + 'deg) rotateY(' + yRotation + 'deg)'; this.style.transform = string; } }
 div { display: inline-block; border: solid 1px #999; padding: 16px; margin: 8px; }
 <div>2</div><div>1</div><div>4</div><div>3</div><div>6</div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM