WEBLEB
Home
Editor
Accedi
Pro
Italiano
English
Français
Español
Português
Deutsch
Italiano
हिंदी
2035
Andev.web
Apri nell'Editor
Pubblica il Tuo Codice
Consigliato
21 October 2024
Vecchio progetto... nuove vibrazioni
26 May 2025
Un codice di mironovbogdan341
HTML
Copy
Andev Web
Canyons
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Beaches
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Trees
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Lakes
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
CSS
Copy
body { margin: 40px 0; font-family: "Raleway"; font-size: 14px; font-weight: 500; background-color: #BCAAA4; -webkit-font-smoothing: antialiased; overflow-y: hidden; } p { line-height: 1.5em; } h1 + p, p + p { margin-top: 10px; } .container { display: flex; justify-content: center; align-items: center; height: 100vh; } .card-wrap { margin: 10px; transform: perspective(800px); transform-style: preserve-3d; cursor: pointer; } .card-wrap:hover .card-info { transform: translateY(0); } .card-wrap:hover .card-info p { opacity: 1; } .card-wrap:hover .card-info, .card-wrap:hover .card-info p { transition: 0.6s cubic-bezier(0.23, 1, 0.32, 1); } .card-wrap:hover .card-info:after { transition: 5s cubic-bezier(0.23, 1, 0.32, 1); opacity: 1; transform: translateY(0); } .card-wrap:hover .card-bg { transition: 0.6s cubic-bezier(0.23, 1, 0.32, 1), opacity 5s cubic-bezier(0.23, 1, 0.32, 1); opacity: 0.8; } .card-wrap:hover .card { transition: 0.6s cubic-bezier(0.23, 1, 0.32, 1), box-shadow 2s cubic-bezier(0.23, 1, 0.32, 1); box-shadow: rgba(255, 255, 255, 0.2) 0 0 40px 5px, white 0 0 0 1px, rgba(0, 0, 0, 0.66) 0 30px 60px 0, inset #333 0 0 0 5px, inset white 0 0 0 6px; } .card { position: relative; flex: 0 0 240px; width: 240px; height: 320px; background-color: #333; overflow: hidden; border-radius: 10px; box-shadow: rgba(0, 0, 0, 0.66) 0 30px 60px 0, inset #333 0 0 0 5px, inset rgba(255, 255, 255, 0.5) 0 0 0 6px; transition: 1s cubic-bezier(0.445, 0.05, 0.55, 0.95); } .card-bg { opacity: 0.5; position: absolute; top: -20px; left: -20px; width: 100%; height: 100%; padding: 20px; background-repeat: no-repeat; background-position: center; background-size: cover; transition: 1s cubic-bezier(0.445, 0.05, 0.55, 0.95), opacity 5s 1s cubic-bezier(0.445, 0.05, 0.55, 0.95); pointer-events: none; } .card-info { padding: 20px; position: absolute; bottom: 0; color: #fff; transform: translateY(40%); transition: 0.6s 1.6s cubic-bezier(0.215, 0.61, 0.355, 1); } .card-info p { opacity: 0; text-shadow: black 0 2px 3px; transition: 0.6s 1.6s cubic-bezier(0.215, 0.61, 0.355, 1); } .card-info * { position: relative; z-index: 1; } .card-info:after { content: ""; position: absolute; top: 0; left: 0; z-index: 0; width: 100%; height: 100%; background-image: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.6) 100%); background-blend-mode: overlay; opacity: 0; transform: translateY(100%); transition: 5s 1s cubic-bezier(0.445, 0.05, 0.55, 0.95); } .card-info h1 { font-family: "Playfair Display"; font-size: 36px; font-weight: 700; text-shadow: rgba(0, 0, 0, 0.5) 0 10px 10px; }
JS
Copy
Vue.config.devtools = true; Vue.component('card', { template: ` <div class="card-wrap" @mousemove="handleMouseMove" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave" ref="card"> <div class="card" :style="cardStyle"> <div class="card-bg" :style="[cardBgTransform, cardBgImage]"></div> <div class="card-info"> <slot name="header"></slot> <slot name="content"></slot> </div> </div> </div>`, mounted() { this.width = this.$refs.card.offsetWidth; this.height = this.$refs.card.offsetHeight; }, props: ['dataImage'], data: () => ({ width: 0, height: 0, mouseX: 0, mouseY: 0, mouseLeaveDelay: null }), computed: { mousePX() { return this.mouseX / this.width; }, mousePY() { return this.mouseY / this.height; }, cardStyle() { const rX = this.mousePX * 30; const rY = this.mousePY * -30; return { transform: `rotateY(${rX}deg) rotateX(${rY}deg)` }; }, cardBgTransform() { const tX = this.mousePX * -40; const tY = this.mousePY * -40; return { transform: `translateX(${tX}px) translateY(${tY}px)` }; }, cardBgImage() { return { backgroundImage: `url(${this.dataImage})` }; } }, methods: { handleMouseMove(e) { this.mouseX = e.pageX - this.$refs.card.offsetLeft - this.width / 2; this.mouseY = e.pageY - this.$refs.card.offsetTop - this.height / 2; }, handleMouseEnter() { clearTimeout(this.mouseLeaveDelay); }, handleMouseLeave() { this.mouseLeaveDelay = setTimeout(() => { this.mouseX = 0; this.mouseY = 0; }, 1000); } } }); const app = new Vue({ el: '#app' });