npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@metav_xly/decal-editor

v1.1.3

Published

Vue3 + Element UI 贴花编辑器组件,基于 Three.js

Readme

@metav_xly/decal-editor

基于 Vue3 + Element UI + Three.js 的贴花编辑器组件

特性

  • 🎨 基于 Three.js 的 3D 贴花编辑功能
  • 🖱️ 鼠标点击添加贴花
  • ⚙️ 实时编辑贴花属性(位置、旋转、缩放、纹理类型)
  • 📋 贴花列表管理
  • 💾 配置导入导出
  • 🎯 支持多种纹理类型
  • 📦 TypeScript 支持
  • 🔧 可自定义材质构造器

安装

npm install @metav_xly/decal-editor
# 或
pnpm add @metav_xly/decal-editor
# 或
yarn add @metav_xly/decal-editor

使用方法

全局注册

import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import DecalEditor from '@metav_xly/decal-editor'
import App from './App.vue'

const app = createApp(App)
app.use(ElementPlus)
app.use(DecalEditor)
app.mount('#app')

局部使用

<template>
  <DecalEditorComponent
    :model-url="modelUrl"
    :textures="textures"
    @decal-added="onDecalAdded"
    @decal-selected="onDecalSelected"
    @decal-updated="onDecalUpdated"
    @decal-removed="onDecalRemoved"
    @decals-cleared="onDecalsCleared"
  />
</template>

<script setup>
import { ref } from 'vue'
import { DecalEditorComponent } from '@metav_xly/decal-editor'

// 准备纹理配置数据
const textures = ref([
  {
    label: '贴花类型1',
    diffuseUrl: '/textures/decal1-diffuse.png',
    normalUrl: '/textures/decal1-normal.jpg'
  },
  {
    label: '贴花类型2',
    diffuseUrl: '/textures/decal2-diffuse.png',
    normalUrl: '/textures/decal2-normal.jpg'
  },
  {
    label: '贴花类型3',
    diffuseUrl: '/textures/decal3-diffuse.png',
    normalUrl: '/textures/decal3-normal.jpg'
  }
])

const modelUrl = ref('/models/your-model.glb')

// 事件处理
const onDecalAdded = (decal, index) => {
  console.log('贴花已添加:', decal, index)
}

const onDecalSelected = (decal, index) => {
  console.log('贴花已选中:', decal, index)
}

const onDecalUpdated = (decal, index) => {
  console.log('贴花已更新:', decal, index)
}

const onDecalRemoved = (index) => {
  console.log('贴花已删除:', index)
}

const onDecalsCleared = () => {
  console.log('所有贴花已清空')
}
</script>

使用核心类

import * as THREE from 'three'
import { DecalEditor, DecalLoader } from '@metav_xly/decal-editor'

// 创建 Three.js 场景
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
const renderer = new THREE.WebGLRenderer()

// 准备纹理配置
const textures = [
  {
    label: '贴花类型1',
    diffuseUrl: '/textures/decal-diffuse.png',
    normalUrl: '/textures/decal-normal.jpg'
  },
  {
    label: '贴花类型2',
    diffuseUrl: '/textures/decal2-diffuse.png',
    normalUrl: '/textures/decal2-normal.jpg'
  }
]

// 创建贴花编辑器
const decalEditor = new DecalEditor(scene, camera, renderer, textures)

// 设置目标网格
decalEditor.setTargetMesh(yourMesh)

// 设置参数
decalEditor.setParams({
  minScale: 0.1,
  maxScale: 5.0,
  textureType: '0',
  rotate: false,
  helperSize: 20,
  normalLength: 20
})

// 监听事件
decalEditor.onDecalAdded = (decal, index) => {
  console.log('贴花已添加:', decal, index)
}

decalEditor.onDecalSelected = (decal, index) => {
  console.log('贴花已选中:', decal, index)
}

decalEditor.onDecalUpdated = (decal, index) => {
  console.log('贴花已更新:', decal, index)
}

decalEditor.onDecalRemoved = (index) => {
  console.log('贴花已删除:', index)
}

decalEditor.onDecalsCleared = () => {
  console.log('所有贴花已清空')
}

// 创建贴花加载器
const decalLoader = new DecalLoader(scene, textures)

// 加载配置
const config = {
  version: '1.0',
  decals: [
    {
      id: 0,
      position: { x: 0, y: 0, z: 0 },
      orientation: { x: 0, y: 0, z: 0 },
      scale: 10,
      textureType: '0',
      targetName: 'mesh'
    }
  ]
}

const loadedDecals = decalLoader.loadConfig(config, yourMesh)

API 文档

DecalEditorComponent Props

| 属性 | 类型 | 默认值 | 说明 | |------|------|--------|---------| | modelUrl | string | '' | 3D 模型文件 URL | | textures | TextureConfig[] | [] | 纹理配置数组 |

DecalEditorComponent Events

| 事件名 | 参数 | 说明 | |--------|------|------| | decal-added | (decal: THREE.Mesh, index: number) | 贴花添加时触发 | | decal-selected | (decal: THREE.Mesh, index: number) | 贴花选中时触发 | | decal-updated | (decal: THREE.Mesh, index: number) | 贴花更新时触发 | | decal-removed | (index: number) | 贴花删除时触发 | | decals-cleared | () | 清空所有贴花时触发 |

TextureConfig 接口

interface TextureConfig {
  label: string        // 纹理标签
  diffuseUrl?: string  // 漫反射纹理 URL
  normalUrl?: string   // 法线纹理 URL
}

TextureSet 接口

interface TextureSet {
  diffuse?: THREE.Texture  // 漫反射纹理
  normal?: THREE.Texture   // 法线纹理
  label: string           // 纹理标签
}

DecalParams 接口

interface DecalParams {
  minScale: number      // 最小缩放值
  maxScale: number      // 最大缩放值
  textureType: string   // 纹理类型索引
  rotate: boolean       // 是否随机旋转
  helperSize: number    // 辅助器大小
  normalLength: number  // 法线长度
}

DecalEditor 类方法

| 方法 | 参数 | 返回值 | 说明 | |------|------|--------|------| | setTargetMesh | (mesh: THREE.Object3D) | void | 设置目标网格 | | setParams | (params: Partial) | void | 设置参数 | | createDecal | () | THREE.Mesh | null | 创建贴花 | | selectDecal | (index: number) | void | 选择贴花 | | updateDecal | (index: number, properties: DecalProperties) | void | 更新贴花 | | removeDecal | (index: number) | void | 删除贴花 | | removeAllDecals | () | void | 删除所有贴花 | | exportConfig | () | any | 导出配置 | | getDecals | () | THREE.Mesh[] | 获取所有贴花 | | getSelectedDecal | () | THREE.Mesh | null | 获取选中的贴花 | | getSelectedDecalIndex | () | number | 获取选中贴花的索引 |

DecalLoader 类方法

| 方法 | 参数 | 返回值 | 说明 | |------|------|--------|------| | loadConfig | (config: DecalConfig, targetMesh: THREE.Object3D) | THREE.Mesh[] | 加载配置 | | validateConfig | (config: any) | boolean | 验证配置格式 |

自定义材质构造器

import * as THREE from 'three'
import { DecalEditor } from '@metav_xly/decal-editor'

const customMaterialConstructor = (textureSet, index) => {
  const material = new THREE.MeshPhongMaterial({
    transparent: true,
    depthTest: true,
    depthWrite: false,
    polygonOffset: true,
    polygonOffsetFactor: -4
  })
  
  if (textureSet.diffuse) {
    material.map = textureSet.diffuse
  }
  if (textureSet.normal) {
    material.normalMap = textureSet.normal
  }
  
  // 根据索引和标签自定义材质属性
  if (index === 0) {
    material.color.setHex(0xff0000)
  }
  
  // 根据纹理标签设置不同属性
  if (textureSet.label.includes('金属')) {
    material.shininess = 100
  }
  
  return material
}

// 准备纹理配置
const textures = [
  {
    label: '金属纹理',
    diffuseUrl: '/textures/metal-diffuse.png',
    normalUrl: '/textures/metal-normal.jpg'
  }
]

const decalEditor = new DecalEditor(
  scene, 
  camera, 
  renderer, 
  textures, 
  customMaterialConstructor
)

开发

# 安装依赖
pnpm install

# 开发模式
pnpm dev

# 构建库
pnpm build:lib

# 类型检查
pnpm type-check

许可证

MIT