vue3 composition-api实现波纹涟漪

简介: 接着上一章的制作锦鲤。现在我们要实现水中涟漪。首先我们先创建一个波纹组件。

接着上一章的制作锦鲤。现在我们要实现水中涟漪。首先我们先创建一个波纹组件。

7a00e54bd8220bd1a6a027013e9dda2b.gif

波纹组件Wave

<template>
  <!-- 显示波纹的组件 -->
  <div
      class="WaveRoot"
      :style="{
      left: `${x - 50}px`,
      top: `${y - 50}px`,
    }"
  />
</template>
<script lang="ts">
import { defineComponent, onMounted } from "vue";
export default defineComponent({
  name: "Wave",
  // x、y 波纹的位置
  props: {
    x: { type: Number, default: 0 },
    y: { type: Number, default: 0 },
  },
  setup(_, ctx) {
    onMounted(() => {
      window.setTimeout(() => {
        ctx.emit("end");
      }, 6000);
    });
  },
});
</script>
<style lang="scss" scoped>
.WaveRoot {
  position: absolute;
  left: 0;
  top: 0;
  width: 100px;
  height: 100px;
  border: 1.8px solid currentColor;
  border-radius: 100%;
  pointer-events: none;
  animation: appear 5s both;
  &::before {
    content: "";
    position: absolute;
    width: 80%;
    height: 80%;
    left: calc(10% - 1px);
    top: calc(10% - 1px);
    border: 1.4px solid currentColor;
    border-radius: 100%;
  }
  &::after {
    content: "";
    position: absolute;
    width: 60%;
    height: 60%;
    left: calc(20% - 1px);
    top: calc(20% - 1px);
    border: 1.2px solid currentColor;
    border-radius: 100%;
  }
}
@keyframes appear {
  0% {
    transform: scale(0);
    opacity: 0;
  }
  10% {
    transform: scale(0.1);
    opacity: 0.3;
  }
  100% {
    transform: scale(2.5);
    opacity: 0;
  }
}
</style>


创建一个多波纹排序的组件waveLayer

组件用来管理波纹和显示涟漪的层

<template>
  <div class="WaveLayerRoot">
    <Wave
        v-for="waveProps in stageState.waveList"
        class="WaveElement"
        :key="waveProps.id"
        :x="waveProps.position.x"
        :y="waveProps.position.y"
        @end="removeWave(waveProps)"
    />
  </div>
</template>
<script lang="ts">
import { defineComponent, reactive} from "vue";
import Wave from "./Wave.vue";
import { Point } from "../core/Point";
import { useMouse } from "../core/useMouse";
import { useClick } from "../core/useClick";
import { useTicker } from "../core/useTicker";
import { WaveModel } from "../core/WaveModel";
/**
 * 波纹状态管理
 */
type LayerState = {
  waveList: WaveModel[];
};
export default defineComponent({
  name: "WaveLayer",
  components: { Wave },
  setup(_, ctx) {
    // 状态
    const stageState = reactive<LayerState>({
      waveList: [],
    });
    // 位置
    const { mousePos: destination } = useMouse();
    // 添加波纹
    const addWave = (x: number, y: number) => {
      const RND = 100;
      const rndX = (Math.random() - 0.5) * RND;
      const rndY = (Math.random() - 0.5) * RND;
      stageState.waveList.push(new WaveModel(new Point(x + rndX, y + rndY)));
    };
    // 移除波纹
    const removeWave = (wave: WaveModel) => {
      stageState.waveList = stageState.waveList.filter((w) => w !== wave);
    };
    // 定时增加涟漪,跟背景石头一样
    useTicker(() => {
      if (Math.random() < 0.93) {
        return;
      }
      addWave(destination.x, destination.y);
    }, 100);
    useClick(() => {
      addWave(destination.x, destination.y);
    });
    return {
      stageState,
      addWave,
      removeWave,
    };
  },
});
</script>
<style scoped lang="scss">
.WaveLayerRoot {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  .WaveElement {
    color: rgb(129, 170, 189);
  }
}
</style>


创建一个WaveModel用来管理涟漪位置和数量

import { Point } from "./Point";
let instanseCount = 0;
export class WaveModel {
    readonly id = instanseCount++;
    readonly position: Point;
    constructor(p: Point) {
        this.position = p;
    }
}

使用

<template>
  <!--合成背景、锦鲤和涟漪-->
  <stage-bg class="StageRoot" >
    <FishLayer :maxFish="maxFish" @count-changed="fishCountChanged" />
    <wave-layer />
  </stage-bg>
</template>
<script lang="ts">
import FishLayer from "./FishLayer.vue";
import {defineComponent} from "vue";
import StageBg from "./stageBg.vue";
import WaveLayer from "./waveLayer.vue";
export default defineComponent({
  name: "stageFish",
  components: {WaveLayer, StageBg, FishLayer},
  props: {
    maxFish: { type: Number, default: 50 },
  },
  setup(props,ctx) {
    console.log('33333',props.maxFish)
    //锦鲤数量变化时的事件
    const fishCountChanged = (count: number) => {
      ctx.emit('count-changed', count);
    }
    return {
      fishCountChanged
    }
  }
})
</script>


相关文章
|
5天前
|
JavaScript 前端开发 API
深入浅出:Vue 3 Composition API 的魅力与实践
【2月更文挑战第13天】 本文将探索 Vue 3 的核心特性之一——Composition API。通过对比 Options API,本文旨在揭示 Composition API 如何提高代码的组织性和可复用性,并通过实际案例展示其在现代前端开发中的应用。不同于传统的技术文章摘要,我们将通过一个具体的开发场景,引领读者步入 Composition API 的世界,展现它如何优雅地解决复杂组件逻辑的管理问题,从而激发读者探索和运用 Vue 3 新特性的热情。
27 1
|
5天前
|
缓存 JavaScript Serverless
一些可能被忽视的 Vue3 API 附带案例
一些可能被忽视的 Vue3 API 附带案例
115 0
|
5天前
|
JavaScript 前端开发 API
深入浅出:Vue 3 Composition API 的魅力
【2月更文挑战第13天】 在前端开发的世界里,Vue.js 一直占据着重要的地位。随着 Vue 3 的推出,Composition API 成为了开发者热议的焦点。本文将从一个独特的视角探讨 Composition API 的核心优势,通过对比 Options API,解析其如何优化代码组织和提升项目的可维护性。我们将通过实际案例,深入理解 Composition API 的使用方法和最佳实践,帮助开发者更好地把握这一新工具,激发前端开发的无限可能。
|
5天前
|
JavaScript API
vue 3.0 所采用的 Composition Api 和 vue 2.0 使用的 Option Api 区别
vue 3.0 所采用的 Composition Api 和 vue 2.0 使用的 Option Api 区别
40 0
|
4天前
|
JavaScript 架构师 API
Vue 3.x全面升级指南:Composition API深度探索
Vue 3.x 的全面升级引入了 Composition API,这是对 Vue 2.x 传统 Options API 的一个重大改进,它提供了更加灵活和模块化的代码组织方式.
10 0
|
5天前
|
JavaScript API 开发者
Vue3有哪些常用的API
Vue3有哪些常用的API
13 1
|
5天前
|
JavaScript API
Vue3 API函数及功能
Vue3 API函数及功能
8 0
|
5天前
|
JavaScript 前端开发 API
Vue3 组合式 API
Vue3 组合式 API
|
5天前
|
JavaScript API
Vue3的手脚架使用和组件父子间通信-插槽(Options API)学习笔记
Vue3的手脚架使用和组件父子间通信-插槽(Options API)学习笔记
32 3
|
5天前
|
JavaScript 前端开发 API
深入浅出Vue 3 Composition API:重塑前端开发范式
【2月更文挑战第12天】 本文旨在深入探讨Vue 3中的Composition API,一种全新的组件和逻辑复用方式。相较于传统的Options API,Composition API提供了更为灵活和高效的代码组织机制。通过实例和对比分析,我们将揭示其如何优化代码结构,提升项目的可维护性和扩展性。文章不仅为初学者铺平进入Vue 3世界的道路,也为有经验的开发者提供了深度思考的视角,探索前端开发的新范式。

热门文章

最新文章