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>


相关文章
|
4月前
|
JavaScript 前端开发 IDE
[译] 用 Typescript + Composition API 重构 Vue 3 组件
[译] 用 Typescript + Composition API 重构 Vue 3 组件
[译] 用 Typescript + Composition API 重构 Vue 3 组件
|
4月前
|
JavaScript 前端开发 API
[译] 用 Vue 3 Composition API 实现 React Context/Provider 模式
[译] 用 Vue 3 Composition API 实现 React Context/Provider 模式
|
2月前
|
缓存 JavaScript 前端开发
深入理解 Vue 3 的 Composition API 与新特性
本文详细探讨了 Vue 3 中的 Composition API,包括 setup 函数的使用、响应式数据管理(ref、reactive、toRefs 和 toRef)、侦听器(watch 和 watchEffect)以及计算属性(computed)。我们还介绍了自定义 Hooks 的创建与使用,分析了 Vue 2 与 Vue 3 在响应式系统上的重要区别,并概述了组件生命周期钩子、Fragments、Teleport 和 Suspense 等新特性。通过这些内容,读者将能更深入地理解 Vue 3 的设计理念及其在构建现代前端应用中的优势。
44 1
深入理解 Vue 3 的 Composition API 与新特性
|
1月前
|
JavaScript 前端开发 API
Vue 3新特性详解:Composition API的威力
【10月更文挑战第25天】Vue 3 引入的 Composition API 是一组用于组织和复用组件逻辑的新 API。相比 Options API,它提供了更灵活的结构,便于逻辑复用和代码组织,特别适合复杂组件。本文将探讨 Composition API 的优势,并通过示例代码展示其基本用法,帮助开发者更好地理解和应用这一强大工具。
36 2
|
3月前
|
JavaScript 前端开发 API
花了一天的时间,地板式扫盲了vue3中所有API盲点
这篇文章全面介绍了Vue3中的API,包括组合式API、选项式API等内容,旨在帮助开发者深入了解并掌握Vue3的各项功能。
花了一天的时间,地板式扫盲了vue3中所有API盲点
|
3月前
|
存储 JavaScript 前端开发
敲黑板!vue3重点!一文了解Composition API新特性:ref、toRef、toRefs
该文章深入探讨了Vue3中Composition API的关键特性,包括`ref`、`toRef`、`toRefs`的使用方法与场景,以及它们如何帮助开发者更好地管理组件状态和促进逻辑复用。
敲黑板!vue3重点!一文了解Composition API新特性:ref、toRef、toRefs
|
2月前
|
缓存 JavaScript API
Vue 3的全新Reactivity API:解锁响应式编程的力量
Vue 3引入了基于Proxy的全新响应式系统,提升了性能并带来了更强大的API。本文通过示例详细介绍了`reactive`、`ref`、`computed`、`watch`等核心API的使用方法,帮助开发者深入理解Vue 3的响应式编程。无论你是初学者还是资深开发者,都能从中受益,构建更高效的应用程序。
28 1
|
2月前
|
缓存 JavaScript API
Vue 3的全新Reactivity API:解锁响应式编程的力量
【10月更文挑战第9天】Vue 3的全新Reactivity API:解锁响应式编程的力量
27 3
|
2月前
|
JavaScript API
|
2月前
|
API
《vue3第四章》Composition API 的优势,包含Options API 存在的问题、Composition API 的优势
《vue3第四章》Composition API 的优势,包含Options API 存在的问题、Composition API 的优势
30 0