vue3

vue3.0礼物动画

<template>
  <div class="gift-container">
    <transition-group name="gift-transition">
      <div class="gitem" :key="index" v-for="(gift, index) in giftList">
        <div class="gitem-left">
          <div class="gitem-left__avatar">
            <img :src="gift.avatar" class="gitem-avatar--img" />
          </div>
          <div class="gitem-left__info">
            <div class="gitem-left__info--name">{{ gift.nickname }}</div>
            <div class="gitem-left__info--dir">{{ gift.name }}</div>
          </div>
          <div class="gitem-left__bigimg">
            <img :src="gift.icon" class="gitem-left__bigimg--img" />
          </div>
        </div>
        <div class="gitem-count" :class="{ alteration: gift.count > 1 }">
          x{{ gift.count }}
        </div>
      </div>
    </transition-group>
  </div>

  <div @click="sendGift" style="margin-top: 500px">送礼物</div>
  <div class="m-t20" @click="sendGift2">送礼物2</div>
</template>

<script setup>
const giftList = ref([])

const addGift = gift => {
  const existingGift = giftList.value.find(g => g.id === gift.id)
  if (existingGift) {
    existingGift.count += gift.count
    return
  }
  giftList.value.push(gift)
}

function sendGift() {
  addGift({
    id: 1,
    nickname: '张三疯',
    name: '玫瑰花',
    avatar:
      'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fblog%2F202104%2F22%2F20210422220415_2e4bd.jpg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1681972630&t=33e03cb1f9a7d9cd98c16d4502649fa8',
    count: 1,
    icon: 'https://b09-prod.luziedu.com/data/upload/20210615/60c828378355a.gif'
  })
}
function sendGift2() {
  addGift({
    id: 2,
    nickname: '王五',
    name: '玫瑰花2',
    avatar:
      'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fitem%2F202003%2F30%2F20200330091314_yNVUZ.thumb.1000_0.jpeg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1681972630&t=ebeac42ddeb3b3052c41135ebdba298d',
    count: 3,
    icon: 'https://b09-prod.luziedu.com/data/upload/20210615/60c829aab9200.gif'
  })
}

let timer = null

watch(
  giftList,
  (newVal, old) => {
    if (!giftList.value.length) {
      clearTimeout(timer)
    }
    timer = setTimeout(() => {
      giftList.value.shift()
    }, 4000)
  },
  { deep: true }
)
</script>

<style lang="scss">
.gift-container {
  position: absolute;
  top: 30px;
  width: 400px;
  height: 300px;
}

.gitem {
  /* position: absolute;
  top: 0;
   */
  margin-left: 15px;
  display: flex;
  align-items: center;
  margin-bottom: 30px;
  &-left {
    display: flex;
    font-size: 18px;
    color: #fff;
    width: 180px;
    height: 48px;
    background: linear-gradient(94deg, #d47458 0%, rgba(227, 187, 255, 0) 100%);
    border-radius: 50px;
    position: relative;
    &__avatar {
      @include wh(40, 40);
      border-radius: 50px;
      overflow: hidden;
      margin: 4px 5px 4px 4px;
    }
    &__info {
      font-size: 12px;
      color: #fff;
      &--name {
        margin-bottom: 2px;
      }
    }
    &__bigimg {
      position: absolute;
      top: -13px;
      right: 0;
      width: 67px;
      height: 74px;
      &--img {
        width: 100%;
      }
    }
  }

  &-count {
    font-size: 25px;
    color: #fe9331;
    margin-left: 17px;
  }
}

/* .gift-transition-leave-active */
.gift-transition-enter-active {
  animation: bounce-in 0.5s;
}

/* .gift-transition-enter-from, */
.gift-transition-leave-to {
  /* opacity: 0; */

  transform: translateX(-100%);
  transition: all 0.5s;
}

.gift-count {
  animation: ripple 0.5s;
  &.alteration {
    animation: ripple 1s ease-in-out both;
    animation-delay: 1.1s;
  }
}

@keyframes bounce-in {
  0% {
    opacity: 0;
    transform: translateX(-100%);
  }
  100% {
    opacity: 1;
    transform: translateX(0%);
  }
}

@keyframes ripple {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.1);
  }
  100% {
    transform: scale(1);
  }

  /* 0% {
    transform: scale(0.5);
  }
  100% {
    transform: scale(1);
  } */
}
</style>
上次更新: