likes
comments
collection
share

绽放奇迹:探索如何为您的UI添加令人惊叹的动效

作者站长头像
站长
· 阅读数 23

Start

大家好,我是TalexDreamSoul,一个个人开发者,也是高中生。今天我想跟大家分享一个我开发的项目,它叫做TalexTouch。

TalexTouch是一个基于Electron制作的全客户端,旨在提供更完美的UI体验。它支持在Windows、MacOS和Linux等主流平台上运行,让用户能够在各种设备上享受一致的使用体验。 TalexTouch的源码地址

这是一个非常强大的项目,集成了多种实用的功能,让你的桌面更智能、更高效。同时,它还支持自定义插件,让用户可以根据自己的需求进行定制化操作。

TalexTouch的UI设计非常优美,参考了TDesignS的设计风格,简洁美观。所有的主题、字体和图标都经过精心调整,以使用户获得更佳的使用体验。操作也非常简单易用,用户可以轻松地完成各种任务。

我们非常注重用户的安全和隐私,保证用户的数据不会被泄露或滥用,同时提供了多种安全机制来保护用户的使用安全。如果你正在寻找一款全平台支持、优美易用的桌面软件,TalexTouch将是你的不二选择。它不仅提供了丰富的功能,还有着良好的用户体验和开放的社区生态。

欢迎使用TalexTouch,体验全新的桌面体验!

Tutorial

本教程将介绍如何实现一个输入框联想功能,当用户输入文字时,会自动弹出与输入内容匹配的联想选项,用户可以从选项中选择一个。

效果预览

绽放奇迹:探索如何为您的UI添加令人惊叹的动效

在这个教程中,我们将使用Vue 3和SCSS编写代码,并且使用Teleport组件实现将联想选项移动到页面的body元素。

我们的组件将具有以下功能:

  • 自动弹出联想选项
  • 点击联想选项时填充输入框
  • 点击输入框外部的任何区域,关闭联想选项
  • 限制联想选项的数量不超过8项
  • 动态计算联想选项的位置,确保联想选项在输入框下方,并且不会超出视窗范围

以下是我们组件的模板代码:

<template>
  <div class="FlatInput-Container" ref="completionInput">
    <FlatInput v-model="value" :icon="icon" />
  </div>
  <teleport to="body">
    <div @click="value = ''" class="FlatInput-Completion" ref="completionWrapper">
      <div v-wave class="FlatInput-Completion-Item fake-background" :style="`--d: ${index * 0.125}s`" v-for="(item, index) in _res" :key="item">
        <slot :item="item">
          {{ item }}
        </slot>
      </div>
    </div>
  </teleport>
</template>

在上面的代码中,我们定义了一个FlatInput组件和一个Teleport组件,FlatInput是我们自己定义的一个输入框组件,Teleport可以将FlatInput-Completion组件移动到body元素中。

接下来是我们组件的逻辑代码:

<script setup name="FlatCompletion">
import FlatInput from "@comp/input/FlatInput.vue";
import { sleep, useModelWrapper } from "@modules/utils";
import { useFloating, autoUpdate, flip, shift, computePosition } from '@floating-ui/vue'

const props = defineProps({
  icon: {
    type: String,
    default: "search",
  },
  fetch: {
    type: Function,
    require: true
  }
});

const _res = ref([])
const res = ref([]);
const completionInput = ref()
const completionWrapper = ref()
const value = ref()

watch(() => value.value, () => {
  nextTick(blur)
}, { deep: true, immediate: true });

watch(() => res.value, async () => {
  const el = completionWrapper.value

  for ( const item of [ ...el.children ].reverse() ) {

    setTimeout(async () => {

      item.classList.add('remove')

      await sleep(500)
      item?.remove()
    })
    await sleep(125)
  }

  await sleep(600)

  _res.value = res.value
})

function blur() { if ( !value.value ) value.value = "" res.value = props.fetch(value.value) if ( res.value.length > 8 ) res.value = res.value.slice(0, 8) nextTick(async() => { const floating = await computePosition(completionInput.value, completionWrapper.value) Object.assign(completionWrapper.value.style, { top: `${floating.y}px`, left: `${floating.x}px` }) }) } </script>
  1. 监听数据变化

为了实时获取用户输入的内容,我们需要在 watch 函数中监听 value 数据的变化,并调用 blur 函数进行处理。代码如下:

watch(() => value.value, () => {
  nextTick(blur)
}, { deep: true, immediate: true });

其中,deep: true 表示深度监听 value 的变化,immediate: true 表示在监听之前立即触发一次回调函数。

  1. 处理用户输入

blur 函数中,我们需要对用户输入进行处理,并根据输入的内容动态展示下拉框中的选项。

具体处理流程如下:

  • 获取用户输入的内容,如果为空,则直接清空下拉框。
  • 调用 fetch 函数获取用户输入所对应的选项列表。
  • 对选项列表进行截取,最多展示 8 个选项。
  • 获取下拉框的浮动位置,并设置到下拉框元素的样式中。
function blur() {
  if ( !value.value ) value.value = ""
  res.value = props.fetch(value.value)

  if ( res.value.length > 8 )
    res.value = res.value.slice(0, 8)

  nextTick(async() => {
    const floating = await computePosition(completionInput.value, completionWrapper.value)

    Object.assign(completionWrapper.value.style, {
      top: `${floating.y}px`,
      left: `${floating.x}px`
    })
  })
}
  1. 渲染下拉框

在模板中,我们使用 teleport 将下拉框挂载到页面的 body 元素上,实现了下拉框的浮动效果。同时,我们使用 v-for 指令遍历选项列表,生成下拉框中的选项元素,并使用插槽 slot 将每个选项的内容作为插槽内容进行渲染。

<teleport to="body">
  <div @click="value = ''" class="FlatInput-Completion" ref="completionWrapper">
    <div v-wave class="FlatInput-Completion-Item fake-background" :style="`--d: ${index * 0.125}s`" v-for="(item, index) in _res" :key="item">
      <slot :item="item">
        {{ item }}
      </slot>
    </div>
  </div>
</teleport>

在样式中,我们使用 position: absolute 将下拉框定位到合适的位置,并使用 max-height 控制下拉框的最大高度。同时,我们还使用了一些动画效果,实现了选项元素的渐入渐出效果。

  1. 最后补充所有的样式即可
<style lang="scss" scoped>
.FlatInput-Completion {
  z-index: 100;
  position: absolute;
  display: flex;
  padding: 10px;

  flex-direction: column;
  justify-content: center;
  align-items: center;

  max-height: 380px;
  overflow: hidden;

  transition: .5s cubic-bezier(0.785, 0.135, 0.150, 0.860);

  .FlatInput-Completion-Item {
    position: relative;
    margin: 5px 0;
    padding: 10px;
    cursor: pointer;

    width: max-content;

    opacity: 0;

    animation: fade-in .5s var(--d) cubic-bezier(0.785, 0.135, 0.150, 0.860) forwards;
    transition: .5s cubic-bezier(0.785, 0.135, 0.150, 0.860);

    --fake-opacity: 0.5;
    --fake-radius: 4px;
    border-radius: var(--fake-radius);
    box-sizing: border-box;
    backdrop-filter: blur(16px) saturate(180%);
    &:hover {
      --fake-opacity: 0.8;
    }
    &.remove {
      animation: fade-out .5s cubic-bezier(0.785, 0.135, 0.150, 0.860) forwards;
    }
  }
}

@keyframes fade-out {
  from {
      opacity: 1;
      filter: blur(0);
      transform: translateY(0) scaleY(1);
  }
  to {
    opacity: 0;
    filter: blur(10px);
    transform: translateY(10px) scaleY(1.1);
  }
}

@keyframes fade-in {
  from {
    opacity: 0;
    filter: blur(10px);
    transform: translateY(10px) scaleY(1.1);
  }
  to {
    opacity: 1;
    filter: blur(0);
    transform: translateY(0) scaleY(1);
  }
}
</style>

结语

完整的代码地址:github.com/talex-touch…

在本篇技术博客中,我向大家介绍了我开发的桌面软件TalexTouch里面的自动补全输入框。作为一个个人开发者,我花费了很多时间和精力来打磨这个项目,让它变得更加完美和实用。我相信TalexTouch可以成为你工作和生活中的得力助手,让你的桌面体验变得更加优美和高效。同时,我也希望这篇博客可以为其他开发者提供一些参考和启发,让我们一起为技术的进步和创新而努力!

Tip: 本篇文章部分内容由 GPT 引领而入

(「创新引领未来」——让我们一起探索人工智能的奥秘!)