
Research
Supply Chain Attack on Axios Pulls Malicious Dependency from npm
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.
@metav_xly/decal-editor
Advanced tools
基于 Vue3 + Element UI + Three.js 的贴花编辑器组件
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)
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| modelUrl | string | '' | 3D 模型文件 URL |
| textures | TextureConfig[] | [] | 纹理配置数组 |
| 事件名 | 参数 | 说明 |
|---|---|---|
| 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 | () | 清空所有贴花时触发 |
interface TextureConfig {
label: string // 纹理标签
diffuseUrl?: string // 漫反射纹理 URL
normalUrl?: string // 法线纹理 URL
}
interface TextureSet {
diffuse?: THREE.Texture // 漫反射纹理
normal?: THREE.Texture // 法线纹理
label: string // 纹理标签
}
interface DecalParams {
minScale: number // 最小缩放值
maxScale: number // 最大缩放值
textureType: string // 纹理类型索引
rotate: boolean // 是否随机旋转
helperSize: number // 辅助器大小
normalLength: number // 法线长度
}
| 方法 | 参数 | 返回值 | 说明 |
|---|---|---|---|
| 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 | 获取选中贴花的索引 |
| 方法 | 参数 | 返回值 | 说明 |
|---|---|---|---|
| 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
FAQs
Vue3 + Element UI 贴花编辑器组件,基于 Three.js
We found that @metav_xly/decal-editor demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 5 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.

Security News
TeamPCP is partnering with ransomware group Vect to turn open source supply chain attacks on tools like Trivy and LiteLLM into large-scale ransomware operations.