【babylonjs】环形屏幕3d展示

0.前言:

前阵子接到一个需求是需要开发一个能够跑在环形屏幕上的3d展示项目

刚接到这个项目的时候我以为能吧相机fov直接调整成360°,后来发现我想多了。。babylonjs中的相机最大视角就是π(180°)

然后我又想说,那我干脆两个相机拼一起。

但是两个相机边缘会有失真,效果不好效果不好。

算了 暴力一点,我写了个全景相机类,想用几个相机拼接用几个相机,相机数量越多拼接的越丝滑,移动的话利用主相机的控制器进行移动,其他副相机都绑在这个相机身上。

(本文完整代码连接如下,为ts编写,需要js移步ts官网的playground编译成自己需要的版本)

AnnularCamera.tshttps://gitee.com/Susiia/babylon-standard-framework/blob/master/src/assets/ts/tools/AnnularCamera.ts


1.使用方法:

首先导入

import AnnularCamera from "./AnnularCamera.ts";

然后使用

  // 默认相机
  private defaultCamera ():void {
    this.camera = new AnnularCamera('defaultCamera', new Vector3(0, 2, -2), this.scene)
    this.camera.ellipsoid = new Vector3(0.15, 0.9, 0.15)
    this.camera.speed = 0.2
    this.camera.checkCollisions = true
    this.camera.applyGravity = true
    this.camera.attachControl(this.canvas, true)
  }

齐活儿


2.代码讲解

首先导入我们需要的东西

import { Scene, UniversalCamera, Vector3, Viewport } from '@babylonjs/core'

创建AnnularCamera类

export default class AnnularCamera {
    constructor (
        name:string, // 相机名
        position:Vector3, // 位置
        scene:Scene, // 场景
        CameraCount?:number // 相机数量
    ){
        //...
    }
}

声明所需要的私有变量

  private _name: string // 相机名
  private readonly scene:Scene // 场景
  private readonly mainCamera:UniversalCamera // 主相机
  private deputyCameras:UniversalCamera[] = [] // 副相机组
  private readonly CameraCount:number // 相机数量
  private _position:Vector3 // 相机位置
  private _ellipsoid!:Vector3 // 碰撞检测盒子大小
  private _speed!: number // 相机速度
  private _checkCollisions!: boolean // 检查碰撞检测
  private _applyGravity!: boolean // 应用重力

在构造函数中进行初始化操作

constructor (
    name:string, // 相机名
    position:Vector3, // 位置
    scene:Scene, // 场景
    CameraCount?:number // 相机数量
  ) {
  // 初始化相机名
    this._name = name
    // 初始化相机位置
    this._position = position
    // 初始化相机数量
    this.CameraCount = (CameraCount || 4) < 4 ? 4 : (CameraCount || 4)
    // 初始化场景
    this.scene = scene
    // 初始化主相机
    this.mainCamera = new UniversalCamera(
      this._name,
      this.position,
      this.scene
    )
    this.mainCamera.fov = Math.PI / (this.CameraCount / 2) // 设置主相机视野
    this.mainCamera.fovMode = UniversalCamera.FOVMODE_HORIZONTAL_FIXED // 设置主相机视野模式
    // eslint-disable-next-line no-unused-expressions
    scene.activeCameras?.push(this.mainCamera) // 主相机推入场景激活相机组
    this.mainCamera.viewport = new Viewport(0, 0, 1 / this.CameraCount, 1) // 设置主相机视口
    // 初始化副相机组
    for (let i = 0; i < this.CameraCount - 1; i++) {
    // 定义副相机
      const deputyCamera = new UniversalCamera(
        this._name + 'Camera' + (i + 1),
        new Vector3(0, 0, 0),
        this.scene
      )
      deputyCamera.parent = this.mainCamera // 设置父级别为主相机
      this.deputyCameras.push(deputyCamera) // 推入副相机组
      // eslint-disable-next-line no-unused-expressions
      scene.activeCameras?.push(deputyCamera) // 副相机推入场景激活相机组
      deputyCamera.rotation = new Vector3(0, (Math.PI / (this.CameraCount / 2)) * (i + 1), 0) // 设置副相机旋转
      deputyCamera.fov = Math.PI / (this.CameraCount / 2) // 设置相机视野
      deputyCamera.fovMode = UniversalCamera.FOVMODE_HORIZONTAL_FIXED // 设置相机视野模式
      deputyCamera.viewport = new Viewport((1 / this.CameraCount) * (i + 1), 0, 1 / this.CameraCount, 1) // 设置相机视口
    }
  }

公开主相机的attachControl

  public attachControl = (canvas: HTMLCanvasElement, noPreventDefault?: boolean | undefined):void => {
    this.mainCamera.attachControl(canvas, noPreventDefault)
  }

将主相机常用的一些方法和属性用setter和getter公开

  /*
  * getter/setter
  */

  // 碰撞检测盒getter/setter
  public get ellipsoid (): Vector3 {
    return this._ellipsoid
  }

  public set ellipsoid (value: Vector3) {
    this.mainCamera.ellipsoid = value
    this._ellipsoid = value
  }

  // 相机位置getter/setter
  public get position (): Vector3 {
    return this._position
  }

  public set position (value: Vector3) {
    this.mainCamera.position = value
    this._position = value
  }

  // 相机名getter/setter
  public get name (): string {
    return this._name
  }

  public set name (value: string) {
    this.mainCamera.name = value
    this._name = value
  }

  // 相机速度
  public get speed (): number {
    return this._speed
  }

  public set speed (value: number) {
    this.mainCamera.speed = value
    this._speed = value
  }

  // 是否应用碰撞检测
  public get checkCollisions (): boolean {
    return this._checkCollisions
  }

  public set checkCollisions (value: boolean) {
    this.mainCamera.checkCollisions = value
    this._checkCollisions = value
  }

  // 是否应用重力
  public get applyGravity (): boolean {
    return this._applyGravity
  }

  public set applyGravity (value: boolean) {
    this.mainCamera.applyGravity = value
    this._applyGravity = value
  }

齐活儿。


3.使用

放映的时候,用英伟达或者amd驱动的跨屏幕融合吧环形屏幕搞成理论上的一整块,然后网页全屏就可以用。


4.后记

其实现在还有一些问题,就是目前移动控制器的正向是主相机的朝向,在上面画面的最左侧,之后还需要优化一下,将主相机挪到画面的中间(最好是能够随意挪动,想放在第几个放在第几个)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 ECharts 中,可以通过设置 `series` 中的 `label` 属性来在环形图中间展示数据。具体方法如下: 1. 在 `series` 中添加环形图的配置,例如: ```javascript series: [ { name: '访问来源', type: 'pie', radius: ['40%', '60%'], avoidLabelOverlap: false, label: { show: false, position: 'center' }, emphasis: { label: { show: true, fontSize: '30', fontWeight: 'bold' } }, labelLine: { show: false }, data: [ {value: 335, name: '直接访问'}, {value: 310, name: '邮件营销'}, {value: 234, name: '联盟广告'}, {value: 135, name: '视频广告'}, {value: 1548, name: '搜索引擎'} ] } ] ``` 2. 在 `label` 属性中设置 `show: true`,表示显示标签。 ```javascript label: { show: true, position: 'center', formatter: '{a|Total}\n{b|{c}}', rich: { a: { color: '#999', fontSize: 14, lineHeight: 20 }, b: { color: '#333', fontSize: 18, lineHeight: 25 } } }, ``` 其中 `formatter` 属性用来设置标签显示的内容,`rich` 属性用来设置标签内容的样式,例如颜色、字体大小等。在这个例子中,标签内容分为两行,第一行为 "Total",第二行为数据的和。 完整的代码如下: ```javascript option = { title: { text: '环形图', subtext: '数据来源:XXX' }, tooltip: { trigger: 'item', formatter: '{a} <br/>{b}: {c} ({d}%)' }, legend: { orient: 'vertical', left: 10, data: ['直接访问', '邮件营销', '联盟广告', '视频广告', '搜索引擎'] }, series: [ { name: '访问来源', type: 'pie', radius: ['40%', '60%'], avoidLabelOverlap: false, label: { show: true, position: 'center', formatter: '{a|Total}\n{b|{c}}', rich: { a: { color: '#999', fontSize: 14, lineHeight: 20 }, b: { color: '#333', fontSize: 18, lineHeight: 25 } } }, emphasis: { label: { show: true, fontSize: '30', fontWeight: 'bold' } }, labelLine: { show: false }, data: [ {value: 335, name: '直接访问'}, {value: 310, name: '邮件营销'}, {value: 234, name: '联盟广告'}, {value: 135, name: '视频广告'}, {value: 1548, name: '搜索引擎'} ] } ] }; ``` ### 回答2: ECharts是一个用于数据可视化的JavaScript图表库。它提供了丰富的图表类型和灵活的配置选项,可以帮助开发者快速地创建各种各样的图表。其中,环形图(Pie Chart)是一种常用的图表类型,它可以用来展示数据的占比情况。 在ECharts的环形图中间展示数据,通常可以通过设置label和tooltip的方式来实现。label是用于展示图表上各个扇形区域的文本标签,而tooltip则用于在鼠标悬停时显示详细信息。 在ECharts中,可以使用series配置项来设置环形图的数据。每一个数据项可以包含多个字段,其中value字段表示数据的数值。可以利用这个字段来在环形图中间展示数据。 为了将数据展示环形图中间,可以设置label的position属性为'inner',表示文本标签位于扇形区域内部。同时,可以将formatter属性设置为'{c}',表示label的内容为数据项的值。这样,就可以实现在环形图中间展示数据的效果。 除了设置label,还可以设置tooltip来显示详细信息。可以将tooltip的formatter属性设置为'{b} : {c}',显示数据项的名称和值。这样,在鼠标悬停时,就能在tooltip中显示扇形区域的名称和对应的数值。 通过以上的设置,就可以在ECharts的环形图中间展示数据。通过label和tooltip的配合使用,可以让用户清晰地了解每个扇形区域的数值和占比情况。这样,就能更好地传达数据的信息,提升数据可视化的效果。 ### 回答3: 在Echarts环形图中,可以通过在中间展示数据来提供更直观的信息呈现。一种常见的方式是在环形图中间绘制一个中央文本框,用于显示关键数据。 首先,在Echarts的配置项中,我们可以通过设置series的label属性来实现中央文本框的绘制。具体来说,我们可以设置label属性的formatter参数,通过自定义格式化函数来确定中央文本框中要显示的内容。 其次,在自定义的格式化函数中,我们可以根据需求选择性地呈现不同的数据。例如,可以显示该环形图的总体数据,或者某个特定阶段的数据等。通过在格式化函数中处理数据,并将其作为返回值进行展示,我们可以根据实际需要灵活地展示不同的数据。 同时,我们还可以进一步美化中央文本框的样式,如调整文本的字体大小、颜色、位置等,以及添加背景色、边框等效果,从而使整个环形图更加美观和易读。 总的来说,在Echarts环形图中间展示数据是一种向用户展示关键信息的有效方式。通过合理地设置配置项和自定义格式化函数,我们可以灵活地展示环形图中不同的数据,并为用户提供更加直观和清晰的图形化呈现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值