You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Thingworx开发ThreeJS扩展时widget-content下canvas渲染异常问题

问题根因

你遇到的渲染异常是Thingworx内置的.widget-content样式约束,叠加布局时序、渲染逻辑缺失共同导致的,具体原因和修复方案如下:

  1. Thingworx默认给.widget-content类设置了padding、overflow:hidden、固定定位等样式,会挤压canvas的实际渲染区域,导致你初始化时设置的宽高和实际渲染尺寸不匹配,球体被裁剪到可视范围外
  2. 你在afterRender阶段获取的宽高是配置项的固定值,此时Thingworx还未完成widget容器的布局渲染,拿到的尺寸和实际容器尺寸不一致,相机宽高比错误
  3. 仅在控制器触发change事件时才执行渲染,没有持续的渲染循环,场景更新后不会自动重绘,仅交互时才会触发单次渲染

修复方案

1. 修改renderHtml方法,新增自定义类避免样式冲突

// runtime.ts file
renderHtml(): string {
    // 给外层容器加自定义类覆盖默认样式,canvas设置为块级元素撑满容器
    let htmlString = '<div class="widget-content three-widget-container"><canvas style="display:block;width:100%;height:100%;"></canvas></div>';
    return htmlString;
}

2. 新增自定义样式覆盖默认规则

在你的扩展的css文件中添加如下样式,也可以在afterRender中动态插入style标签:

.three-widget-container {
    position: relative !important;
    padding: 0 !important;
    margin: 0 !important;
    overflow: visible !important;
    width: 100% !important;
    height: 100% !important;
}

3. 修改afterRender逻辑,适配Thingworx布局时序

afterRender(): void {
    const OrbitControls = require('three-orbit-controls')(CourseView);
    const OBJLoader = require('three-obj-loader')(CourseView);

    const scene = new CourseView.Scene();
    // 直接获取容器实际渲染尺寸,而非配置项的固定值
    const container = this.jqElement.find(".three-widget-container").get(0);
    let width = container.clientWidth;
    let height = container.clientHeight;
    const color = this.getProperty('SceneColor', '#000000') || "#000000";

    const camera = new CourseView.PerspectiveCamera(75, width / height, 0.1, 1000);
    camera.position.z = 30;

    const cv = this.jqElement.find("canvas").get(0);
    this.renderer = new CourseView.WebGLRenderer({canvas: cv, antialias: true});
    this.renderer.setSize(width, height);
    this.renderer.setClearColor("#0000ff");

    const control = new OrbitControls(camera, this.renderer.domElement);
    control.update();

    const geometry = new CourseView.SphereGeometry( 15, 32, 16 );
    const material = new CourseView.MeshBasicMaterial( { color: 0xff00ff, wireframe: true } );
    const sphere = new CourseView.Mesh( geometry, material );
    scene.add( sphere );

    // 新增渲染循环,保证场景自动更新
    const animate = () => {
        requestAnimationFrame(animate);
        control.update();
        this.renderer.render(scene, camera);
    }
    animate();

    // 监听容器尺寸变化,同步更新渲染参数
    const resizeObserver = new ResizeObserver(entries => {
        const { width: newWidth, height: newHeight } = entries[0].contentRect;
        camera.aspect = newWidth / newHeight;
        camera.updateProjectionMatrix();
        this.renderer.setSize(newWidth, newHeight);
    });
    resizeObserver.observe(container);
}

myRender(scene, camera) {
    this.renderer.render(scene, camera);
}

内容的提问来源于stack exchange,提问作者CaipiDE

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 08:45:01