HarmonyOS鸿蒙Next中JS开发3D建模软件网页三维CAD中绘制一个窗户模型

HarmonyOS鸿蒙Next中JS开发3D建模软件网页三维CAD中绘制一个窗户模型

前言

本文使用mxcad3d在网页中创建一个简单的三维窗户模型,mxcad3d提供了丰富的三维建模功能和便捷的API,使得创建各种三维模型变得简单方便,最终效果如下图:

1728875232217.jpg

环境搭建和入门

首先学习mxcad的基本使用方法,可通过官方的入门教程来搭建一个最基本的项目模板,依次查看教程:安装Node.js以及VS Code开发工具、创建mxcad开发项目、API文档接口使用说明。

压缩包下载解压后需要在项目目录下打开cmd命令行,然后在命令行中执行npm install来安装依赖,然后再按照本教程中的方式来运行项目查看效果。

编写创建窗户模型的代码

  1. 根据官方快速入门教程来创建一个名为Test3dWindow的项目,如下图:

1728873070449.jpg

  1. 编写绘制窗户模型的代码

在index.html中插入一个按钮"绘制窗户模型", index.html的完整代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>vite use mxcad</title>
</head>
<body>
    <div style="height: 800px; overflow: hidden;"> <canvas id="myCanvas"></canvas></div>
    <button>绘制窗户模型</button>
    <script type="module" src="./src/index.ts"></script>
</body>
</html>

在src/index.ts中编写绘制窗户模型的函数,src/index.ts的完整代码如下:

import { MdGe, Mx3dGeAxis, Mx3dGeColor, Mx3dGeDir, Mx3dGeMaterial, Mx3dGeomPlane, Mx3dGePoint, Mx3dGeVec, Mx3dMkBox, Mx3dMkFace, Mx3dMkPolygon, Mx3dMkPrism, MxCAD3DObject } from "mxcad"
// 创建mxcad3d对象
const mxcad3d = new MxCAD3DObject()
// 初始化mxcad3d对象
mxcad3d.create({
    // canvas元素的css选择器字符串(示例中是id选择器),或canvas元素对象
    canvas: "#myCanvas",
    // 获取加载wasm相关文件(wasm/js/worker.js)路径位置
    locateFile: (fileName)=> new URL(`/node_modules/mxcad/dist/wasm/3d/${fileName}`, import.meta.url).href,
})
// 初始化完成
mxcad3d.on("init", ()=>{
    console.log("初始化完成");
    // 修改背景颜色
    const color1 = new Mx3dGeColor(61/255, 139/255, 221/255, MdGe.MxTypeOfColor.Color_TOC_sRGB);
    const color2 = new Mx3dGeColor(203/255, 223/255, 247/255, MdGe.MxTypeOfColor.Color_TOC_sRGB);
    mxcad3d.setGradientBgColor(color1, color2, MdGe.MxGradientFillMethod.GFM_VER);
    // 设置透视投影
    mxcad3d.setProjectionType(MdGe.MxCameraProjection.CProjection_Perspective);
    // 打开光照阴影
    mxcad3d.enableDirLightSrc(true);
});
function drawWindow(){
    // 窗户边框横截面轮廓点
    const pts: Mx3dGePoint[] = [];
    pts.push(new Mx3dGePoint(0, 0, 0));
    pts.push(new Mx3dGePoint(1, 0, 0));
    pts.push(new Mx3dGePoint(1, 0, 2));
    pts.push(new Mx3dGePoint(4, 0, 2));
    pts.push(new Mx3dGePoint(4, 0, 0));
    pts.push(new Mx3dGePoint(5, 0, 0));
    pts.push(new Mx3dGePoint(5, 0, 10));
    pts.push(new Mx3dGePoint(3, 0, 10));
    pts.push(new Mx3dGePoint(3, 0, 8));
    pts.push(new Mx3dGePoint(2, 0, 8));
    pts.push(new Mx3dGePoint(2, 0, 10));
    pts.push(new Mx3dGePoint(0, 0, 10));
    // 窗户边框横截面轮廓多段线
    const polygon = new Mx3dMkPolygon();
    pts.forEach((pt) => polygon.Add(pt));
    polygon.Close();
    // 窗户边框横截面轮廓线
    const wire = polygon.Wire();
    // 窗户边框横截面轮廓线生成窗框横截面
    const makeface = new Mx3dMkFace(wire);
    const face = makeface.Face();
    const vec = new Mx3dGeVec(0, 100, 0);
    // 横截面拉伸出窗框体形状
    const frame = new Mx3dMkPrism(face, vec);
    let frameShape = frame.Shape();
    // 构造两个平面用于分割窗户边框(边框两端的斜45度角)
    const pt = new Mx3dGePoint(0, 0, 0);
    const dir = new Mx3dGeDir(0, -1, 1);
    const plane = new Mx3dGeomPlane(pt, dir);
    // 平面1
    const planeFace = plane.Face(1e-5);
    pt.setXYZ(0, 50, 0);
    dir.SetXYZ(0, 0, 1);
    const axis = new Mx3dGeAxis(pt, dir);;
    // 平面2
    const planeFace2 = planeFace.MirroredByAxis(axis);
    // 分割窗户边框(分割成了两个斜45度的小三角形部分和中间的一个梯形部分)
    const parts = frameShape.spliter([planeFace, planeFace2]);
    // 筛选出中间那个梯形的部分(这里是通过质心的位置来判断的)
    parts.forEach((shape)=>{
        // 这里Centroid的参数添填的MdGe.MxQuantAspect.Quant_Volume这个枚举,是因为shape是实体,它的质心是体质心,所以这里填MdGe.MxQuantAspect.Quant_Volume
        // 如果shape是面,它的质心是面质心,所以要填MdGe.MxQuantAspect.Quant_Area
        // 如果shape是线,它的质心是线质心,所以要填MdGe.MxQuantAspect.Quant_Length
        const centroid = shape.Centroid(MdGe.MxQuantAspect.Quant_Volume);
        if (centroid.Y() > 45 && centroid.Y() < 55) {
            frameShape = shape;
        }
    });
    // 通过旋转得到另外三个边的边框
    const frameShape2 = frameShape.Rotated(new Mx3dGeAxis([0, 50, 50], [1, 0, 0]), Math.PI / 2);
    const frameShape3 = frameShape.Rotated(new Mx3dGeAxis([0, 50, 50], [1, 0, 0]), Math.PI);
    const frameShape4 = frameShape2.Rotated(new Mx3dGeAxis([0, 50, 50], [1, 0, 0]), Math.PI);
    // 合并四个边框,获得边框整体形状
    frameShape = frameShape.fuse(frameShape2).fuse(frameShape3).fuse(frameShape4);
    // 窗框颜色
    const frameColor = new Mx3dGeColor(0.5, 0.5, 0.5, MdGe.MxTypeOfColor.Color_TOC_RGB);
    // 窗框材质
    const frameMaterial = new Mx3dGeMaterial(MdGe.MxNameOfMaterial.Material_NOM_ShinyPlastified);
    // 玻璃
    const glass = new Mx3dMkBox([2, 8, 8], [3, 92, 92]);
    // 玻璃形状
    const glassShape = glass.Shape();
    // 玻璃颜色
    const glassColor = new Mx3dGeColor(0, 0.9, 0.549, MdGe.MxTypeOfColor.Color_TOC_RGB);
    // 玻璃材质,看起来是透明的
    const glassMaterial = new Mx3dGeMaterial(MdGe.MxNameOfMaterial.Material_NOM_Glass);
    // 获取模型文档
    const doc = mxcad3d.getDocument();
    // 新增一个形状标签用于保存边框形状
    const frameLabel = doc.addShapeLabel();
    frameLabel.setShape(frameShape);
    frameLabel.setColor(frameColor)
    frameLabel.setMaterial(frameMaterial);
    // 新增一个形状标签用于保存玻璃形状
    const glassLabel = doc.addShapeLabel();
    glassLabel.setShape(glassShape);
    glassLabel.setColor(glassColor)
    glassLabel.setMaterial(glassMaterial);
    // 更新视图显示
    mxcad3d.update();
}
// 给button添加点击事件,点击后调用drawWindow函数,进行窗户模型的绘制
// 立即执行函数
(function addEventToButton(){
    const btn = document.querySelector("button");
    if (btn) {
        btn.addEventListener("click", () => {
            drawWindow();
        });
    }
})()
  1. 新建终端,运行npx vite命令来运行项目,效果如下图:

1728875910573.jpg


更多关于HarmonyOS鸿蒙Next中JS开发3D建模软件网页三维CAD中绘制一个窗户模型的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

在HarmonyOS鸿蒙Next中,使用JS开发3D建模软件时,可通过ArkUI的Web组件嵌入Three.js等WebGL库来绘制窗户模型。首先创建三维场景,定义窗户的几何形状(如矩形框和玻璃面板),应用材质和纹理,最后将模型添加到场景中进行渲染。

更多关于HarmonyOS鸿蒙Next中JS开发3D建模软件网页三维CAD中绘制一个窗户模型的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


这是一个非常实用的教程,清晰地展示了如何在HarmonyOS Next的Web环境中,利用mxcad3d库进行3D建模。代码结构完整,从环境搭建、初始化到核心建模逻辑都覆盖了,对于想学习在鸿蒙Web项目中集成三维CAD功能的开发者很有帮助。

核心实现分析:

  1. 建模思路清晰:教程通过定义窗户边框的横截面轮廓线,然后拉伸成实体,再通过平面切割和旋转复制,高效地构建了完整的窗框。最后使用长方体创建玻璃,逻辑严谨。
  2. API运用得当:代码熟练使用了Mx3dMkPolygonMx3dMkPrism(拉伸)、spliter(分割)、Rotated(旋转)、fuse(合并)等关键建模API,并正确设置了颜色和材质(如玻璃的透明材质),使模型效果更逼真。
  3. 与HarmonyOS Next的集成:示例本质上是一个标准的Web前端项目(使用Vite)。它可以无缝运行在HarmonyOS Next的WebView或纯Web环境中。mxcad3d库通过WASM运行,性能有保障,符合鸿蒙应用高性能的要求。

潜在优化与扩展方向:

  • 交互性:可以扩展为允许用户通过界面输入参数(如窗户长、宽、边框厚度)来动态生成不同尺寸的窗户。
  • 模型操作:在drawWindow函数基础上,可增加模型选择、移动、旋转等交互功能,使其更接近一个真正的微型CAD工具。
  • 鸿蒙特性集成:虽然当前是通用Web代码,但可以探索将其封装为HarmonyOS的ArkUI组件,或利用鸿蒙的分布式能力,实现跨设备协同查看与编辑此3D模型。

这个示例成功证明了使用JS生态库在HarmonyOS Next上开发复杂3D图形应用的可行性,为开发Web版三维设计工具、产品展示、建筑模型查看等应用提供了很好的技术参考。

回到顶部