English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
先上效果图(gif自己录制的,有点难看抱歉,工具licecap)
实现思路
HTML结构
<ul> <li> <div class="bg"> <p>JS</p> </div> </li> ..... </ul>
li作为鼠标移入(mouseenter)和鼠标移出(mouseleave)的载体。
div作为动画执行的载体。
CSS
div采用absolute定位,通过top、left改变它的位置。
由于div的top、left可能会超出li的大小,所以要设置li的overflow:hidden;
JS
1、采用JS操纵CSS3 animación de transición
2、如何判断鼠标移入移除的方向
鼠标坐标的相关知识
MouseEvent对象
下面介绍几个MouseEvent中坐标的相关知识:
(clientX, clientY): 以可视区域为参考系的坐标。
(pageX, pageY): 以整个页面(包括滚动条卷出的区域)为参考系的坐标。
(screenX, screenY): 以你的电脑屏幕为参考系的坐标。
获取某个元素内部的坐标
function pointTo(element, e) { var elementBox = element.getBoundingClientRect(); devolver { x: e.clientX - elementBox.left, y: e.clientY - elementBox.top }; }
calcular las coordenadas del extremo superior izquierdo del elemento
function startPoint(element){ var x = 0,y = 0; while(element != null) { x += element.offsetLeft; y += element.offsetTop; element = element.offsetParent; } devolver { x: x, y: y } }
obtener el ancho y la altura del elemento (no lo considere como width y height, los principiantes suelen cometer errores)
offsetHeight y offsetWidth
envoltura simple de CSS3 animación de transición
/* parámetros options: obj: objeto en movimiento speed: duración del movimiento (opcional) changeStyle: propiedades que se cambian, aquí pueden ser varias, por lo que se utiliza una función (opcional) callback: función de retroalimentación (opcional) */ function animation(options){ if(!options.obj) { return false; } //establecer el tiempo de duración predeterminado options.speed = options.speed || '.5s'; options.obj.style.transition = "all " + options.speed + " suavidad-in-out"; options.changeStyle.call(options.obj); var flag = false; options.obj.addEventListener('transitionend',function(){ //Aquí se debe a que el evento 'transitionend' se ejecuta varias veces después de que se complete la animación de cada propiedad, por lo que debemos asegurarnos de que se ejecute solo una vez. if(!flag) { options.callback && options.callback(); } },false); }
cómo determinar la dirección
Aquí se utilizan conceptos relacionados con la tangente en matemáticas, dibujé un gráfico, no sé si pueden entenderlo claramente: (horrible...)
obtener la dirección de movimiento del elemento
function getDirection(element,startPoint,pagePoint){ var halfWidth = element.offsetWidth / 2,halfHeight = element.offsetHeight / 2; //Obtener el punto central var center = { x: startPoint.x + halfWidth, y: startPoint.y + halfHeight } //Obtener la distancia del ratón desde el centro var disX = pagePoint.x - center.x; var disY = pagePoint.y - center.y; if(disY < 0 && Math.abs(disY / disX) >= 1) { //arriba return 1; } else if(disY > 0 && Math.abs(disY / disX) >= 1) { //abajo return 2; } else if(disX < 0 && Math.abs(disY / disX) < 1) { //izquierda return 3; } else { //derecha return 4; } }
El código para iniciar el evento, con comentarios
/* Los parámetros en options: el portador del evento desencadenado: targetElement El portador de la animación: animationElement */ function HoverAction(options) { if(!options.targetElement || !options.animationElement) { return false; } this.targetElement = options.targetElement; this.animationElement = options.animationElement; this.timeId = null; this.speed = "0.3s"; } HoverAction.prototype.addEvent = function() { //Guardar la referencia de this var _this = this; _this.targetElement.addEventListener('mouseenter',function(e){ //Obtener las coordenadas del ratón var point = { x: e.pageX, y: e.pageY } console.log(point); //Obtener la dirección var dir = getDirection(_this.targetElement,startPoint(_this.targetElement),point); clearTimeout(_this.timeId); //Cancelar la animación de transición (para evitar que se active el efecto de transición cuando se restablece la posición del elemento de animación) _this.animationElement.style.transition = ""; //Obtener la dirección del movimiento, para determinar la posición de inicio del elemento de animación switch(dir){ case 1: _this.animationElement.style.top = ""-100%"; _this.animationElement.style.left = "0"; break; case 2: _this.animationElement.style.top = ""100%"; _this.animationElement.style.left = "0"; break; case 3: _this.animationElement.style.top = "0"; _this.animationElement.style.left = "-100%"; break; case 4: _this.animationElement.style.top = "0"; _this.animationElement.style.left = "100%"; break; } //Ejecución asíncrona _this.timeId = setTimeout(function(){ animation({ obj: _this.animationElement, speed: _this.speed, changeStyle: function(){ this.style.top = "0"; this.style.left = "0"; } }); },20); },false); _this.targetElement.addEventListener('mouseleave',function(e){ var left,top; var point = { x: e.pageX, y: e.pageY } clearTimeout(_this.timeId); _this.animationElement.style.transition = ""; var dir = getDirection(_this.targetElement,startPoint(_this.targetElement),point); switch(dir) { case 1: top = '-100%'; left = '0'; break; case 2: top = '100%'; left = "0"; break; case 3: left = "-100%"; top = "0"; break; case 4: left = "100%"; top = "0"; break; } _this.timeId = setTimeout(function(){ animation({ obj: _this.animationElement, speed: _this.speed, changeStyle: function(){ this.style.top = top; this.style.left = left; } }); },20); },false); }
Resumen
Este es el contenido completo de este artículo, espero que el contenido de este artículo pueda ayudarles en su aprendizaje o trabajo, si tienen alguna pregunta, pueden dejar comentarios para intercambiar.