欢迎光临
我们一直在努力

[开源] 纯前端实现楼盘采光模拟工具:从2D规划图到3D日照分析

前言

买房是人生大事,不仅要看户型,更要看采光。尤其是现在高层住宅密集,低楼层的日照时长往往是购房者的心病。虽然市面上有专业的日照分析软件,但对于普通开发者或购房者来说门槛太高。

最近利用周末时间,我开发了一套纯前端、零依赖的楼盘规划与采光模拟工具。它包含两个部分:

  • 配置器 (Editor):基于 Canvas,在普通的楼盘规划图(JPG/PNG)上绘制楼栋轮廓、标定比例尺。
  • 可视化 (Viewer):基于 Three.js,将配置好的数据生成 3D 模型,模拟冬至/夏至不同时间段的日照阴影。
  • 本文将分享这个项目的核心技术实现思路。

    开源地址:[https://github.com/SeanWong17/building-sunlight-simulator] 欢迎 Star ⭐ 和 Fork!

    🚀 功能演示

    1. 2D 规划图配置器

    这是数据生产的入口。用户上传一张总平图,通过“两点标定法”确定比例尺(例如:图上两点代表实际50米),然后就可以在图上通过点击绘制楼栋的多边形轮廓。

    在这里插入图片描述

    • 支持交互:滚轮缩放、右键平移、双击闭合多边形。
    • 参数配置:可设置楼栋名称、层数、层高、每层户数等。
    • 自动清洗:内置算法自动处理多边形绘制中的共线点、过近点。

    2. 3D 采光可视化

    将配置导出的 JSON 文件拖入查看器,即可生成 3D 场景。 在这里插入图片描述

    • 日照模拟:支持冬至、夏至、春秋分切换,支持 06:00 – 18:00 连续时间拖动。
    • 真实坐标:基于纬度计算太阳高度角和方位角。
    • 可视化细节:根据户数自动生成简单的窗户纹理,支持只查看“本小区”模式。

    🛠️ 核心技术实现

    本项目完全由原生 HTML/CSS/JS 实现,3D 部分引入了 Three.js。

    一、 2D 编辑器:Canvas 交互与坐标变换

    编辑器最核心的难点在于视图的缩放/平移与Canvas 坐标系之间的转换。

    我们需要维护 viewScale (缩放倍率), viewX, viewY (偏移量)。在鼠标点击 Canvas 获取坐标时,必须将其逆变换回“图片原始坐标系”,这样导出的数据才与缩放无关。

    // 核心坐标转换函数
    function getCanvasCoordinates(e) {
    const rect = wrapper.getBoundingClientRect();
    const mouseXInWrapper = e.clientX rect.left;
    const mouseYInWrapper = e.clientY rect.top;

    // 逆向计算:(屏幕坐标 – 偏移) / 缩放倍率 = 原始画布坐标
    const canvasX = (mouseXInWrapper viewX) / viewScale;
    const canvasY = (mouseYInWrapper viewY) / viewScale;
    return { x: canvasX, y: canvasY };
    }

    此外,为了防止手抖导致绘制的多边形产生“毛刺”或重叠点,我在闭合多边形时增加了一个净化算法 (Sanitize):

    // 多边形净化:去重、去共线、去极短边
    function sanitizePolygon(rawPoints, epsPx = 0.5) {
    // 1. 去掉首尾重复点
    // 2. 去掉相邻的极近点 (distance < threshold)
    // 3. 核心:去掉近似共线的中间点 (通过叉积计算)
    const result = [];
    const n = clean.length;
    for (let i = 0; i < n; i++) {
    const p0 = clean[mod(i 1, n)];
    const p1 = clean[i];
    const p2 = clean[mod(i + 1, n)];
    // 计算向量叉积,判断三点是否共线
    const cross = Math.abs(v1x * v2y v1y * v2x);
    if (cross > eps * (len1 + len2)) result.push(p1);
    }
    return result;
    }

    二、 3D 可视化:Three.js 与 太阳轨迹计算

    1. 从 2D 轮廓生成 3D 楼栋

    利用 Three.js 的 ExtrudeGeometry (挤压几何体),我们可以直接将 2D 的 Shape 拉伸成 3D 模型。

    这里有一个细节:为了让模型看起来不像“素模”,我根据 JSON 中的 units (每层户数) 动态生成了 Canvas 纹理贴图,模拟窗户的效果。

    // 动态生成外立面纹理
    function createFacadeTexture(floors, unitsPerFloor) {
    const canvas = document.createElement('canvas');
    // … 绘制背景色 …

    // 根据层数和户数绘制窗户矩形
    for (let f = 0; f < floors; f++) {
    // 简单的 Canvas 2D 绘图操作
    ctx.fillStyle = 'rgba(255,255,255,0.22)';
    ctx.fillRect(x, y, w, h);
    }

    return new THREE.CanvasTexture(canvas);
    }

    // 生成几何体
    const shape = new THREE.Shape();
    // … 解析 JSON 点集 …
    const geometry = new THREE.ExtrudeGeometry(shape, {
    depth: totalHeight, // 挤压深度即楼高
    bevelEnabled: false // 关闭倒角
    });

    2. 模拟真实日照 (核心算法)

    阴影的产生依赖于平行光 (DirectionalLight) 的位置。我们需要根据用户选择的季节和时间,结合地理纬度,算出太阳在天空中的准确位置(高度角和方位角)。

    公式实现如下:

    function updateSun() {
    const hour = getCurrentHour();
    const decl = parseFloat(seasonSelect.value); // 赤纬角:冬至-23.44,夏至23.44

    // 1. 计算时角 (Hour Angle)
    const hAngle = (hour 12) * 15 * rad;

    // 2. 计算高度角 (Altitude)
    // sin(h) = sin(φ)sin(δ) + cos(φ)cos(δ)cos(t)
    const sinAlt = Math.sin(lat) * Math.sin(dec) + Math.cos(lat) * Math.cos(dec) * Math.cos(hAngle);
    const alt = Math.asin(sinAlt);

    // 3. 计算方位角 (Azimuth)
    // cos(A) = (sin(h)sin(φ) – sin(δ)) / (cos(h)cos(φ))
    const cosAz = (sinAlt * Math.sin(lat) Math.sin(dec)) / (Math.cos(alt) * Math.cos(lat));
    let az = Math.acos(Math.min(1, Math.max(1, cosAz)));
    if (hour >= 12) az = az;

    // 4. 转换为 Three.js 坐标系 (x, y, z)
    // 注意:Three.js 中 Y 轴向上
    const y = dist * Math.sin(alt);
    const r = dist * Math.cos(alt);
    const x = r * Math.sin(az);
    const z = r * Math.cos(az);

    sunLight.position.set(x, y, z);

    // 如果太阳在地平线以下,关闭光源强度
    sunLight.intensity = alt > 0 ? 1.2 : 0.0;
    }

    📂 项目结构与使用

    整个项目非常轻量,没有复杂的构建流程(Webpack/Vite),只有 HTML 文件,下载即用。

    building-sunlight-simulator/
    ├── editor.html # 2D 规划图配置器
    ├── viewer.html # 3D 采光可视化
    ├── README.md
    └── examples/ # 示例文件

    使用步骤:

  • 打开 editor.html,导入你的楼盘规划图。
  • 标定比例尺,绘制楼栋,导出 JSON。
  • 打开 viewer.html,导入刚才的 JSON,开始日照分析。
  • 🔮 总结与展望

    这个项目展示了前端技术在可视化工具领域的潜力。不依赖后端,仅仅使用 Canvas 和 WebGL 就能解决实际生活中的“痛点”。

    未来可以优化的方向:

    • 增加户型图叠加功能。
    • 引入更精确的地理高程数据。
    • 支持 VR 模式看房。

    完整的代码我已经上传到 GitHub,如果你对 Canvas 交互或 Three.js 开发感兴趣,欢迎下载体验!

    [Github 传送门:点击此处跳转]

    赞(0)
    未经允许不得转载:171主机测评 » [开源] 纯前端实现楼盘采光模拟工具:从2D规划图到3D日照分析
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址