
Security News
minimatch Patches 3 High-Severity ReDoS Vulnerabilities
minimatch patched three high-severity ReDoS vulnerabilities that can stall the Node.js event loop, and Socket has released free certified patches.
three-editor-release
Advanced tools
原生Three.js Cesium.js 案例 https://github.com/z2586300277/three-cesium-examples 1000+ Star ⭐
Copyright (c) threehub.cn email:2586300277@qq.com All rights reserved.
这是一个 集成 three.js 等依赖的库 build 打包为一个 js 文件 发布到 npm 仓库使用, 专注 编辑器 造轮子 (three.js 低代码, 组件化, 内核框架)
API文档不全,自行查看
| 预览 | 赞助我 |
|---|---|
![]() | ![]() |
npm install three-editor-cores
THREE.js 0.157.0
import { ThreeEditor } from 'three-editor-cores'
const { ThreeEditor } = require('three-editor-cores')
ThreeEditor.dracoPath = '/draco/'
/**
* 挟制监听
*/
let originalAdd = scene.add
scene.add = function (object) {
originalAdd.apply(scene, arguments)
}
const ThreeEditor = new ThreeEditor({
threeBoxRef: document.querySelector('#threeBox'),
rendererParams: {
fps: null, // fps 控制 传 null 不控制, 根据电脑分辨率 HZ
pixelRatio: window.devicePixelRatio * 1, // 分辨率参数
webglRenderParams: { antialias: true, alpha: true, logarithmicDepthBuffer: true }, // 同 three.js WebglRenderer 通用参数
userPermissions: { autoPlace: true, proxy: false } // 用户权限 autoPlace false 不挂载到页面上 proxy 空对象 代理 dat.gui
},
sceneParams: JSON.parse(localStorage.getItem('sceneParams')), // 场景参数 没有可以不传, 保存后生成
meshListParams: JSON.parse(localStorage.getItem('meshListParams')), // 物体对象参数 没有可以不传 保存后生成
skyParams: JSON.parse(localStorage.getItem('skyParams')), // 天空盒子参数 注:此天空盒会同时设置为全局环境贴图 没有可不传 自行生成和保存
// 编辑器场景保存回调
saveEditorCallBack: (sceneParams, meshListParams) => {
localStorage.setItem('sceneParams', JSON.stringify(sceneParams))
localStorage.setItem('meshListParams', JSON.stringify(meshListParams))
}
})
threeEditor.viewer // 包含场景 所有 对象
threeEditor.progressList // 初次加载每一个模型进度控制
threeEditor.progressList.forEach(i => i.loaderService.progress = e => yourCallBack(e)) // 将你的回调 挂接获取每一个进度
threeEditor.viewer.destroySceneRender()
window.onresize = () => threeEditor.viewer.renderSceneResize()
transformControls.dragChangeCallback = (v) => {} // 控制器拖拽回调
chartsMapControls.geoGroupLoadCall = (group) => {} // 地理地图加载完成回调 注:重构
chartsMapControls.geoGroupAllLoadedCall = () => {} // 所有地图加载完毕
/**
* e DOM click/dblclick/mousemove/mouseup/mousedown 事件
*
* info 返回点击相关信息
*/
threeEditor.getSceneEvent(e, (info) => ())
/**
* 原生未处理事件 group 从 group 中进行查找
*
* return 获取相交所有元素
*/
threeEditor.getRawSceneEvent(e, group)
/**
* 注:重构
*
* 传递参数
*
* { type: 'GLTF', url: 'HOST/yCar.glb' },
*
* { type: 'FBX', url: 'HOST/tileset.FBX' },
*
* { type: 'OBJ', url: 'HOST/resource/objHouse/house.obj' },
*
* 根据传参增加相关mesh 模型对象
*
* return { loaderService, type } 自动push progressList
*/
const { loaderService, rootInfo } = threeEditor.setModelFromInfo({ type: 'GLTF', url: 'HOST/yCar.glb' })
loaderService.progress = e => console.log(e) // 单一进度回调
loaderService.complete = (model) => console.log('加载完成') // 单一加载完成回调
/**
* 设置天空盒子 图片地址列表 urls
*
* [1.png, 2.png, 3.png, 4.png, 5.png, 6.png]
*/
threeEditor.setSky(urls)
/**
* 设置全局环境贴图资源
*
* 值同 上 天空盒
*/
threeEditor.setGlobalEnvBackground(urls)
/**
* 设置二维DOM 元素
*
* DOM 传入的dom元素
*
* point 传入的坐标点
*
* return mesh 属性 destroy() 销毁方法 更新重新调用 setCss2dDOM
*
* 注:移除事件 生成完毕 => dom.style.pointerEvents = 'none'
*/
const mesh = threeEditor.setCss2dDOM(document.querySelector('#your_dom'),point)
mesh.destroy()
/**
* 设置三维DOM 元素
*
* DOM 传入的dom元素
*
* point 传入的坐标点
*
* return mesh 属性 destroy() 销毁方法 更新重新调用 setCss3dDOM
*
* 注:移除事件 生成完毕 => dom.style.pointerEvents = 'none'
*/
const mesh = threeEditor.setCss3dDOM(document.querySelector('#your_dom'),point)
mesh.destroy()
/**
* 计算两点之间的 指定距离比例点
*
* p1, p2 , 比例 , :例如计算相机与点击点之间的 0.5 比例点
*
* return vector3
*/
threeEditor.getDistanceScalePoint(camera.position, info.point, 0.5)
/**
* 补间动画 例如: 对camera.position 视角补间 , controls.target 视角中心补间
*
* vector3 旧的三维向量, vector3_ 更改后的三维向量 可以是对象 { x: 0, y: 0, z: 0 }
*
* gsapQuery { duration: 3, ease: 'none', repeat: 0, yoyo: false , onUpdate: () => {}, onComplete: () =>{} }
*
* duration 动画时间
*
* ease 缓动函数
*
* repeat 重复次数
*
* yoyo 往返播放
*
* onUpdate 动画更新回调
*
* onComplete 动画完成回调
*
* return gsapControl 动画对象 用于控制动画 gsapControl.pause() gsapControl.play() gsapControl.kill()
*/
threeEditor.setGsapAnimation(vector3, vector3_, gsapQuery)
/**
* 设置GUI DOM 位置 userPermissions: { autoPlace: false} autoPlace 需要设置成false
*
* DOM 传入的GUI 父级dom元素
*
* return { GUIDom, remove () } 返回GUIDom, 和 dom 移除方法
*
* 可通过GUIDom.style.display 控制显示隐藏
*/
threeEditor.setGUIDomPosition(DOM)
/**
* 设置轮廓光选中
*
* model 模型对象 数组形式
*
* 清空传 []
*/
threeEditor.setOutlinePass([model])
/**
* 保存
*/
threeEditor.saveSceneEditor()
/**
* 刷新GUI 数据 使GUI 数据与mesh 数据同步
*/
threeEditor.refreshGUI()
/**
* 场景截图
*
* 例 params = ['image/jpeg', 0.9] => toDataURL(...params)
*/
threeEditor.getSceneEditorImage(params)
/**
* 设置场景模式
*
* mode = '选择', '根选择', '变换', '场景绘制', '点击信息'
*/
threeEditor.setSceneControlMode(mode)
/**
* 设置控制器属性
*
* showX showY showZ => Boolean, translationSnap rotateSnap scaleSnap => Number mode => 'translate' || 'rotate' || 'scale'
*/
threeEditor.setTransformControlsProperty('showX', false)
/**
* 设置操作选项
*
* key = grid || axes || openKey || stats : value = true || false
*/
threeEditor.setOperateOption('stats', Math.random() > 0.5 ? true : false)
/**
* 根据参数播放模型动画
*
* 参数 mesh => 加载的模型对象 模型如果存在动画 则mesh 会携带以下属性
*
* animations => 模型动画列表
*
* animationPlayParams => 模型动画播放参数 与GUI一致 修改会进行保存 如下 可自行修改
*
* { initPlay: false, speed: 0.5, actionIndexs: [animations.length], startTime: 0, loop: true, frameCallback: () => { } }
*
* initPlay 是否初始化播放 speed 播放速度 actionIndexs: [需要播放得动画 bool] startTime 播放开始时间 loop 是否循环播放 frameCallback 每一帧回调
*
* return { mixer: 播放器, actions:播放列表 } 暂停/继续 actions.forEach(i => i.paused = !i.paused) 停止:i.stop() 播放:i.play()
*/
const model = threeEditor.viewer.currentInfo?.currentRootModel
const _actions = Math.random() > 0.5 ? [1, 3, 5, 7] : [2, 4, 6, 8]
model.animationPlayParams.actionIndexs.forEach((_, k, arr) => arr[k] = _actions.includes(k))
const { mixer, actions } = threeEditor.setModelAnimationPlay(model)
mixer.addEventListener('finished', (e) => console.log(123))
/**
* 移除模型动画
*
* 参数 mesh => 模型对象
*/
threeEditor.removeModelAnimation(mesh)
/**
* 生成立方体
*
* size 尺寸 color 颜色
*/
threeEditor.setBoxGeometry(size, color)
/**
* 地理物体 group 使用
*
* 属性 url, materialType 同生成地理地图
*
* geoInfo => 同geojson 数据拷贝加工, geoInfo?.properties?.centerCoord3 地理区块行政中心原三维坐标
*
* 方法 getTransformedVector(Vector3) => 根据模型转换坐标
*
*/
group.children.forEach(i => {
if (i.geoInfo?.properties?.centerCoord3) {
const mesh = threeEditor.setBoxGeometry(10, 'red')
mesh.position.copy(getTransformedVector(i.geoInfo?.properties.centerCoord3))
threeEditor.viewer.scene.add(mesh)
}
})
/**
* 设置物体材质
*
* params = material 参数
*
* mesh.meshRevertMaterial() => 恢复原材质
*/
threeEditor.changeMeshMaterial(group, params)
/**
* 设置物体变换
*
* params = position, rotation, scale 参数
*
* mesh.meshRevertTransform() => 恢复原变换
*/
threeEditor.changeMeshTransform(group, params)
/**
* 地图设置浮动变化 注:重构
*
* 变换材质 可使用 changeMeshMaterial Api
*
* changeMeshTransform 可实现物体变换,实际地图场景可能并不适用, 需要特定并结合动画手写
*/
let currnetMeshName = null
let meshs = []
threeEditor.viewer.chartsMapControls.geoGroupLoadCall = (group) => {
if (group.name !== '带事件') return
const { raycaster, getIntersects } = threeEditor.getRawSceneEvent()
raycaster.far = 1000
document.querySelector('#threeBox').addEventListener('mousemove', (e) => {
const intersects = getIntersects(e, group.children)
const i = intersects.find((i) => i.object.text !== 'TransformControls' && i.object.isMesh)
if (!i) return
if (currnetMeshName === i.object.name) return
currnetMeshName = i.object.name
meshs.forEach(i => {
i?.meshRevertMaterial()
i?.meshRevertTransform()
})
// 修改形状
meshs = group.children.filter(j => j.name === i.object.name)
meshs.forEach(i => {
threeEditor.changeMeshTransform(i, { scale: { x: 1, y: 1, z: 3 } })
threeEditor.changeMeshMaterial(i, { color: 'blue', opacity: 1 })
})
})
}
/**
* 三维向量计算 物体变换后结果
*
* point 传入的坐标点 object: { position, rotation, scale }
*/
threeEditor.pointSyncTransform(point, mesh)
/**
* 获取场景曲线列表
*
* return [{ path, mesh }]
*/
threeEditor.getSceneCurveList()
/**
* 根据曲线生成曲线动画
*
* 参数 path => 曲线路径 speed => 速度
*
* return { time: 时间 0-1, speed, paused: 暂停, destroy: 销毁, frameCallback:(p) => 每一帧, frameEndCallback: () => 结束 } 实时更新
*
* 注: 返回的此对象并不针对一次动画, 重复动画, 将time 重置为0, paused 重置为false
*/
threeEditor.setCurveAnimation(curve, 1)
/**
* 案例: 物体曲线动画
*/
const { mesh, path } = threeEditor.getSceneCurveList()[0] // 获取一条曲线
const curveAnimate = threeEditor.setCurveAnimation(path, 1) // 生成当前曲线的动画控制器
const mesh1 = threeEditor.viewer.scene.getObjectByName('运动')
// 每一帧回调
curveAnimate.frameCallback = p => {
// 想要实现何种动画逻辑
mesh1.position.copy(
// 坐标点同步
threeEditor.pointSyncTransform(p, mesh)
)
}
curveAnimate.start()
/**
* 自定义物体变换动画 播放
*
* mesh/ group 下的transformAnimationList 为自定义变换动画列表 = [action, action]
*
* action = { name, _transformInfo: 旧变换信息 , transformInfo_: 新变换信息 , gsapParams { mode: gsap 函数方式 , query: gsapQuery } }
*
* setGsapMeshAction 执行物体的变换动画
*
* 传值 mesh, action._transformInfo, action.transformInfo_, action.gsapParams
*
* return promise => 动画执行
*/
const mesh = threeEditor.viewer.scene.getObjectByName('大楼')
const { transformAnimationList } = mesh
// 时间轴组合如
transformAnimationList.forEach((i, k) => {
setTimeout(() => {
i.gsapParams.query.onUpdate = () => { }
threeEditor.setGsapMeshAction(mesh, i._transformInfo, i.transformInfo_, i.gsapParams)
}, k * 2000)
})
/**
* 获取最佳视角
*
* model 模型对象 scale 视角缩放比例 默认2.5
*
* return { target, position }
*/
threeEditor.getBestViewTarget(model, scale)
/**
* 获取视图api
*
* getObjectViews(object, fov = camera.fov) return { 视图 点}
*/
threeEditor.getObjectViews(object)
/**
* 场景根物体根据 前缀进行分组
*
* 参数 prefix => '全部' || [ '场景1', '场景2']
*/
threeEditor.setSceneFromClassify(['#1'])
// ---:例 转场
const { camera, controls } = threeEditor.viewer
const [end, start] = controls.viewAngleList // 此前预设的两级下转视角
// 第一次视角切换
setGsapAnimationLook(start).then(() => {
// 场景模型切换 天空 等 任意操作
threeEditor.setSceneFromClassify(['场景2'])
threeEditor.setSky([])
// 第二次视角切换
setGsapAnimationLook(end)
})
function setGsapAnimationLook(viewAngle) {
return Promise.all([
new Promise((resolve) => {
threeEditor.setGsapAnimation(camera.position, viewAngle.position, { duration: 2, onComplete: resolve })
}),
new Promise((resolve) => {
threeEditor.setGsapAnimation(controls.target, viewAngle.target, { duration: 2, onComplete: resolve })
})
])
}
/**
* mesh 或 group 进行材质克隆
*
* 增加 isCloneMaterial = true 属性 originMaterial = 原材质 备份
*/
threeEditor.meshGroupCloneMaterial(mesh/group)
/**
* 额外 API
*
* import { createSkySphereShader, createScanPlane, getLight } from 'three-editor-cores'
*/
createSkySphereShader({ materialType }) // 返回天空球 mesh 属性调节 uniforms
createScanPlane({ materialType, url }) // 返回扫描平面 mesh 属性调节 uniforms
getLight('PointLight') // 返回光源
FAQs
security holding package
The npm package three-editor-release receives a total of 0 weekly downloads. As such, three-editor-release popularity was classified as not popular.
We found that three-editor-release demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 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.

Security News
minimatch patched three high-severity ReDoS vulnerabilities that can stall the Node.js event loop, and Socket has released free certified patches.

Research
/Security News
Socket uncovered 26 malicious npm packages tied to North Korea's Contagious Interview campaign, retrieving a live 9-module infostealer and RAT from the adversary's C2.

Research
An impersonated golang.org/x/crypto clone exfiltrates passwords, executes a remote shell stager, and delivers a Rekoobe backdoor on Linux.