让我们构建VUE指令 - 用VMotion插入运动设计
#javascript #网络开发人员 #设计 #vue

tl:dr-带我去代码

-> Vue 3 Code Sandbox

运动设计的想法自1950年代以来就已经存在。它比静态对应物的主要优势是用户参与度。我们的眼睛演变为特别注意移动物体。运动设计的目的是确切地做 - 使用动画吸引用户的眼睛。

I've written about a directive with a similar goal before。这次,我们不会以简单的连锁效果停止,而是为您的Web应用程序的整个部分动画。

VUE指令的原因

这种类型的设计模式使用浏览器的观察者API。要观察一个元素,您需要直接访问它。指令是提供它的简单方法。简而言之,我们使用指令,因为它

  • 很容易添加到元素
  • 剩下可配置的同时
  • 并封装了创建新的IntersectionObserver的责任

用Vite设置VUE 3项目

我们将使用Vite旋转基本应用程序。您可以使用Vue CLI

更改为您选择和类型的目录:

# 1: Init your project
npm init vite@latest # using Vite with npm
# yarn create vite   # using Vite with yarn
# vue create .       # using Vue CLI

# 2: Change into the created folder and start the dev server
cd vite-project
npm install
npm run dev

使应用对象可用于指令注册

在注册我们的自定义指令之前,让我们在VUE的主文件中进行调整。它即时使用“ createApp”,但我们需要创建的应用程序对象注册组件。

此步骤是可选的,您还可以作为CreateApp引导过程的一部分链条.directive()

// Inside main.js: Change this 
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

// ------

// to 
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)

// ... register directives here

app.mount('#app')

使用app.directive(directiveName, directiveFunction),我们现在能够在应用程序中的各处注册自己的指令。

创建运动指令

我们将使用Intersection Observer API跟踪进出的元素。它使我们能够跟踪DOM元素以及它们是否与视口相交。基于这些信息,我们将添加相关的动画。

然后,我们将使用标准VUE 3“已安装”生命周期应用指令。让我们首先在项目的“/src”中创建一个“/指令”文件夹,然后将其命名为“ vmotion.js”。

父函数

在此文件中,添加以下代码:

// Adjust these as per your requirement
const defaultFromValue = 'right' // or 'left';
const defaultSpeedValue = 0.5;
const defaultTheresholdValue = 0.5;

// Handle the intersection event
function handleIntersection(el, observer, from) {
    const { isIntersecting } = observer;
    // function slideInElementFromRight() { ... }

    // function slideInElementFromLeft() { ...  }

    if (from === 'right') {
        slideInElementFromRight();
    }

    if (from === 'left') {
        slideInElementFromLeft();
    }
}

const vMotion = {
    mounted: (el, binding) => { /* ... */ }
};

export default vMotion;

我们为指令的行为创建了一些默认变量。这些是可以使用该指令的绑定来定制的。我们还声明了我们的处理程序功能和“ VMotion” - 对象。它代表了我们的指示。让我们从编写处理程序开始,然后将其添加到我们指令的“安装”生命周期中。

定义动画样式

相交观察者检查观察到的元素是否在当前视口内。如果支票为正,则注册回调功能会触发。它将检查元素是在当前视口内还是外部。根据结果​​的不同,然后播放相关动画。

让我们首先写出两个动画功能。在“ handlettersection”上下文中,添加这两个功能:

  function slideInElementFromRight() {
    if (isIntersecting) {
      el.style.opacity = 1;
      el.style.transform = "translateX(0px)";
    } else {
      el.style.opacity = 0;
      el.style.transform = "translateX(100px)";
    }
  }

  function slideInElementFromLeft() {
    if (isIntersecting) {
      el.style.opacity = 1;
      el.style.transform = "translateX(0px)";
    } else {
      el.style.opacity = 0;
      el.style.transform = "translateX(-100px)";
    }
  }

注册动画

回调函数就位。现在,我们可以创建一个新的IntersectionObserver并注册动画。

将“ vmotion”指令更改为这样:

const vMotion = {
  mounted: (el, binding) => {
    el.style.transition = `all ${binding.value?.speed || defaultSpeedValue}s`;

    // Create a new IntersectionObserver for the element
    const observer = new IntersectionObserver(
      // Callback function to handle intersection event
      (entries) =>
        handleIntersection(
          el,
          entries[0],
          binding.value?.from || defaultFromValue
        ),

      // Options for the Observer
      {
        threshold: binding.value?.thereshold || defaultTheresholdValue
      }
    );

    observer.observe(el);
  }
};

  • 我们为元素定义了动态过渡,以使元素进入和看不见
  • 我们创建一个观察者实例并注册我们的“句柄调查”'回调 - 函数
  • 我们添加了一个阈值选项,以确定函数执行函数必须在视口中有多少元素
  • 我们称之为“观察”方法开始监视元素的位置

在您的应用程序中注册指令

我们几乎完成了。唯一要做的就是注册指令并尝试一下:

在“ main.js”文件中,注册指令:

import { createApp } from 'vue'
import App from './App.vue'
import vMotion from './directives/vMotion'

const app = createApp(App)

app.directive('motion', vMotion)

app.mount('#app')

在模板上使用指令

现在自己尝试一下。将“ V-Motion”指令添加到您选择的元素中,并查看其行为方式。您可以(并且应该)尝试code sandbox for this project查看一些示例。

可以像这样定制指令对该项目的绑定:

{ 
  speed: 5        // In seconds, the bigger, the slower
  threshold: 0.25 // 0 to 1, the bigger, the longer element stays in view
  from: 'right'   // or 'right'. Determines from where the element moves in
}