@vuemap/vue-amap-extra
Version:
@vuemap/vue-amap扩展库,包含threejs相关图层
326 lines (321 loc) • 12.2 kB
JavaScript
'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