Vue自定义指令实现卡片翻转功能
作者:傑丶
效果预览
1 原理介绍
1.1 前置知识
backface-visibility
backface-visibility
是一个用于控制元素的背面是否可见的 CSS 属性。该属性通常用于在进行 3D 转换时,控制元素背面的可见性。
当元素进行 3D 转换时,其背面可能会变得可见,backface-visibility
属性就是用来控制这种可见性的。属性有两个可能的值:
visible
:默认值。背面可见。hidden
:背面不可见,即不会显示。
如果设置了 backface-visibility: hidden;
盒子背面将不可见,把盒子绕 y 轴进行3d 旋转 180° 后,我们将看到盒子的背面。
backface-visibility
主要用于处理 3D 转换的情况,如果没有使用 3D 转换,该属性的效果可能不会显著。
transform-style: preserve-3d
transform-style: preserve-3d
主要用于配合 CSS 3D 变换,它告诉浏览器在进行 3D 变换时应该如何处理子元素。当给父元素应用 transform-style: preserve-3d
时,其子元素将以三维的方式定位,而不是被扁平化到同一个平面。
必须在父盒子上加上这个属性,因为这里是父盒子翻转带动子盒子,如果不加上这个属性,子盒子中的back背面将显示不出来!
1.2 步骤分析
首先你需要一个大盒子,里面包含两个小盒子,这里第一个小盒子为正面内容,第二个小盒子为反面内容。结构如下:
<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; }
加上上面样式后得到如下效果:
上面的效果显然不满足翻转卡片的前置条件,思考一下我们想要达到的效果:
首先,正面和背面应该叠在一起。
实现:绝对定位。
叠在一起的初始状态应该只显示正面,隐藏背面。
实现:
默认将正面css设置为:transform: rotateY(0deg); backface-visibility: hidden;
默认将背面css设置为:transform: rotateY(180deg); backface-visibility: hidden;
这样初始状态下只显示正面内容,背面会自动隐藏。
翻转后应该显示背面,隐藏正面。
实现:将父盒子沿y轴翻转 180度,这样子盒子 front 会旋转到背面去,从而隐藏。子盒子 back 会旋转到正面,从而显示。通过点击父盒子 添加移除 flipped 类名,从而实现翻转功能。
完整代码如下:
<!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>卡片旋转效果</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 自定义指令实现卡片翻转
这里自定义指令的用法就不再介绍了,直接贴上实现代码:
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) { // 在解绑时移除事件 // }, })
组件中使用(注意 html 结构必须如下):
<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自定义指令实现卡片翻转功能的详细内容,更多关于Vue实现卡片翻转的资料请关注脚本之家其它相关文章!