Vue自定義指令實(shí)現(xiàn)卡片翻轉(zhuǎn)功能
效果預(yù)覽
1 原理介紹
1.1 前置知識
backface-visibility
backface-visibility
是一個(gè)用于控制元素的背面是否可見的 CSS 屬性。該屬性通常用于在進(jìn)行 3D 轉(zhuǎn)換時(shí),控制元素背面的可見性。
當(dāng)元素進(jìn)行 3D 轉(zhuǎn)換時(shí),其背面可能會變得可見,backface-visibility
屬性就是用來控制這種可見性的。屬性有兩個(gè)可能的值:
visible
:默認(rèn)值。背面可見。hidden
:背面不可見,即不會顯示。
如果設(shè)置了 backface-visibility: hidden;
盒子背面將不可見,把盒子繞 y 軸進(jìn)行3d 旋轉(zhuǎn) 180° 后,我們將看到盒子的背面。
backface-visibility
主要用于處理 3D 轉(zhuǎn)換的情況,如果沒有使用 3D 轉(zhuǎn)換,該屬性的效果可能不會顯著。
transform-style: preserve-3d
transform-style: preserve-3d
主要用于配合 CSS 3D 變換,它告訴瀏覽器在進(jìn)行 3D 變換時(shí)應(yīng)該如何處理子元素。當(dāng)給父元素應(yīng)用 transform-style: preserve-3d
時(shí),其子元素將以三維的方式定位,而不是被扁平化到同一個(gè)平面。
必須在父盒子上加上這個(gè)屬性,因?yàn)檫@里是父盒子翻轉(zhuǎn)帶動子盒子,如果不加上這個(gè)屬性,子盒子中的back背面將顯示不出來!
1.2 步驟分析
首先你需要一個(gè)大盒子,里面包含兩個(gè)小盒子,這里第一個(gè)小盒子為正面內(nèi)容,第二個(gè)小盒子為反面內(nèi)容。結(jié)構(gòu)如下:
<div class="card"> <div class="front">front</div> <div class="back">back</div> </div>
.card { height: 270px; width: 270px; margin: 40px auto; border: 1px solid #f00; position: relative; } .front,.back { width: 100%; height: 100%; } .front { background-image: url(./imgs/youli.png); background-repeat: no-repeat; background-size: cover; } .back { background-image: url(./imgs/erha.jpg); background-repeat: no-repeat; background-size: cover; }
加上上面樣式后得到如下效果:
上面的效果顯然不滿足翻轉(zhuǎn)卡片的前置條件,思考一下我們想要達(dá)到的效果:
首先,正面和背面應(yīng)該疊在一起。
實(shí)現(xiàn):絕對定位。
疊在一起的初始狀態(tài)應(yīng)該只顯示正面,隱藏背面。
實(shí)現(xiàn):
默認(rèn)將正面css設(shè)置為:transform: rotateY(0deg); backface-visibility: hidden;
默認(rèn)將背面css設(shè)置為:transform: rotateY(180deg); backface-visibility: hidden;
這樣初始狀態(tài)下只顯示正面內(nèi)容,背面會自動隱藏。
翻轉(zhuǎn)后應(yīng)該顯示背面,隱藏正面。
實(shí)現(xiàn):將父盒子沿y軸翻轉(zhuǎn) 180度,這樣子盒子 front 會旋轉(zhuǎn)到背面去,從而隱藏。子盒子 back 會旋轉(zhuǎn)到正面,從而顯示。通過點(diǎn)擊父盒子 添加移除 flipped 類名,從而實(shí)現(xiàn)翻轉(zhuǎn)功能。
完整代碼如下:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>卡片旋轉(zhuǎn)效果</title> <style> .card { height: 270px; width: 270px; margin: 40px auto; border: 1px solid #f00; position: relative; transform-style: preserve-3d; transition: transform 0.5s; perspective: 0px; } .card.flipped { transform: rotateY(180deg); } .front,.back { width: 100%; height: 100%; position: absolute; left: 0; top: 0; } .front { background-image: url(./imgs/youli.png); background-repeat: no-repeat; background-size: cover; backface-visibility: hidden; transform: rotateY(0deg); } .back { background-image: url(./imgs/erha.jpg); background-repeat: no-repeat; background-size: cover; transform: rotateY(180deg); backface-visibility: hidden; } </style> </head> <body> <div class="card"> <div class="front">front</div> <div class="back">back</div> </div> <script> const card = document.querySelector('.card') card.addEventListener('click', function() { this.classList.toggle('flipped') }) </script> </body> </html>
2 用 Vue 自定義指令實(shí)現(xiàn)卡片翻轉(zhuǎn)
這里自定義指令的用法就不再介紹了,直接貼上實(shí)現(xiàn)代碼:
Vue.directive('flip', { bind: function (el, binding) { // console.log('bind', el.children.length, binding.value) el.style.position = 'relative' el.style.transformStyle = 'preserve-3d' el.style.transition = 'transform 0.5s' el.initChidren = (el, binding) => { // console.log(el.children.length) if (el.children.length !== 2) { return } if (binding.value) { el.style.transform = 'rotateY(180deg)' } else { el.style.transform = 'rotateY(0deg)' } for (let i = 0; i < el.children.length; i++) { const element = el.children[i] element.style.position = 'absolute' element.style.position = 'absolute' element.style.width = '100%' element.style.height = '100%' element.style.left = 0 element.style.top = 0 if (i === 0) { element.style.backfaceVisibility = 'hidden' element.style.transform = 'rotateY(0deg)' } if (i === 1) { element.style.backfaceVisibility = 'hidden' element.style.transform = 'rotateY(180deg)' } } } el.initChidren(el, binding) }, // inserted: function (el, binding) { // console.log('inserted', el, binding.value) // }, // update: function (el, binding) { // console.log('update', el, binding) // }, componentUpdated: function (el, binding) { // console.log('componentUpdated', el, binding.value) console.log(el.children.length) // el.innerHTML 更新之后先重置子元素css屬性,再初始化 for (let i = 0; i < el.children.length; i++) { const element = el.children[i] element.style.backfaceVisibility = 'visible' element.style.transform = 'rotateY(0deg)' } el.initChidren(el, binding) }, // unbind(el) { // 在解綁時(shí)移除事件 // }, })
組件中使用(注意 html 結(jié)構(gòu)必須如下):
<template> <div class="flipped_card" v-flip="isFlipped" @click="handleFlippedClick"> <div class="front">front</div> <div class="back">back</div> </div> </template> <script> data() { return { isFlipped: false, } }, methods: { handleFlippedClick() { if (!this.isFlipped) { this.isFlipped = true } else { this.isFlipped = false } }, } </script>
以上就是Vue自定義指令實(shí)現(xiàn)卡片翻轉(zhuǎn)功能的詳細(xì)內(nèi)容,更多關(guān)于Vue實(shí)現(xiàn)卡片翻轉(zhuǎn)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue實(shí)現(xiàn)動態(tài)樣式的多種方法匯總
本文要給大家介紹Vue實(shí)現(xiàn)動態(tài)樣式的多種方法,下面給大家?guī)韼讉€(gè)案列,需要的朋友可以借鑒研究一下。2021-06-06vue中Npm run build 根據(jù)環(huán)境傳遞參數(shù)方法來打包不同域名
這篇文章主要介紹了vue項(xiàng)目中Npm run build 根據(jù)環(huán)境傳遞參數(shù)方法來打包不同域名,使用npm run build --xxx,根據(jù)傳遞參數(shù)xxx來判定不同的環(huán)境,給出不同的域名配置,具體內(nèi)容詳情大家參考下本文2018-03-03vue+iview框架實(shí)現(xiàn)左側(cè)動態(tài)菜單功能的示例代碼
這篇文章主要介紹了vue+iview框架實(shí)現(xiàn)左側(cè)動態(tài)菜單功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07詳解vue-cli3開發(fā)Chrome插件實(shí)踐
這篇文章主要介紹了vue-cli3開發(fā)Chrome插件實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05vue3 provide和inject底層組件的值不是響應(yīng)式的處理詳解
這篇文章主要為大家介紹了vue3 provide和inject底層組件的值不是響應(yīng)式的處理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08Vue數(shù)組響應(yīng)式操作及高階函數(shù)使用代碼詳解
這篇文章主要介紹了Vue數(shù)組響應(yīng)式操作及高階函數(shù)使用代碼詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08