UNPKG

@vuemap/vue-amap-extra

Version:

@vuemap/vue-amap扩展库,包含threejs相关图层

326 lines (321 loc) 12.2 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var three = require('three'); var lodashEs = require('lodash-es'); var HDRCubeTextureLoader_js = require('three/examples/jsm/loaders/HDRCubeTextureLoader.js'); var EffectComposer_js = require('three/examples/jsm/postprocessing/EffectComposer.js'); var threeLayer = require('@vuemap/three-layer'); var CSS2DRenderer = require('./CSS2DRenderer.js'); var CSS3DRenderer = require('./CSS3DRenderer.js'); var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => { __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); return value; }; class CustomThreeLayer extends threeLayer.ThreeLayer { constructor(map, options, callback) { options.onInit = (render, scene) => { var _a; this.raycaster = new three.Raycaster(); if (options.axesHelper) { const axesHelper = new three.AxesHelper(1e4); scene.add(axesHelper); } (_a = this.renderer) == null ? void 0 : _a.setPixelRatio(window.devicePixelRatio); if (options.createCssRender) this.creatCssRenders(map); this.createEffect(); this.createLights(options.lights || []); this.createHDR(options.hdr); this.bindEvents(); if (callback) { callback(); } }; options.onRender = (render, scene, camera) => { var _a, _b, _c, _d; if (this.passNum > 0) { (_a = this.effectComposer) == null ? void 0 : _a.render(this.clock.getDelta()); } else { (_b = this.renderer) == null ? void 0 : _b.render(this.scene, camera); (_c = this.css2DRenderer) == null ? void 0 : _c.render(this.scene, camera); (_d = this.css3DRenderer) == null ? void 0 : _d.render(this.scene, camera); } }; super(map, options); __publicField(this, "lightTypes", { AmbientLight: three.AmbientLight, // 环境光 环境光会均匀的照亮场景中的所有物体 DirectionalLight: three.DirectionalLight, // 平行光 平行光是沿着特定方向发射的光 HemisphereLight: three.HemisphereLight, // 半球光 光源直接放置于场景之上,光照颜色从天空光线颜色渐变到地面光线颜色。 PointLight: three.PointLight, // 点光源 从一个点向各个方向发射的光源。一个常见的例子是模拟一个灯泡发出的光 RectAreaLight: three.RectAreaLight, // 平面光光源 平面光光源从一个矩形平面上均匀地发射光线。这种光源可以用来模拟像明亮的窗户或者条状灯光光源 SpotLight: three.SpotLight // 聚光灯 光线从一个点沿一个方向射出,随着光线照射的变远,光线圆锥体的尺寸也逐渐增大 }); __publicField(this, "raycaster"); // 射线,用于判断点击或者鼠标移动是否碰到物体 __publicField(this, "mouse"); __publicField(this, "envMap"); // HDR的环境贴图 __publicField(this, "clickFun"); __publicField(this, "hoverFun"); __publicField(this, "resizeFun"); __publicField(this, "effectComposer"); __publicField(this, "renderPass"); __publicField(this, "passNum", 0); __publicField(this, "passList", []); __publicField(this, "clock", new three.Clock()); __publicField(this, "preHoverGroup", null); __publicField(this, "css2DRenderer", null); __publicField(this, "css3DRenderer", null); this.mouse = new three.Vector2(); } updateRendererSize() { var _a, _b, _c; const container = this.map.getContainer(); const width = container.offsetWidth; const height = container.offsetHeight; (_a = this.renderer) == null ? void 0 : _a.setSize(width, height); (_b = this.css2DRenderer) == null ? void 0 : _b.setSize(width, height); (_c = this.css3DRenderer) == null ? void 0 : _c.setSize(width, height); if (this.map.getView().type === "3D") { this.camera.aspect = width / height; } } updateEffectComposerSize() { var _a, _b; if (this.effectComposer && this.renderer) { const size = this.renderer.getSize(new three.Vector2()); this.effectComposer.setSize(size.x, size.y); (_a = this.css2DRenderer) == null ? void 0 : _a.setSize(size.x, size.y); (_b = this.css3DRenderer) == null ? void 0 : _b.setSize(size.x, size.y); } } createEffect() { var _a, _b, _c; const size = (_a = this.renderer) == null ? void 0 : _a.getSize(new three.Vector2()); this.effectComposer = new EffectComposer_js.EffectComposer(this.renderer); this.effectComposer.setSize(size == null ? void 0 : size.x, size == null ? void 0 : size.y); (_b = this.css2DRenderer) == null ? void 0 : _b.setSize(size == null ? void 0 : size.x, size == null ? void 0 : size.y); (_c = this.css3DRenderer) == null ? void 0 : _c.setSize(size == null ? void 0 : size.x, size == null ? void 0 : size.y); } creatCssRenders(map) { this.css2DRenderer = new CSS2DRenderer.CSS2DRenderer(); this.css2DRenderer.domElement.style.position = "absolute"; this.css2DRenderer.domElement.style.left = "0"; this.css2DRenderer.domElement.style.top = "0"; this.css3DRenderer = new CSS3DRenderer.CSS3DRenderer(); this.css3DRenderer.domElement.style.position = "absolute"; this.css3DRenderer.domElement.style.left = "0"; this.css3DRenderer.domElement.style.top = "0"; const element = map.getContainer().querySelector(".amap-markers"); element.appendChild(this.css2DRenderer.domElement); element.appendChild(this.css3DRenderer.domElement); } addPass(pass) { var _a; (_a = this.effectComposer) == null ? void 0 : _a.addPass(pass); this.passNum++; this.passList.push(pass); } removePass(pass) { var _a; const index = this.passList.indexOf(pass); if (index !== -1) { this.passList.splice(index, 1); } (_a = this.effectComposer) == null ? void 0 : _a.removePass(pass); this.passNum--; } createLights(lights) { const defaultLightOptions = { type: "DirectionalLight", // 灯光类型, 可选值见下面的字典 args: [] // 灯光初始化时需要的参数,具体参数顺序可以查看threejs官网灯光的说明。 采用 ...args 的方式进行初始化 }; if (lights && lights.length > 0) { lights.forEach((lightOptions) => { lightOptions = lodashEs.merge( {}, defaultLightOptions, lightOptions ); if (this.lightTypes[lightOptions.type]) { const light = new this.lightTypes[lightOptions.type]( ...lightOptions.args ); const position = lightOptions.position; const lookAt = lightOptions.lookAt; if (position) { light.position.set(position.x, position.y, position.z); } if (lookAt) { light.lookAt(lookAt.x, lookAt.y, lookAt.z); } this.add(light); } else { console.warn("\u5F53\u524D\u8BBE\u7F6E\u7684\u706F\u5149\u7C7B\u578B\u4E0D\u5B58\u5728"); } }); } } createHDR(hdr) { if (!hdr) { return; } const options = lodashEs.merge( {}, { urls: [], // HDR贴图下载地址,需要6个文件,代表6个方向 path: "/", // HDR下载地址的路径前缀 // roughness: 0.0, exposure: 1 // 光亮程度 }, hdr ); const render = this.renderer; render.physicallyCorrectLights = true; render.outputEncoding = three.sRGBEncoding; render.toneMappingExposure = options.exposure; const hdrUrls = options.urls; let pmremGenerator = new three.PMREMGenerator(render); pmremGenerator.compileCubemapShader(); const hdrCubeMap = new HDRCubeTextureLoader_js.HDRCubeTextureLoader().setPath(options.path).load(hdrUrls, () => { const hdrCubeRenderTarget = pmremGenerator.fromCubemap(hdrCubeMap); hdrCubeMap.magFilter = three.LinearFilter; hdrCubeMap.needsUpdate = true; this.envMap = hdrCubeRenderTarget ? hdrCubeRenderTarget.texture : null; this.addEnvMap(this.scene); pmremGenerator.dispose(); pmremGenerator = null; this.refreshMap(); }); } addEnvMap(object) { this.scene.environment = this.envMap; } bindEvents() { this.clickFun = lodashEs.bind(this._clickEvent, this); this.hoverFun = lodashEs.bind(this._hoverEvent, this); this.resizeFun = lodashEs.bind(this.updateEffectComposerSize, this); if (this.canvas) { this.canvas.addEventListener("click", this.clickFun, false); this.canvas.addEventListener("mousemove", this.hoverFun, false); } else { this.map.on("click", this.clickFun); this.map.on("mousemove", this.hoverFun); } this.map.on("resize", this.resizeFun); } ubBindEvents() { this.map.off("click", this.clickFun); this.map.off("mousemove", this.hoverFun); this.map.on("off", this.resizeFun); } _getOriginEvent(e) { if (e.originEvent) { return e.originEvent; } return e; } _clickEvent(e) { e = this._getOriginEvent(e); const group = this._intersectGltf(e); if (group) { if (group.userData.$vue) { group.userData.$vue.$emit("click", group); } this.emit("click", group); } } _hoverEvent(e) { e = this._getOriginEvent(e); const group = this._intersectGltf(e); if (group) { if (!group.userData.isHover) { group.userData.isHover = true; if (group.userData.$vue) { group.userData.$vue.$emit("mouseover", group); } else { this.emit("mouseover", group); } } } if (this.preHoverGroup) { if (!group || this.preHoverGroup.uuid !== group.uuid) { if (this.preHoverGroup.userData.$vue) { this.preHoverGroup.userData.$vue.$emit( "mouseout", this.preHoverGroup ); } else { this.emit("mouseout", this.preHoverGroup); } this.preHoverGroup.userData.isHover = false; } } this.preHoverGroup = group; } _intersectGltf(e) { var _a, _b; const client = this.map.getContainer(); const getBoundingClientRect = client.getBoundingClientRect(); const offsetTop = getBoundingClientRect.top + window.pageYOffset - client.clientTop; const offsetLeft = getBoundingClientRect.left + window.pageXOffset - client.clientLeft; this.mouse.x = (e.x + window.pageXOffset - offsetLeft) / getBoundingClientRect.width * 2 - 1; this.mouse.y = -((e.y + window.pageYOffset - offsetTop) / getBoundingClientRect.height) * 2 + 1; const camera = this.camera; (_a = this.raycaster) == null ? void 0 : _a.setFromCamera(this.mouse, camera); const intersects = (_b = this.raycaster) == null ? void 0 : _b.intersectObjects( [this.scene], true ); const length = intersects == null ? void 0 : intersects.length; if (length && length > 0) { let group = null; for (let i = 0; i < length; i++) { const object = intersects[i]; group = this._getGroup(object.object); if (group !== null) { break; } } return group; } return null; } _getGroup(object) { if (!object) { return null; } if (object.userData.acceptEvent) { return object; } return this._getGroup(object.parent); } destroy() { var _a, _b, _c, _d; this.ubBindEvents(); if (this.envMap) { this.envMap.dispose(); this.envMap = null; } (_b = (_a = this.css2DRenderer) == null ? void 0 : _a.domElement) == null ? void 0 : _b.remove(); (_d = (_c = this.css3DRenderer) == null ? void 0 : _c.domElement) == null ? void 0 : _d.remove(); super.destroy(); this.lightTypes = null; this.raycaster = void 0; } } exports.default = CustomThreeLayer; //# sourceMappingURL=CustomThreeLayer.js.map