UNPKG

@ciniki/iclient-maplibregl

Version:

@supermapgis/iclient-maplibregl 是一套基于 Maplibre GL 的云 GIS 网络客户端开发平台, 支持访问 SuperMap iServer / iEdge / iPortal / iManager / Online 的地图、服务和资源,为用户提供了完整专业的 GIS 能力, 同时提供了优秀的可视化功能。

315 lines (285 loc) 9.79 kB
/* Copyright© 2000 - 2025 SuperMap Software Co.Ltd. All rights reserved. * This program are made available under the terms of the Apache License, Version 2.0 * which accompanies this distribution and is available at http://www.apache.org/licenses/LICENSE-2.0.html.*/ /** * reference and modification * maptalks.three * (https://github.com/maptalks/maptalks.three) * Apache Licene 2.0 * thanks maptalks */ import maplibregl from "maplibre-gl"; import { ThreeLayerRenderer } from "@ciniki/iclient-common/overlay/threejs/ThreeLayerRenderer"; /** * @class ThreeLayer * @category Visualization Three * @classdesc Three 图层类。Three.js 是一款开源的主流 3D 绘图 JS 引擎。 此类主要提供了 threejs 模型绘制、渲染3D场景的功能。 * @version 11.1.0 * @modulecategory Overlay * @param {string} id - 图层 ID。 * @param {string} [renderer="gl"] - 图层渲染器,仅支持"gl"。'canvas'在 v11.1.0 后被弃用。 * @param {Object} options - 初始化参数。 * @param {Object} options.threeOptions - threejs 渲染器初始化参数对象。参数内容详见: * {@link THREE.WebGLRenderer}。 * * @extends {maplibregl.Evented} * @fires ThreeLayer#render * @fires ThreeLayer#renderscene * @example * var threeLayer = new ThreeLayer('three'); * //模型绘制 * threeLayer.on("initialized", draw); * threeLayer.addTo(map); * * function draw() { * var scene=threeLayer.getScene(); * camera=threeLayer.getCamera(); * var light = new THREE.PointLight(0xffffff); * camera.add(light); * var material = new THREE.MeshPhongMaterial({color: 0xff0000}); * //根据坐标点转换成模型 * var mesh = this.toThreeMesh(feature.geometry.coordinates, 10, material, true); * //模型添加到3D场景 * scene.add(mesh); * } * * 叠加模型可以通过两种方式:</br> * 1.调用 threeLayer.toThreeMesh 直接将地理坐标转换成 threejs 3D 模型(适用于挤压模型,如城市建筑),然后添加到 3D 场景 * 2.使用 ThreeJS 的接口创建好 Mesh,然后调用 threeLayer.setPosition 设置地理位置,然后添加到 3D 场景 * * @usage */ export class ThreeLayer extends maplibregl.Evented { //options.threeOptions是初始化threejs renderer的参数对象 constructor(id, renderer, options) { super(); this.id = id; this.options = options; this.type = 'custom'; this.renderingMode = '3d'; this.overlay = true; let threeOptions = options && options.threeOptions; this.renderer = new ThreeLayerRenderer(this, renderer, threeOptions); } /** * @function ThreeLayer.prototype.toThreeShape * @description 创建 threejs shape 对象。 * @param {Array} coordinates - 坐标点数组。 * @returns {THREE.Shape} threejs shape 对象。 */ toThreeShape(coordinates) { return this.renderer.toThreeShape(coordinates); } /** * @function ThreeLayer.prototype.toThreeMesh * @description 创建 threejs Mesh 对象。将地理坐标转换成 threejs 3D 模型(适用于挤压模型,如城市建筑)。 * @param {Array.<Object>} coordinates - 坐标点数组。 * @param {number} amount - 高度。 * @param {THREE.Material} material - Threejs 材质对象。 * @param {boolean} [removeDuplicated] - 是否移除重复的坐标点。 * @returns {THREE.Mesh} threejs Mesh 对象。 */ toThreeMesh(coordinates, amount, material, removeDuplicated) { return this.renderer.toThreeMesh(coordinates, amount, material, removeDuplicated); } /** * @function ThreeLayer.prototype.addObject * @description 设置threejs 3D 对象的坐标(经纬度)。 * @param {THREE.Object3D} object3D - threejs 3D 对象及子类对象。 * @param {(Array.<number>|Object)} coordinate - 添加的 three 对象坐标(经纬度)。 * @returns {ThreeLayer} ThreeLayer的实例对象。 */ addObject(object3D, coordinate) { this.renderer && this.renderer.addObject(object3D, coordinate); } /** * @function ThreeLayer.prototype.getScene * @description 获取 threejs 场景对象。 * @returns {THREE.Scene} threejs 场景对象。 */ getScene() { return this.renderer.scene; } /** * @function ThreeLayer.prototype.getCamera * @description 获取 threejs 相机。 * @returns {THREE.Camera} threejs 相机。 */ getCamera() { return this.renderer.camera; } /** * @function ThreeLayer.prototype.getThreeRenderer * @description 获取 threejs renderer。 * @returns {THREE.WebGLRenderer} threejs renderer。 */ getThreeRenderer() { return this.renderer.context; } /** * @function ThreeLayer.prototype.clearMesh * @description 清除所有 threejs mesh 对象。 * @returns {ThreeLayer} ThreeLayer的实例对象。 */ clearMesh() { this.renderer.clearMesh(); return this; } /** * @function ThreeLayer.prototype.clearAll * @description 清除所有 threejs 对象。 * @param {boolean} clearCamera - 是否清除相机。 * @returns {ThreeLayer} ThreeLayer的实例对象。 */ clearAll(clearCamera) { this.renderer.clearAll(clearCamera); return this; } /** * @function ThreeLayer.prototype.setPosition * @description 设置 threejs 3D 对象的坐标(经纬度)。 * @param {THREE.Object3D} object3D - threejs 3D 对象及子类对象。 * @param {(Array.<number>|Object)} coordinate - 添加的 three 对象坐标(经纬度)。 * @returns {ThreeLayer} ThreeLayer的实例对象。 */ setPosition(object3D, coordinate) { return this.renderer.setPosition(object3D, coordinate); } /** * @function ThreeLayer.prototype.lngLatToPosition * @description 经纬度转threejs 3D 矢量对象。 * @param {(Array.<number>|Object)} lngLat - 经纬度坐标。 * @returns {THREE.Vector3} threejs 3D 矢量对象。 */ lngLatToPosition(lngLat) { return this.renderer.lngLatToPosition(lngLat); } /** * @function ThreeLayer.prototype.distanceToThreeVector3 * @description 计算距离指定坐标给定距离的新坐标的 threejs 3D 矢量对象。 * @param {number} x - x 轴距离,单位米。 * @param {number} y - y 轴距离,单位米。 * @param {(Array.<number>|Object)} lngLat - 源坐标。 * @returns {THREE.Vector3} 目标点的 threejs 3D 矢量对象。 */ distanceToThreeVector3(x, y, lngLat) { let map = this._map; let center = lngLat || map.getCenter(); return this.renderer.distanceToThreeVector3(x, y, center); } /** * @function ThreeLayer.prototype.removeDuplicatedCoordinates * @description 移除数组中的重复坐标。 * @param {(Array.<Array.<number>>)} coordinates - 坐标数组。 * @returns {(Array.<Array.<number>>)} 新的坐标数组。 */ removeDuplicatedCoordinates(coordinates) { return this.renderer.removeDuplicatedCoordinates(coordinates); } /** * @function ThreeLayer.prototype.getCoordinatesCenter * @description 获取给定坐标数组的中心坐标。 * @param {(Array.<Array.<number>>)} coordinates - 坐标数组。 * @returns {Object} 包含经纬度的坐标对象。 */ getCoordinatesCenter(coordinates) { return this.renderer.getCoordinatesCenter(coordinates); } /** * @function ThreeLayer.prototype.onAdd * @description 添加图层到地图。 * @param {Object} map - 地图对象。 */ onAdd(map) { var me = this; me._map = map; me.renderer.setMap(map); me.renderer.render(); me.on('render', (function () { this.context && this.context.render(this.scene, this.camera); }).bind(me.renderer)); return this; } /** * @function ThreeLayer.prototype.addTo * @deprecated * @description 添加图层到地图。 * @param {Object} map - 地图对象。 * @returns {ThreeLayer} ThreeLayer的实例对象。 */ addTo(map) { map.addLayer(this); return this; } /** * @function ThreeLayer.prototype.render */ render() { this._update(); } /** * @function ThreeLayer.prototype.getCanvasContainer * @description 获取 three 图层容器。 * @returns {HTMLElement} three 图层的容器。 */ getCanvasContainer() { return this.renderer.getCanvasContainer(); } /** * @function ThreeLayer.prototype.getCanvas * @description 获取 three 图层画布。 * @returns {HTMLCanvasElement} three 图层画布。 */ getCanvas() { return this.renderer.getCanvas(); } /** * @function ThreeLayer.prototype.remove * @description 移除图层。 */ remove() { this.renderer.remove(); this._map = null; } /** * @function ThreeLayer.prototype.draw * @description 提供给外部的 threejs 模型绘制接口。 * @returns {ThreeLayer} ThreeLayer的实例对象。 * @example * var threeLayer = new ThreeLayer('three'); * //可以通过重写 draw 实现模型绘制 * threeLayer.draw = function (gl, scene, camera) { * //TODO 绘制操作 * } * threeLayer.addTo(map); */ draw() { return this; } /** * @function ThreeLayer.prototype.renderScene * @description 渲染场景。 * @returns {ThreeLayer} ThreeLayer的实例对象。 */ renderScene() { this.renderer.renderScene(); /** * @event ThreeLayer#renderscene * @description renderScene 事件,场景渲染后触发。 */ this.fire("renderscene"); return this; } _resize() { this.renderer.resize(); } _update() { /** * @event ThreeLayer#render * @description render 事件,地图渲染时(地图状态改变时)触发。 */ this.renderScene(); this.fire('render'); return this; } }