场景切换 × 流畅过渡动画实现方案 | 图扑软件

在图扑 HT 项目中,尤其是复杂应用里,单一场景或图纸通常难以承载所有需求,因此在多个图纸或场景之间进行切换是一种常见的实现方式。本文将深入解析图扑 HT 项目中场景/图纸切换的核心实现方法,并详细介绍如何为切换过程添加流畅自然的过渡效果,以提升用户体验。

场景 / 图纸核心切换步骤

图扑 HT 项目中,实现图纸或场景的无缝切换需严格遵循以下关键步骤,以避免潜在问题并确保切换过程稳定可靠:

  1. 清除当前的数据模型使用 dataModel.clear() 清除当前场景关联的所有数据模型。
  2. 反序列化新场景/图纸通过 view.deserialize(url) 方法加载并反序列化新的场景或图纸资源文件,完成新场景的载入。

注意:

不建议通过创建多个 ht.graph3d.GraphView 进行切换。

原因在于 ht.graph3d.GraphView 是基于 WebGL 的 3D 渲染组件。而多数浏览器对单个页面可运行的 WebGL 上下文数量有严格限制。频繁创建新实例会导致内存泄漏或资源耗尽,引发场景显示异常甚至浏览器崩溃。

场景切换过渡效果

为了在场景切换时获得更流畅、更具视觉吸引力的体验,可以添加过渡动画。常见的实现思路有两种:

利用场景属性实现过渡

通过控制场景的特定属性,在切换过程中产生动态过渡效果,常见的有景深动画和亮度调节等。

景深动画过渡

景深效果主要通过以下两个属性控制:

  • image 属性:模拟景深的贴图(通常为四周黑色、中间透明的 PNG 图片,黑色区域应用景深模糊,透明区域保持清晰)。
  • aperture(孔径)属性:代表中间空白区域的大小,取值范围 0~1,0 表示无景深效果,1 表示景深效果最明显。

实现步骤

使用一张全黑景深贴图(确保整个场景受景深影响),在旧场景切换前开启景深并执行递增孔径值的动画,新场景加载后执行递减孔径值的动画,形成"渐隐渐显"的过渡效果。

复制代码
let dof = g3d.getPostProcessingModule('Dof');
dof.image = 'assets/景深.png'
dof.aperture = 0
// 景深开启
g3d.enablePostProcessing('Dof', true);
let anim = {
      duration: 800,
      easing: (t: number) => {
          return t * t;
      },
      action: (v: number, t: number) => {
          // 动态设置景深阈值
          dof.aperture = v * 0.2
      }
}
ht.Default.startAnim(anim);

复制代码
 

**新场景反序列化后,新场景也需要执行景深动画。**这时执行的景深动画跟旧场景的景深动画区别在于 action 中的逻辑是递减的过程:dof.aperture =0.2-v*0.2。

其他属性过渡效果

除景深外,还可通过调节亮度等场景属性实现过渡,原理与景深动画一致:

  • 旧场景切换前,执行属性动画(如亮度逐渐降低至 0,场景变暗);
  • 新场景加载后,执行反向动画(如亮度从 0 逐渐恢复至正常值,场景变亮)。

利用 2D 图纸动画实现过渡

通过在 3D 场景上层叠加 2D 图纸,利用 2D 元素的动画效果遮蔽切换过程,创意自由度更高,为整体呈现带来了更多的艺术动感和技术深度。

帧动画过渡(云朵过渡)

旧场景被"云朵"图片序列逐渐覆盖(遮蔽),切换新场景后,"云朵"再逐渐消散以展现新场景。

实现步骤

  1. 准备一组连续的过渡图片(如从透明到完全遮蔽再到透明的云朵图片序列);
  2. 旧场景切换前,执行动画使图片从初始状态过渡到完全遮蔽场景;
  3. 新场景加载后,执行反向动画使图片从完全遮蔽过渡到消失。

代码示例

复制代码
const cloudList = [
    "assets/cloud1.png",
    "assets/cloud2.png",
    ...
    "assets/cloud20.png",
];
const image = this.getDataByTag('cloud');
let i = 0;
ht.Default.startAnim({
    frames: 20,
    interval:50,
    action: (t) => {
        cloudList[i] && image.setImage(cloudList[i]);
    }
})

在新旧场景内执行的动画代码基本一样,区别在于切换前 action 中是从第一张图片切换到最后一张,在新场景反序列化后是从最后一张切换回第一张。

其他创意效果

利用 2D 覆盖层进行过渡的核心优势在于创意自由度极高。开发者可以结合 HT 强大的 2D 动画能力,对覆盖元素应用多种属性动画组合:

  • 渐入渐出的遮罩层动画;
  • 模拟镜头推拉的缩放动画;
  • 基于路径的元素移动动画;
  • ......

2D 图纸间切换过渡

前文主要探讨了 3D 场景的切换过渡。同样地,在纯 2D 图纸 (ht.graph.GraphView) 之间进行切换时,也可以利用 HT 的 2D 特性实现平滑的过渡效果。一种实用的方法是动态生成并动画化当前视图的缩略图。

利用缩略图过渡

在图纸切换前动态生成缩略图并施加动画,实现平滑过渡的效果,具体的实现步骤:

  • **生成当前视图缩略图:**在触发图纸切换前,使用 gv.toDataURL() 生成当前视图的缩略图。
  • 创建过渡节点:

生成与图纸视图窗口尺寸相同的节点。

将缩略图设置为该节点的内容。

  • **应用动画效果:**在动画中调整缩略图节点的裁切、透明等属性,以达到过渡效果。

代码示例

复制代码
functiongenerateThumbnail() {
     var jsonSerializer = new ht.JSONSerializer(dm); // 创建序列化器,并传入旧图纸的 dm
     jsonSerializer.isSerializable = function (data) { // 过滤节点
         return data.getTag() != 'mask';
     }
     var json = ht.Default.parse(jsonSerializer.serialize()); 
     json.a = {};
     const gv = new ht.graph.GraphView(); // 创建一个新的2D 视图
     gv.dm().deserialize(json); // 反序列化

     const thumbnail = gv.toDataURL(null, null, 1, 0); // 生成缩略图
}
functioncreateThumbnailData(thumbnail){
     const thumbnail_data = new ht.Node(); // 生成缩略图节点
     thumbnail_data.setImage(thumbnail);
     const contentRect = gv.getContentRect(); // 获取所有图元占用的矩形区域
     const rect = div.getBoundingClientRect();// 获取2D视图尺寸
     const width = rect.width;
     const height = rect.height;
     thumbnail_data.p({ x: contentRect.x + contentRect.width / 2, y: contentRect.y + contentRect.height / 2 }) // 为缩略图节点设置位置
     thumbnail_data.setSize({ width, height });// 为缩略图节点设置尺寸
     thumbnail_data.setScale(contentRect.width / width, contentRect.height / height);// 为缩略图节点设置缩放
     thumbnail_data.setAnchor({ x: 0.5, y: 0.5 });
     dm.add(thumbnail_data);

     const mask = dm.getDataByTag('mask'); 
     thumbnail_data.setHost(mask); 
     thumbnail_data.s('clip.host', true); // 开启吸附裁切后,缩略图节点会根据吸附的节点进行裁切

     ht.Default.startAnim({
        duration: 2000,
        easing: function (t) { return t; },
        finishFunc: function () {
              dm.remove(thumbnail_data); // 动画结束后移除缩略图节点
        },
        action: function (v, t) {
              thumbnail_data.s('opacity', 1 - v + 0.1);
              mask.setScaleX(1 - v);
              thumbnail_data.iv();
        }
     });
}

view.mi((e) =>{
  if(e.kind === 'onClick' && e.type === 'data'){
        if(e.data.getTag() === 'switchBtn'){ // 点击按钮切换图纸
        const thumbnail = generateThumbnail(); // 生成缩略图
        ....
        createThumbnailData(thumbnail); // 生成缩略图节点
        ...
      }
    }
})

总结

在图扑软件 HT 项目中实现场景/图纸切换,关键在于遵循 dataModel.clear() + view.deserialize() 的核心步骤,并避免重复创建 ht.graph3d.GraphView 实例。

为了提升用户体验,添加过渡效果是重要环节。无论是通过动态调整场景后处理属性(如景深、亮度)还是利用精心设计的 2D 图纸动画(如帧序列),本质上都是对 HT 引擎灵活性和设计者创意的结合应用。不仅优化了技术流程,更能创造出引人入胜的视觉表现,是当前 Web 可视化项目中的重要实践。

您可以至图扑软件官网查看更多案例及效果:

https://www.hightopo.com/demos/index.html

相关推荐
铅笔侠_小龙虾13 小时前
大话 IOT 技术(1) -- 架构篇
物联网·架构
一袋米扛几楼981 天前
【物联网】MQTT / Broker / Topic 是什么?
网络·物联网
DreamLife☼1 天前
工业 5G + AI:智能制造的未来引擎
人工智能·5g·ai·制造·控制·工业·scada
阿幸软件杂货间2 天前
SimLab Composer8.2_win中文_3D绘画_安装教程
3d·设计
麦麦大数据2 天前
vue+Django 双推荐算法旅游大数据可视化系统Echarts mysql数据库 带爬虫
数据库·vue.js·django·可视化·推荐算法·百度地图·旅游景点
丁同亚的博客2 天前
echarts大屏项目指南
echarts·可视化·js·web前端·大屏
云望无线图传模块2 天前
突破视界的边界:16公里远距离无人机图传模块全面解析
网络·物联网·无人机
清风6666662 天前
基于STM32单片机的OneNet物联网云平台农业土壤湿度控制系统
stm32·单片机·物联网·毕业设计·课程设计
曼彻斯特的海边2 天前
物联网(IoT)中常用的通信协议
物联网·iot