UNPKG

@orca-fe/x-map

Version:
121 lines (113 loc) 4.8 kB
import { RawShaderMaterial, Color, Shape, DoubleSide, Mesh, ShapeGeometry } from 'three'; import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial'; import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry'; import { Line2 } from 'three/examples/jsm/lines/Line2'; import { circle } from '@turf/turf'; import { lonLat2Mercator } from '../../utils/coord'; import ThreeObject from './ThreeObject'; export default class CircleObject extends ThreeObject { constructor(options) { var _a, _b; super(options); this.object3D = new Mesh(); const { fill, border, center, radius = 50, config = {} } = options; this.center = center; this.radius = radius; this.config = config; const color = new Color((_a = fill === null || fill === void 0 ? void 0 : fill.color) !== null && _a !== void 0 ? _a : 0x000000); this.circleMaterial = new RawShaderMaterial({ uniforms: { baseColor: { value: [color.r, color.g, color.b, (_b = fill === null || fill === void 0 ? void 0 : fill.opacity) !== null && _b !== void 0 ? _b : 1] }, }, vertexShader: ` precision mediump float; precision mediump int; uniform mat4 modelViewMatrix; // optional uniform mat4 projectionMatrix; // optional attribute vec3 position; attribute vec4 color; varying vec3 vPosition; void main() { vPosition = position; gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); } `, fragmentShader: ` precision mediump float; precision mediump int; uniform vec4 baseColor; varying vec3 vPosition; void main() { gl_FragColor = baseColor; } `, side: DoubleSide, depthWrite: false, depthTest: false, transparent: true, }); this.object3D.material = this.circleMaterial; if (border) { this.lineMaterial = new LineMaterial(Object.assign({ transparent: true, depthTest: false }, border)); } this.object3D.position.set(0, 0, this.z); } createObject() { var _a; if (!((_a = this.layer) === null || _a === void 0 ? void 0 : _a.map)) return; this.object3D.clear(); const circleGeoJson = circle(this.center, this.radius, Object.assign({ units: 'meters', steps: 64 }, this.config)); const { threeCenter } = this.layer.map; const points = []; const shape = new Shape(); circleGeoJson.geometry.coordinates[0].forEach((point, index) => { const [x, y] = lonLat2Mercator(point).map((value, i) => value - threeCenter[i]); if (index === 0) { shape.moveTo(x, y); } else { shape.lineTo(x, y); } points.push(x, y, 0); }); this.object3D.geometry = new ShapeGeometry(shape); if (this.lineMaterial) { const linGeometry = new LineGeometry(); linGeometry.setPositions(points); const line = new Line2(linGeometry, this.lineMaterial); line.computeLineDistances(); line.scale.set(1, 1, 1); this.object3D.add(line); } } updatePosition() { if (this.layer && this.lineMaterial) { const [width, height] = this.layer.getSize(); this.lineMaterial.resolution.set(width, height); } } updateBorder(border) { var _a, _b; (_a = this.lineMaterial) === null || _a === void 0 ? void 0 : _a.setValues(border); (_b = this.layer) === null || _b === void 0 ? void 0 : _b.updatePosition(); } updateFill(fill) { var _a, _b; const color = new Color(fill.color); this.circleMaterial.uniforms.baseColor.value = [color.r, color.g, color.b, fill.opacity]; (_b = (_a = this.layer) === null || _a === void 0 ? void 0 : _a.updatePositionDebounce) === null || _b === void 0 ? void 0 : _b.call(_a); } updateCenter(center) { var _a, _b; this.center = center; this.createObject(); (_b = (_a = this.layer) === null || _a === void 0 ? void 0 : _a.updatePositionDebounce) === null || _b === void 0 ? void 0 : _b.call(_a); } updateRadius(radius) { var _a, _b; this.radius = radius; this.createObject(); (_b = (_a = this.layer) === null || _a === void 0 ? void 0 : _a.updatePositionDebounce) === null || _b === void 0 ? void 0 : _b.call(_a); } }