这是一款带视觉倾斜效果的鼠标悬停卡片动画特效。该特效通过js和css3代码,使鼠标悬停在一张图片卡片上面时,卡片会根据鼠标的方向进行3d倾斜.
使用方法
HTML结构
<section class="main"> <div class="wrap wrap--1"> <div class="container container--1"> <p>01. Normal</p> </div> </div> <div class="wrap wrap--2"> <div class="container container--2"> <p>02. Reverse</p> </div> </div> <div class="wrap wrap--3"> <div class="container container--3"> <p>03. Normal</p> </div> </div> </section>
CSS样式
*, *::after, *::before { margin: 0; padding: 0; box-sizing: border-box; } html { font-size: 62.5%; } body { --background-color: hsl(180, 20%, 90%); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; min-height: 100vh; padding: 2rem; color: hsla(0, 0%, 0%, .6); background: var(--background-color); text-align: center; } h1 { font-size: 3.2rem; padding-top: 2rem; } h1+p { font-size: 1.8rem; padding: 2rem 0 3rem; } .main { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; } .wrap { margin: 2rem; -webkit-transform-style: preserve-3d; transform-style: preserve-3d; -webkit-transform: perspective(100rem); transform: perspective(100rem); cursor: pointer; } .container { --rX: 0; --rY: 0; --bX: 50%; --bY: 80%; width: 30rem; height: 36rem; border: 1px solid var(--background-color); border-radius: 1.6rem; padding: 4rem; display: flex; align-items: flex-end; position: relative; -webkit-transform: rotateX(calc(var(--rX) * 1deg)) rotateY(calc(var(--rY) * 1deg)); transform: rotateX(calc(var(--rX) * 1deg)) rotateY(calc(var(--rY) * 1deg)); /*background: linear-gradient(hsla(0, 0%, 100%, .1), hsla(0, 0%, 100%, .1)), url("https://images.unsplash.com/photo-1559113513-d5e09c78b9dd?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&ixid=eyJhcHBfaWQiOjF9");*/ background: linear-gradient(hsla(0, 0%, 100%, .1), hsla(0, 0%, 100%, .1)), url("../img/photo-1559113513-d5e09c78b9dd.jpg"); background-position: var(--bX) var(--bY); background-size: 40rem auto; box-shadow: 0 0 3rem .5rem hsla(0, 0%, 0%, .2); transition: -webkit-transform .6s 1s; transition: transform .6s 1s; transition: transform .6s 1s, -webkit-transform .6s 1s; } .container::before, .container::after { content: ""; width: 2rem; height: 2rem; border: 1px solid #fff; position: absolute; z-index: 2; opacity: .3; transition: .3s; } .container::before { top: 2rem; right: 2rem; border-bottom-width: 0; border-left-width: 0; } .container::after { bottom: 2rem; left: 2rem; border-top-width: 0; border-right-width: 0; } .container--active { transition: none; } .container--2 { -webkit-filter: hue-rotate(80deg) saturate(140%); filter: hue-rotate(80deg) saturate(140%); } .container--3 { -webkit-filter: hue-rotate(160deg) saturate(140%); filter: hue-rotate(160deg) saturate(140%); } .container p { color: hsla(0, 0%, 100%, .6); font-size: 2.2rem; } .wrap:hover .container::before, .wrap:hover .container::after { width: calc(100% - 4rem); height: calc(100% - 4rem); }
JavaScript
class parallaxTiltEffect { constructor({element, tiltEffect}) { this.element = element; this.container = this.element.querySelector(".container"); this.size = [300, 360]; [this.w, this.h] = this.size; this.tiltEffect = tiltEffect; this.mouseOnComponent = false; this.handleMouseMove = this.handleMouseMove.bind(this); this.handleMouseEnter = this.handleMouseEnter.bind(this); this.handleMouseLeave = this.handleMouseLeave.bind(this); this.defaultStates = this.defaultStates.bind(this); this.setProperty = this.setProperty.bind(this); this.init = this.init.bind(this); this.init(); } handleMouseMove(event) { const {offsetX, offsetY} = event; let X; let Y; if (this.tiltEffect === "reverse") { X = ((offsetX - (this.w/2)) / 3) / 3; Y = (-(offsetY - (this.h/2)) / 3) / 3; } else if (this.tiltEffect === "normal") { X = (-(offsetX - (this.w/2)) / 3) / 3; Y = ((offsetY - (this.h/2)) / 3) / 3; } this.setProperty('--rY', X.toFixed(2)); this.setProperty('--rX', Y.toFixed(2)); this.setProperty('--bY', (80 - (X/4).toFixed(2)) + '%'); this.setProperty('--bX', (50 - (Y/4).toFixed(2)) + '%'); } handleMouseEnter() { this.mouseOnComponent = true; this.container.classList.add("container--active"); } handleMouseLeave() { this.mouseOnComponent = false; this.defaultStates(); } defaultStates() { this.container.classList.remove("container--active"); this.setProperty('--rY', 0); this.setProperty('--rX', 0); this.setProperty('--bY', '80%'); this.setProperty('--bX', '50%'); } setProperty(p, v) { return this.container.style.setProperty(p, v); } init() { this.element.addEventListener('mousemove', this.handleMouseMove); this.element.addEventListener('mouseenter', this.handleMouseEnter); this.element.addEventListener('mouseleave', this.handleMouseLeave); } } const $ = e => document.querySelector(e); const wrap1 = new parallaxTiltEffect({ element: $('.wrap--1'), tiltEffect: 'reverse' }); const wrap2 = new parallaxTiltEffect({ element: $('.wrap--2'), tiltEffect: 'normal' }); const wrap3 = new parallaxTiltEffect({ element: $('.wrap--3'), tiltEffect: 'reverse' });
该带视觉倾斜效果的鼠标悬停卡片动画特效的codepen网址为:https://codepen.io/AbubakerSaeed/pen/rNNdvqz