You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vue项目中导入自定义鼠标轨迹模块并解决报错问题

在Vue项目中引入自定义鼠标轨迹脚本mouseTrail.js的解决方法

问题描述

我编写了一个实现自定义鼠标轨迹的mouseTrail.js文件,在普通HTML项目中,会通过以下代码在标签末尾引入:

<script src="./mouseTrail.js" type="module"></script>

但在Vue项目中采用同样方式引入时会报错,求解决办法。

报错信息

目标环境不支持动态import()语法,因此无法在script标签中使用外部'module'类型

mouseTrail.js关键代码

import {
  Polyline,
  Renderer,
  Transform,
  Geometry,
  Program,
  Mesh,
  Vec3,
  Vec2,
  Color
} from 'https://cdn.jsdelivr.net/npm/ogl@0.0.25/dist/ogl.mjs';

const vertex = `
  attribute vec3 position;
  attribute vec3 next;
  attribute vec3 prev;
  attribute vec2 uv;
  attribute float side;

  uniform vec2 uResolution;
  uniform float uDPR;
  uniform float uThickness;

  vec4 getPosition() {
      vec2 aspect = vec2(uResolution.x / uResolution.y, 1);
      vec2 nextScreen = next.xy * aspect;
      vec2 prevScreen = prev.xy * aspect;

      vec2 tangent = normalize(nextScreen - prevScreen);
      vec2 normal = vec2(-tangent.y, tangent.x);
      normal /= aspect;
      normal *= 1.0 - pow(abs(uv.y - 0.5) * 1.9, 2.0);

      float pixelWidth = 1.0 / (uResolution.y / uDPR);
      normal *= pixelWidth * uThickness;


      float dist = length(nextScreen - prevScreen);
      normal *= smoothstep(0.0, 0.02, dist);

      vec4 current = vec4(position, 1);
      current.xy -= normal * side;
      return current;
  }

  void main() {
      gl_Position = getPosition();
  }
`

解决方案

1. 放弃直接用type="module"引入脚本

Vue的构建环境(Vite/Webpack)本身会处理模块导入,不需要在script标签里指定type="module"。如果要保留原脚本文件,可将其放入项目public目录,然后在index.html中这样引入:

<script src="./mouseTrail.js"></script>

但这种方式仍可能因脚本内的CDNimport语句报错,更推荐下面两种封装方式。

2. 封装为Vue组件(推荐)

创建MouseTrail.vue组件,将轨迹逻辑整合到Vue生命周期中:

<template>
  <div ref="trailContainer"></div>
</template>

<script setup>
import { onMounted, onUnmounted, ref } from 'vue';
import {
  Polyline,
  Renderer,
  Transform,
  Geometry,
  Program,
  Mesh,
  Vec3,
  Vec2,
  Color
} from 'ogl';

const trailContainer = ref(null);
let renderer, scene;

// 复用原vertex shader代码
const vertex = `
  attribute vec3 position;
  attribute vec3 next;
  attribute vec3 prev;
  attribute vec2 uv;
  attribute float side;

  uniform vec2 uResolution;
  uniform float uDPR;
  uniform float uThickness;

  vec4 getPosition() {
      vec2 aspect = vec2(uResolution.x / uResolution.y, 1);
      vec2 nextScreen = next.xy * aspect;
      vec2 prevScreen = prev.xy * aspect;

      vec2 tangent = normalize(nextScreen - prevScreen);
      vec2 normal = vec2(-tangent.y, tangent.x);
      normal /= aspect;
      normal *= 1.0 - pow(abs(uv.y - 0.5) * 1.9, 2.0);

      float pixelWidth = 1.0 / (uResolution.y / uDPR);
      normal *= pixelWidth * uThickness;


      float dist = length(nextScreen - prevScreen);
      normal *= smoothstep(0.0, 0.02, dist);

      vec4 current = vec4(position, 1);
      current.xy -= normal * side;
      return current;
  }

  void main() {
      gl_Position = getPosition();
  }
`;

// 初始化鼠标轨迹
const initTrail = () => {
  renderer = new Renderer({ dpr: window.devicePixelRatio });
  const gl = renderer.gl;
  trailContainer.value.appendChild(gl.canvas);

  scene = new Transform();

  // 补充原mouseTrail.js中剩余的轨迹初始化、鼠标事件监听逻辑
  // ...
};

// 组件挂载后初始化
onMounted(() => {
  initTrail();
  // 监听窗口大小变化
  const handleResize = () => {
    renderer.setSize(trailContainer.value.clientWidth, trailContainer.value.clientHeight);
    // 补充resize时的轨迹调整逻辑
  };
  window.addEventListener('resize', handleResize);

  // 组件销毁时移除监听
  onUnmounted(() => {
    window.removeEventListener('resize', handleResize);
    renderer.dispose();
  });
});
</script>

<style scoped>
div {
  width: 100vw;
  height: 100vh;
  position: fixed;
  top: 0;
  left: 0;
  pointer-events: none; /* 避免遮挡页面交互 */
}
</style>

之后在根组件App.vue中引入使用:

<template>
  <MouseTrail />
  <!-- 其他页面内容 -->
</template>

<script setup>
import MouseTrail from './components/MouseTrail.vue';
</script>

3. 在入口文件main.js中初始化

若不想封装组件,可在项目入口文件中初始化,确保DOM挂载完成后执行:

import { createApp } from 'vue';
import App from './App.vue';
import {
  Polyline,
  Renderer,
  Transform,
  Geometry,
  Program,
  Mesh,
  Vec3,
  Vec2,
  Color
} from 'ogl';

const app = createApp(App);
app.mount('#app');

// 等待DOM挂载完成后初始化轨迹
setTimeout(() => {
  const renderer = new Renderer({ dpr: window.devicePixelRatio });
  const gl = renderer.gl;
  document.body.appendChild(gl.canvas);

  // 补充原mouseTrail.js中的轨迹逻辑
  // ...
}, 100);

4. 安装ogl本地依赖

原脚本通过CDN导入ogl,在Vue项目中更推荐通过npm安装依赖,便于构建工具处理:

npm install ogl --save

安装后即可直接通过import引入ogl模块,无需依赖CDN链接。

内容的提问来源于stack exchange,提问作者Eduardo Garcia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 13:01:22