基于vue3实现翻转卡片效果组件

组件基于下方文章改造成vue3+ts版本的,感谢原作者提供的轮子
原文章链接
https://segmentfault.com/a/1190000017402490?utm_source=tag-newest

//**参数**
//trigger:卡片翻转的触发方式,目前有 hover/click/custom(自定义)三种方式。其中custom方式配合v-model使用,使用场景:在卡片内部点击按钮触发时使用。
//direction:翻转的方向,目前有row/col两种。
//slot:cz/cf 正反两面的插槽

//card.vue
<template>
  <div
    class="card-3d"
    @click="eve_cardres_click"
    @mouseover="eve_cardres_msover"
    @mouseout="eve_cardres_msout"
  >
    <div class="card card-z" ref="cardz">
      <slot name="cz"></slot>
    </div>
    <div
      :class="['card', direction == 'row' ? 'card-f-y' : 'card-f-x']"
      ref="cardf"
    >
      <slot name="cf"></slot>
    </div>
  </div>
</template>
<script setup lang="ts">
import { defineProps, ref, watch } from 'vue'

const props = defineProps<{
  trigger: string
  value?: boolean
  direction?: string
}>()

const surface = ref<boolean>(true)
const cardz = ref<HTMLDivElement | null>(null)
const cardf = ref<HTMLDivElement | null>(null)

watch(
  () => props.value,
  (newVal, oldVal): void => {
    if (props.trigger == 'custom') fn_reserve_action(newVal)
  }
)

const fn_reserve_action = (bool: boolean | undefined): void => {
  const arr =
    props.direction == 'row'
      ? ['rotateY(180deg)', 'rotateY(0deg)']
      : ['rotateX(-180deg)', 'rotateX(0deg)']
  if (cardz.value) {
    cardz.value.style.transform = bool ? arr[0] : arr[1]
  }
  if (cardf.value) {
    cardf.value.style.transform = !bool ? arr[0] : arr[1]
  }
}

const eve_cardres_click = (): void => {
  if (props.trigger == 'click') {
    fn_reserve_action(surface.value)
    surface.value = !surface.value
  }
}

const eve_cardres_msover = (): void => {
  if (props.trigger == 'hover') fn_reserve_action(true)
}

const eve_cardres_msout = (): void => {
  if (props.trigger == 'hover') fn_reserve_action(false)
}
</script>

<style lang="scss" scoped>
.card-3d {
  width: 200px;
  height: 200px;
  transition: all 0.2s;
  position: relative;
  background-color: transparent;
  cursor: pointer;
  .card {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    transition: all 1s;
    backface-visibility: hidden;
    border-radius: 4px;
    border: 1px solid #e8eaec;
    &:hover {
      box-shadow: 0 1px 6px rgba(0, 0, 0, 0.2);
      border-color: #eee;
    }
    &.card-z {
      background-color: red;
    }
    &.card-f-y {
      transform: rotateY(-180deg);
    }
    &.card-f-x {
      transform: rotateX(-180deg);
    }
  }
}
</style>


//用法
<template>
  <div class="flex">
    <card trigger="click" direction="row" v-for="item in 3" :key="item">
      <template #cz>
        <div class="card">aaa</div>
      </template>
      <template #cf>
        <div class="card card1">bbb</div>
      </template>
    </card>
  </div>
</template>
<script setup lang="ts">
import { defineAsyncComponent } from 'vue'

const card = defineAsyncComponent(() => import('@/components/card.vue'))

</script>

<style lang="scss" scoped>
.flex {
  display: flex;
  justify-content: space-between;
}
.card {
  width: 200px;
  height: 200px;
  background: red;
}
.card1 {
  background: gold;
}
</style>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值