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 🙏

© 2024 – Pkg Stats / Ryan Hefner

nsdt-3dconvert-viewer

v1.0.11

Published

3D模型在线预览,基于3dconvert的3D Viewer组件。3D模型在线转换。

Downloads

14

Readme

deploy

概述

3dconvert-viewer.js SDK是一款功能强大、易于集成的3D模型展示工具,它以3D模型在线转换平台的服务为基础,为广大开发者提供了一个高效、便捷的3D模型展示解决方案。通过这款SDK,客户可以轻松地将自己的3D模型集成到Web系统中,实现高质量的3D展示效果。

该SDK具有一系列令人瞩目的功能特点,包括但不限于光照、相机、剖切和拾取等。光照功能可以根据客户需求调整模型的光照效果,使得模型在展示时更加逼真;相机功能则允许用户自由调整视角和焦距,获得最佳的观看体验;剖切功能可以方便地对模型进行切割和查看内部结构,满足特定的展示需求;拾取功能则支持用户对模型进行交互操作,如点击、拖动等,增强了用户与模型的互动性。

3dconvert-viewer.js SDK的显示效果也非常出色。它采用了先进的渲染技术和优化算法,能够确保在Web环境中流畅地展示大型、复杂的3D模型。同时,SDK还支持多种格式的3D模型导入,方便客户使用现有的模型资源。

对于希望将3D模型集成到自己Web系统的客户来说,3dconvert-viewer.js SDK是一个理想的选择。它提供了简单易用的API接口和详细的文档支持,免服务端,使得开发者能够轻松地将其集成到现有的系统中。此外,SDK还提供了灵活的定制选项,可以根据客户的具体需求进行个性化设置,满足各种复杂的展示需求。

主要功能与特性

  1. 模型加载:通过指定模型资源fild,加载并显示3D模型。
  2. 交互控制:支持旋转、缩放、平移等基本视图控制,以及光照、视角、剖切、模型选择等高级设置。
  3. 扩展性良好:支持多种3D模型格式,可根据项目需求定制拓展功能。

快速开始

安装

$ npm install nsdt-3dconvert-viewer
// 使用
import Viewer from 'nsdt-3dconvert-viewer';

使用

html 代码

...
 <div id="viewer-container" style="width: 100%;height: 600px;border: 1px solid #000;"></div>
...

js 代码

// 引入3dconvert-viewer 
import Viewer from 'nsdt-3dconvert-viewer';

async function load3dModal() {
    // 创建Viewer实例,初始化参数为 Dom id 或者 HTMLElement
    const viewer = new Viewer('viewer-container');
	
    // 初始化
    await viewer.init();
    
    // 文件id 详细过程请参考:【获取fileId】章节
    const fileId = '687e6d1ec0'
    
    // 加载模型
    await viewer.loadObjectByFileId(fileId,{ enableCaching: false })

    // 注册事件监听器
    viewer.on('load-progress', (e) => {
      console.log('模型加载进度', e);
    });
}

load3dModal()

资源

开发demo 下载

3D大文件转换客户端 下载

BIM/CAD插件 下载

3Dconvert 服务私有化部署 查看

stp viewer 查看

3D模型在线转换 查看

GLTF在线编辑器 查看

获取fileId

3dconvert-viewer.js SDK 是3dconvert平台提供的3D模型web端预览组件。

这款SDK的设计以文件资源为核心。当您在3dconvert平台上传3D模型后,平台会为您的模型分配一个唯一的ID(fileId)。要查看这个fileId,您可以登录3dconvert平台,进入我的工作空间,然后点击我的上传,在相应的文件信息中找到fileId字段。

deploy

使用SDK加载与fileId对应的3D模型非常简单,只需编写少量代码(请参考示例代码)。如果您希望调整模型的展示效果或实现更个性化的功能,请查阅详细的API。

Vewer API

创建 Viewer 对象

// 创建 Viewer 对象

const viewer = new Viewer(container: HTMLElement, params: ViewerParams);
  • container: Viewer绑定的HTML元素

  • params: ViewerParams Viewer配置

    interface ViewerParams {
      showStats?: boolean
      environmentSrc?: Asset | string
    	verbose: boolean
    }
    • showStats: 启用/禁用viewer画布左上角的统计窗口
    • environmentSrc: 允许用户为viewer场景定义环境纹理,形式为equirectangular HDRI
    • verbose: 在控制台中显示其他信息和警告。

在开始使用viewer之前,您需要像下面这样对其进行初始化:

await viewer.init()

该函数是异步的,因为在这一步骤中,viewer要么加载所需的资产(如您可能在params中提供的HDRI),要么生成运行时资产。

事件绑定 ViewerEvent

on(eventType: ViewerEvent, handler: (arg) => void)
  • eventType : ViewerEvent

    enum ViewerEvent {
      ObjectClicked = 'object-clicked',
      ObjectDoubleClicked = 'object-doubleclicked',
      DownloadComplete = 'download-complete'
      LoadComplete = 'load-complete',
      LoadProgress = 'load-progress',
      LoadCancelled = 'load-cancelled',
      UnloadComplete = 'unload-complete',
      UnloadAllComplete = 'unload-all-complete',
      Busy = 'busy',
      SectionBoxChanged = 'section-box-changed'
      SectionBoxUpdated = 'section-box-updated'
    }
  • handler: 回调函数

加载和卸载模型

Viewer通过文件id加载存储在服务端的模型

loadObject(fileId: string, {enableCaching?: boolean}): Promise<void>
  • fileId: 模型对应的文件id
  • enableCaching: 启用/禁用浏览器中的数据缓存。默认为true

卸载模型

unloadObject(): Promise<void>

相机控制

控制视角
setView(view: CanonicalView)

用于操作相机的视角

  • view: CanonicalView:

    type CanonicalView =
      | 'front'
      | 'back'
      | 'up'
      | 'top'
      | 'down'
      | 'bottom'
      | 'right'
      | 'left'
      | '3d'
      | '3D'
透视/正交相机切换
toggleCameraProjection()
Z/Y轴向上切换
toggleZXAxisUpFixed()

选中模型对象

设置模型选中并且高亮

selectObjects(objects:[]<objectId>);
  • objects: objectId集合

当用户在viewer中点击某个3d对象时,监听ObjectClickedObjectDoubleClicked事件的回调函数会收到SelectionEvent信息:

type SelectionEvent = {
  multiple: boolean
  event?: PointerEvent
  hits: Array<{
    guid?: string
    object: Record<string, unknown>
    point: Vector3
  }>
}
  • 当没有点击对象时,则会使用 null 作为参数触发 ObjectClicked 事件

作为一个简单的例子,在单击对象时将其高亮并且聚焦:

viewer.on(ViewerEvent.ObjectClicked, (selectionInfo: SelectionEvent) => {
  if (selectionInfo) {
  	// 选中对象 并且高亮对象
  	viewer.selectObjects([selectionInfo.hits[0].object.id])
	// 对象聚焦
    viewer.zoom([selectionInfo.hits[0].object.id ])
  }
	else {
		//没有点击的对象。聚焦整个场景
		viewer.zoom()	
	}
})

剖切盒

Viewer提供了一个可配置的剪切盒功能,可用于查看场景的部分内容。

setSectionBox(
  box?: {
    min: { x: number; y: number; z: number }
    max: { x: number; y: number; z: number }
  },
  offset?: number
)

使用即时盒子定义设置切割盒的尺寸。

  • box:切割盒尺寸的盒子定义。如果未提供此参数,则切割盒将调整为整个场景大小。
  • offset:用于增加/减小切割盒的可选乘数,默认为0.05
setSectionBoxFromObjects(objectIds: string[], offset?: number)**

根据一组对象设置切割盒的尺寸。

  • objectIds:我们希望调整切割盒的对象ID。切割盒的尺寸将是其组合轴对齐边界框的结果。
  • offset:用于增加/减小切割盒的可选乘数,默认为0.05

启用切割盒。

sectionBoxOn(): void

禁用切割盒。

sectionBoxOff(): void

切换切割盒的开/关状态。

toggleSectionBox(): void

光照控制

设置光照

setLightConfiguration(config: LightConfiguration): void

config: LightConfiguration

interface LightConfiguration {
  enabled?: boolean
  castShadow?: boolean
  intensity?: number
  color?: number
  indirectLightIntensity?: number
}

interface SunLightConfiguration extends LightConfiguration {
  elevation?: number
  azimuth?: number
  radius?: number
}
  • enabled:启用/禁用太阳直射光
  • castShadow:启用/禁用太阳光投射阴影
  • intensity:太阳光的强度
  • color:太阳光的颜色(以 int 类型表示)
  • indirectLightIntensity:环境光强度(IBL)的强度
  • elevation:太阳球面角(以弧度为单位)
  • azimuth:太阳球面方位角(以弧度为单位)
  • radius:从场景包围球半径的偏移距离

系统默认配置:

export const DefaultLightConfiguration = {
  enabled: true, // 太阳阴影是否开启
  castShadow: false,
  intensity: 3, // 太阳光强度
  color: 0xffffff,
  elevation: 1.8, // 太阳高度
  azimuth: 0.75, // 太阳方位角
  radius: 0,
  indirectLightIntensity: 2,
  shadowcatcher: false,
};

详细开发示例

代码示例

我们以Vue3 hooks方式开发一个viewerHook, 该hook是的主要功能有加载模型模型加载进度模型Z轴|Y轴向上切换模型显示模式切换模型光照设置

直接上代码`viewerHooks.ts:

//@ts-nocheck
import { ref } from 'vue'
import Viewer from '../lib/3dconvert-viewer.js'

const ViewerEvent = {
  ObjectClicked: 'object-clicked',
  ObjectDoubleClicked: 'object-doubleclicked',
  DownloadComplete: 'download-complete',
  LoadComplete: 'load-complete',
  LoadProgress: 'load-progress',
  UnloadComplete: 'unload-complete',
  LoadCancelled: 'load-cancelled',
  UnloadAllComplete: 'unload-all-complete',
  Busy: 'busy',
  SectionBoxChanged: 'section-box-changed',
  SectionBoxUpdated: 'section-box-updated',
}

const DefaultLightConfiguration = {
  enabled: true,
  castShadow: false, // 太阳阴影是否开启
  intensity: 3, // 太阳光强度
  color: 0xffffff,
  elevation: 1.8, // 太阳高度
  azimuth: 0.75, // 太阳方位角
  radius: 0,
  indirectLightIntensity: 2,
  shadowcatcher: false,
}

export const useViewer = function () {
  const viewerRef = ref<any>()

  /***
   * y轴向上和z轴向上切换
   */
  const yup = ref(false) // 默认z轴向上
  const onZYUp = () => {
    viewerRef.value.toggleZXAxisUpFixed()
    const up = viewerRef.value?.cameraHandler?.camera?.up
    yup.value = up.y === 1
  }

  /**
   * viewer 显示模型切换  3d模型/看图模式
   */
  const vieweMode = ref<number>(1)
  const onVieweModeChange = () => {
    vieweMode.value = vieweMode.value === 1 ? 2 : 1
    viewerRef.value.toggleViewerMode()
  }

  /**
   * 剖切盒
   */
  const onCut = () => {
    viewerRef.value.setSectionBox()
    viewerRef.value.toggleSectionBox()
  }

  /**
   * 光照变化
   * @param config
   */
  const sunConfig = ref({ ...DefaultLightConfiguration })
  const sunConfigChange = config => {
    sunConfig.value = config
    setTimeout(() => {
      viewerRef.value.setLightConfiguration(sunConfig.value)
    }, 60)
  }

  /**
   * 进度,及是否加载完成
   */
  const loadProgress = ref<number>(0)
  const loading = ref<boolean>(false)

  const progressChange = evt => {
    loading.value = (evt?.progress || 0) > 0 && (evt?.progress || 0) < 100
    loadProgress.value = ((evt?.progress || 0) * 100).toFixed(2)
  }
  const loadComplete = () => (loading.value = false)

  /**
   * 选中 模型对象 模型高亮
   * @param meshClickEvent
   */
  const selectObject = meshClickEvent => {
    const objects = (meshClickEvent?.hits || []).map(item => item.object.id)
    viewerRef.value.selectObjects(objects)
  }
  
  /**
   * viewer 初始化函数
   * @param fileId 文件id
   */
  const viewerInit = async (dom: any, fileId: any) => {
    const viewer = new Viewer(dom)
    viewerRef.value = viewer

    viewerRef.value.setLightConfiguration(DefaultLightConfiguration)
    await viewerRef.value.init()

    /**
     * 监听:[ 进度 | 点击 | 完成 ] 事件
     */
    viewerRef.value.on(ViewerEvent.LoadProgress, progressChange)
    viewerRef.value.on(ViewerEvent.ObjectClicked, selectObject)
    viewerRef.value.on(ViewerEvent.LoadComplete, loadComplete)

    if (fileId) await viewer.loadObjectByFileId(fileId, { enableCaching: true })
  }

  return {
    viewerInit,           // viewer 初始化函数             Function
    loadProgress,         // 加载模型进度
    loading,              // 是否正在加载中
    sunConfig,            // 光照参数
    vieweMode,            // 显示模式
    
  	sunConfigChange,      // 光照参数变化函数                Function
    onVieweModeChange,    // 显示模式切换函数                Function
    onZYUp,               // z|y 轴向上切换函数             Function 
    onCut,                // 剖切盒打开|关闭函数             Function
  }
}

在vue组件中使用viewerHook示例代码如下

<template>
    ....
</template>

<script setup lang="ts">
import { useViewer } from  './hooks/viewerHooks'
    
/**
 * Viewer use Function
 */
const {
  loadProgress,     
  loading,          
  vieweMode,        
  sunConfig,        
  viewerInit,       
  onZYUp,           
  onCut,            
  onVieweModeChange,
  sunConfigChange,  
} = useViewer()

// 文件id
const fileId = 'cb1224158a'

onMounted(async () => {
  await viewerInit('share3dviewer', fileId)
})

....
</script>

完整代码资源

您可以通过以下地址获取

下载 3dconvert-viewer-demo.zip

这是一个完整的Vue3项目,下载解压运行之后可以直接查看预览效果,并且Viewer对象与模型的交互都已经做好,可以体验交互!

使用方法

yarn 
yarn dev

or npm

npm install
npm run dev

访问 http://localhost:5175

去除背景水印(可选)

如果你希望去除背景中的水印(nsdt.cloud),在模型内嵌对话框中点击【去除水印】即可,如下图所示:

demopage

或者进入【我的工作台】,在【我的上传】中找到对应的文件,点击【去水印】即可,如下图所示:

demopage

联系我们

如果有SDK使用上的疑问或者需要对SDK功能进行个性化的扩展,请联系我们

contact

3D转换工具