mirror of https://gitee.com/antv-l7/antv-l7
chore(layer): 线图层增加拐角效果
This commit is contained in:
parent
39dd92c3c2
commit
12b1b9d225
|
@ -220,18 +220,6 @@ export default class StyleAttributeService implements IStyleAttributeService {
|
||||||
indicesForCurrentFeature.forEach((i) => {
|
indicesForCurrentFeature.forEach((i) => {
|
||||||
indices.push(i + verticesNum);
|
indices.push(i + verticesNum);
|
||||||
});
|
});
|
||||||
verticesForCurrentFeature.forEach((index) => {
|
|
||||||
vertices.push(index);
|
|
||||||
});
|
|
||||||
// fix Maximum call stack size exceeded https://stackoverflow.com/questions/22123769/rangeerror-maximum-call-stack-size-exceeded-why
|
|
||||||
if (normalsForCurrentFeature) {
|
|
||||||
normalsForCurrentFeature.forEach((normal) => {
|
|
||||||
normals.push(normal);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// if (featureIdx % 500 === 0) {
|
|
||||||
// await sleep(100);
|
|
||||||
// }
|
|
||||||
size = vertexSize;
|
size = vertexSize;
|
||||||
const verticesNumForCurrentFeature =
|
const verticesNumForCurrentFeature =
|
||||||
verticesForCurrentFeature.length / vertexSize;
|
verticesForCurrentFeature.length / vertexSize;
|
||||||
|
@ -252,21 +240,20 @@ export default class StyleAttributeService implements IStyleAttributeService {
|
||||||
vertexIdx < verticesNumForCurrentFeature;
|
vertexIdx < verticesNumForCurrentFeature;
|
||||||
vertexIdx++
|
vertexIdx++
|
||||||
) {
|
) {
|
||||||
|
const normal =
|
||||||
|
normalsForCurrentFeature?.slice(vertexIdx * 3, vertexIdx * 3 + 3) ||
|
||||||
|
[];
|
||||||
|
const vertice = verticesForCurrentFeature.slice(
|
||||||
|
vertexIdx * vertexSize,
|
||||||
|
vertexIdx * vertexSize + vertexSize,
|
||||||
|
);
|
||||||
descriptors.forEach((descriptor, attributeIdx) => {
|
descriptors.forEach((descriptor, attributeIdx) => {
|
||||||
if (descriptor && descriptor.update) {
|
if (descriptor && descriptor.update) {
|
||||||
const normal =
|
|
||||||
normalsForCurrentFeature?.slice(
|
|
||||||
vertexIdx * 3,
|
|
||||||
vertexIdx * 3 + 3,
|
|
||||||
) || [];
|
|
||||||
(descriptor.buffer.data as number[]).push(
|
(descriptor.buffer.data as number[]).push(
|
||||||
...descriptor.update(
|
...descriptor.update(
|
||||||
feature,
|
feature,
|
||||||
featureIdx,
|
featureIdx,
|
||||||
verticesForCurrentFeature.slice(
|
vertice,
|
||||||
vertexIdx * vertexSize,
|
|
||||||
vertexIdx * vertexSize + vertexSize,
|
|
||||||
),
|
|
||||||
vertexIdx, // 当前顶点所在feature索引
|
vertexIdx, // 当前顶点所在feature索引
|
||||||
normal,
|
normal,
|
||||||
// TODO: 传入顶点索引 vertexIdx
|
// TODO: 传入顶点索引 vertexIdx
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.8.3/polyfill.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.8.3/polyfill.min.js"></script>
|
||||||
<script src="https://api.mapbox.com/mapbox-gl-js/v1.8.0/mapbox-gl.js"></script>
|
<script src="https://api.mapbox.com/mapbox-gl-js/v1.8.0/mapbox-gl.js"></script>
|
||||||
|
|
||||||
<script src="../dist/l7.js"></script>
|
<script src="../dist/l7-dev.js"></script>
|
||||||
<script>
|
<script>
|
||||||
console.log(L7);
|
console.log(L7);
|
||||||
const scene = new L7.Scene({
|
const scene = new L7.Scene({
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
<!-- <script src="https://cdn.jsdelivr.net/npm/symbol-es6@0.1.2/symbol-es6.min.js"></script> -->
|
<!-- <script src="https://cdn.jsdelivr.net/npm/symbol-es6@0.1.2/symbol-es6.min.js"></script> -->
|
||||||
<script src="https://api.mapbox.com/mapbox-gl-js/v1.8.0/mapbox-gl.js"></script>
|
<script src="https://api.mapbox.com/mapbox-gl-js/v1.8.0/mapbox-gl.js"></script>
|
||||||
|
|
||||||
<script src="../dist/l7.js"></script>
|
<script src="../dist/l7-dev.js"></script>
|
||||||
<script>
|
<script>
|
||||||
console.log(L7);
|
console.log(L7);
|
||||||
const scene = new L7.Scene({
|
const scene = new L7.Scene({
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
<div id="map"></div>
|
<div id="map"></div>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.8.3/polyfill.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.8.3/polyfill.min.js"></script>
|
||||||
<script src="https://api.mapbox.com/mapbox-gl-js/v1.8.0/mapbox-gl.js"></script>
|
<script src="https://api.mapbox.com/mapbox-gl-js/v1.8.0/mapbox-gl.js"></script>
|
||||||
<script src="../dist/l7.js"></script>
|
<script src="../dist/l7-dev.js"></script>
|
||||||
<script>
|
<script>
|
||||||
const data =
|
const data =
|
||||||
{"type":"FeatureCollection","features":[
|
{"type":"FeatureCollection","features":[
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
"d3-scale": "2",
|
"d3-scale": "2",
|
||||||
"earcut": "^2.2.1",
|
"earcut": "^2.2.1",
|
||||||
"eventemitter3": "^4.0.0",
|
"eventemitter3": "^4.0.0",
|
||||||
|
"extrude-polyline": "^1.0.6",
|
||||||
"gl-matrix": "^3.1.0",
|
"gl-matrix": "^3.1.0",
|
||||||
"gl-vec2": "^1.3.0",
|
"gl-vec2": "^1.3.0",
|
||||||
"inversify": "^5.0.1",
|
"inversify": "^5.0.1",
|
||||||
|
|
|
@ -2,8 +2,8 @@ import { IEncodeFeature } from '@antv/l7-core';
|
||||||
import { aProjectFlat, lngLatToMeters } from '@antv/l7-utils';
|
import { aProjectFlat, lngLatToMeters } from '@antv/l7-utils';
|
||||||
import earcut from 'earcut';
|
import earcut from 'earcut';
|
||||||
import { vec3 } from 'gl-matrix';
|
import { vec3 } from 'gl-matrix';
|
||||||
|
import ExtrudePolyline from '../utils/extrude_polyline';
|
||||||
import { calculteCentroid } from '../utils/geo';
|
import { calculteCentroid } from '../utils/geo';
|
||||||
import getNormals from '../utils/polylineNormal';
|
|
||||||
import extrudePolygon, {
|
import extrudePolygon, {
|
||||||
extrude_PolygonNormal,
|
extrude_PolygonNormal,
|
||||||
fillPolygon,
|
fillPolygon,
|
||||||
|
@ -74,11 +74,16 @@ export function LineTriangulation(feature: IEncodeFeature) {
|
||||||
if (Array.isArray(path[0][0])) {
|
if (Array.isArray(path[0][0])) {
|
||||||
path = coordinates[0] as number[][];
|
path = coordinates[0] as number[][];
|
||||||
}
|
}
|
||||||
const line = getNormals(path as number[][], false, 0);
|
const line = new ExtrudePolyline({
|
||||||
|
dash: true,
|
||||||
|
join: 'bevel', //
|
||||||
|
});
|
||||||
|
|
||||||
|
const linebuffer = line.extrude(path as number[][]);
|
||||||
return {
|
return {
|
||||||
vertices: line.attrPos, // [ x,y,z, distance, miter,total ]
|
vertices: linebuffer.positions, // [ x,y,z, distance, miter,total ]
|
||||||
indices: line.attrIndex,
|
indices: linebuffer.indices,
|
||||||
normals: line.normals,
|
normals: linebuffer.normals,
|
||||||
size: 6,
|
size: 6,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ export default class LineModel extends BaseModel {
|
||||||
vertexShader: line_vert,
|
vertexShader: line_vert,
|
||||||
fragmentShader: line_frag,
|
fragmentShader: line_frag,
|
||||||
triangulation: LineTriangulation,
|
triangulation: LineTriangulation,
|
||||||
|
primitive: gl.TRIANGLES,
|
||||||
blend: this.getBlend(),
|
blend: this.getBlend(),
|
||||||
depth: { enable: false },
|
depth: { enable: false },
|
||||||
}),
|
}),
|
||||||
|
@ -146,6 +147,7 @@ export default class LineModel extends BaseModel {
|
||||||
type: gl.FLOAT,
|
type: gl.FLOAT,
|
||||||
},
|
},
|
||||||
size: 3,
|
size: 3,
|
||||||
|
// @ts-ignore
|
||||||
update: (
|
update: (
|
||||||
feature: IEncodeFeature,
|
feature: IEncodeFeature,
|
||||||
featureIdx: number,
|
featureIdx: number,
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { aProjectFlat } from '@antv/l7-utils';
|
||||||
|
|
||||||
|
import ExtrudePolyLine from '../extrude_polyline';
|
||||||
|
|
||||||
|
describe('extrude polyline', () => {
|
||||||
|
const coords = [
|
||||||
|
[57.65624999999999, 55.178867663281984],
|
||||||
|
[74.8828125, 54.77534585936447],
|
||||||
|
[74.8828125, 49.83798245308484],
|
||||||
|
];
|
||||||
|
const extrude = new ExtrudePolyLine({
|
||||||
|
thickness: 1,
|
||||||
|
});
|
||||||
|
it('extrude line', () => {
|
||||||
|
coords.forEach((coord) => {
|
||||||
|
const [lng, lat] = aProjectFlat(coord);
|
||||||
|
coord[0] = lng;
|
||||||
|
coord[1] = lat;
|
||||||
|
});
|
||||||
|
const mesh = extrude.extrude(coords);
|
||||||
|
expect(mesh.indices.length).toBe(12);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,332 @@
|
||||||
|
import { aProjectFlat } from '@antv/l7-utils';
|
||||||
|
import { vec2 } from 'gl-matrix';
|
||||||
|
const tmp = vec2.create();
|
||||||
|
const capEnd = vec2.create();
|
||||||
|
const lineA = vec2.create();
|
||||||
|
const lineB = vec2.create();
|
||||||
|
const tangent = vec2.create();
|
||||||
|
|
||||||
|
export function computeMiter(
|
||||||
|
lineTangent: vec2,
|
||||||
|
miter: vec2,
|
||||||
|
start: vec2,
|
||||||
|
end: vec2,
|
||||||
|
halfThick: number,
|
||||||
|
): [number, vec2] {
|
||||||
|
vec2.add(lineTangent, start, end);
|
||||||
|
vec2.normalize(lineTangent, lineTangent);
|
||||||
|
miter = vec2.fromValues(-lineTangent[1], lineTangent[0]);
|
||||||
|
const tmpvec = vec2.fromValues(-start[1], start[0]);
|
||||||
|
return [halfThick / vec2.dot(miter, tmpvec), miter];
|
||||||
|
}
|
||||||
|
export function computeNormal(out: vec2, dir: vec2) {
|
||||||
|
return vec2.set(out, -dir[1], dir[0]);
|
||||||
|
}
|
||||||
|
export function direction(out: vec2, a: vec2, b: vec2) {
|
||||||
|
vec2.sub(out, a, b);
|
||||||
|
vec2.normalize(out, out);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function isPointEqual(a: vec2, b: vec2) {
|
||||||
|
return a[0] === b[0] && a[1] === b[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IExtrudeLineOption {
|
||||||
|
join: string;
|
||||||
|
cap: string;
|
||||||
|
dash: boolean;
|
||||||
|
closed: boolean;
|
||||||
|
indexOffset: number;
|
||||||
|
miterLimit: number;
|
||||||
|
thickness: number;
|
||||||
|
}
|
||||||
|
export default class ExtrudePolyline {
|
||||||
|
private join: string;
|
||||||
|
private cap: string;
|
||||||
|
private miterLimit: number;
|
||||||
|
private thickness: number;
|
||||||
|
private normal: vec2 | null;
|
||||||
|
private lastFlip: number = -1;
|
||||||
|
private miter: vec2 = vec2.fromValues(0, 0);
|
||||||
|
private started: boolean = false;
|
||||||
|
private dash: boolean = false;
|
||||||
|
private totalDistance: number = 0;
|
||||||
|
|
||||||
|
constructor(opts: Partial<IExtrudeLineOption> = {}) {
|
||||||
|
this.join = opts.join || 'miter';
|
||||||
|
this.cap = opts.cap || 'butt';
|
||||||
|
this.miterLimit = opts.miterLimit || 10;
|
||||||
|
this.thickness = opts.thickness || 1;
|
||||||
|
this.dash = opts.dash || false;
|
||||||
|
}
|
||||||
|
public extrude(points: number[][]) {
|
||||||
|
const complex: {
|
||||||
|
positions: number[];
|
||||||
|
indices: number[];
|
||||||
|
normals: number[];
|
||||||
|
} = {
|
||||||
|
positions: [],
|
||||||
|
indices: [],
|
||||||
|
normals: [],
|
||||||
|
};
|
||||||
|
if (points.length <= 1) {
|
||||||
|
return complex;
|
||||||
|
}
|
||||||
|
this.lastFlip = -1;
|
||||||
|
this.started = false;
|
||||||
|
this.normal = null;
|
||||||
|
this.totalDistance = 0;
|
||||||
|
const total = points.length;
|
||||||
|
for (let i = 1, count = 0; i < total; i++) {
|
||||||
|
const last = points[i - 1] as vec2;
|
||||||
|
const cur = points[i] as vec2;
|
||||||
|
const next = i < points.length - 1 ? points[i + 1] : null;
|
||||||
|
// 如果当前点和前一点相同,跳过
|
||||||
|
if (isPointEqual(last, cur)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const amt = this.segment(complex, count, last, cur, next as vec2);
|
||||||
|
count += amt;
|
||||||
|
}
|
||||||
|
if (this.dash) {
|
||||||
|
for (let i = 0; i < complex.positions.length / 6; i++) {
|
||||||
|
complex.positions[i * 6 + 5] = this.totalDistance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return complex;
|
||||||
|
}
|
||||||
|
private segment(
|
||||||
|
complex: any,
|
||||||
|
index: number,
|
||||||
|
last: vec2,
|
||||||
|
cur: vec2,
|
||||||
|
next: vec2,
|
||||||
|
) {
|
||||||
|
let count = 0;
|
||||||
|
const indices = complex.indices;
|
||||||
|
const positions = complex.positions;
|
||||||
|
const normals = complex.normals;
|
||||||
|
const capSquare = this.cap === 'square';
|
||||||
|
const joinBevel = this.join === 'bevel';
|
||||||
|
const flatCur = aProjectFlat([cur[0], cur[1]]) as [number, number];
|
||||||
|
const flatLast = aProjectFlat([last[0], last[1]]) as [number, number];
|
||||||
|
direction(lineA, flatCur, flatLast);
|
||||||
|
let segmentDistance = 0;
|
||||||
|
if (this.dash) {
|
||||||
|
segmentDistance = this.lineSegmentDistance(flatCur, flatLast);
|
||||||
|
this.totalDistance += segmentDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.normal) {
|
||||||
|
this.normal = vec2.create();
|
||||||
|
computeNormal(this.normal, lineA);
|
||||||
|
}
|
||||||
|
if (!this.started) {
|
||||||
|
this.started = true;
|
||||||
|
|
||||||
|
// if the end cap is type square, we can just push the verts out a bit
|
||||||
|
if (capSquare) {
|
||||||
|
// vec2.scaleAndAdd(capEnd, last, lineA, -this.thickness);
|
||||||
|
const out1 = vec2.create();
|
||||||
|
const out2 = vec2.create();
|
||||||
|
vec2.add(out1, this.normal, lineA);
|
||||||
|
vec2.add(out2, this.normal, lineA);
|
||||||
|
normals.push(out2[0], out2[1], 0);
|
||||||
|
normals.push(out1[0], out1[1], 0);
|
||||||
|
positions.push(
|
||||||
|
last[0],
|
||||||
|
last[1],
|
||||||
|
0,
|
||||||
|
this.totalDistance - segmentDistance,
|
||||||
|
-this.thickness,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
positions.push(
|
||||||
|
last[0],
|
||||||
|
last[1],
|
||||||
|
0,
|
||||||
|
this.totalDistance - segmentDistance,
|
||||||
|
this.thickness,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
|
// this.extrusions(positions, normals, last, out, this.thickness);
|
||||||
|
// last = capEnd;
|
||||||
|
} else {
|
||||||
|
this.extrusions(
|
||||||
|
positions,
|
||||||
|
normals,
|
||||||
|
last,
|
||||||
|
this.normal,
|
||||||
|
this.thickness,
|
||||||
|
this.totalDistance - segmentDistance,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
indices.push(index + 0, index + 1, index + 2);
|
||||||
|
|
||||||
|
if (!next) {
|
||||||
|
computeNormal(this.normal, lineA);
|
||||||
|
if (capSquare) {
|
||||||
|
// vec2.scaleAndAdd(capEnd, cur, lineA, this.thickness);
|
||||||
|
// cur = capEnd;
|
||||||
|
const out1 = vec2.create();
|
||||||
|
const out2 = vec2.create();
|
||||||
|
vec2.sub(out2, lineA, this.normal);
|
||||||
|
vec2.add(out1, lineA, this.normal);
|
||||||
|
// this.extrusions(positions, normals, cur, out, this.thickness);
|
||||||
|
normals.push(out2[0], out2[1], 0);
|
||||||
|
normals.push(out1[0], out1[1], 0);
|
||||||
|
positions.push(
|
||||||
|
cur[0],
|
||||||
|
cur[1],
|
||||||
|
0,
|
||||||
|
this.totalDistance,
|
||||||
|
this.thickness,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
positions.push(
|
||||||
|
cur[0],
|
||||||
|
cur[1],
|
||||||
|
0,
|
||||||
|
this.totalDistance,
|
||||||
|
this.thickness,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.extrusions(
|
||||||
|
positions,
|
||||||
|
normals,
|
||||||
|
cur,
|
||||||
|
this.normal,
|
||||||
|
this.thickness,
|
||||||
|
this.totalDistance,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this.extrusions(positions, normals, cur, this.normal, this.thickness);
|
||||||
|
indices.push(
|
||||||
|
...(this.lastFlip === 1
|
||||||
|
? [index, index + 2, index + 3]
|
||||||
|
: [index + 2, index + 1, index + 3]),
|
||||||
|
);
|
||||||
|
count += 2;
|
||||||
|
} else {
|
||||||
|
const flatNext = aProjectFlat([next[0], next[1]]) as [number, number];
|
||||||
|
if (isPointEqual(flatCur, flatNext)) {
|
||||||
|
vec2.add(
|
||||||
|
flatNext,
|
||||||
|
flatCur,
|
||||||
|
vec2.normalize(flatNext, vec2.subtract(flatNext, flatCur, flatLast)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
direction(lineB, flatNext, flatCur);
|
||||||
|
|
||||||
|
// stores tangent & miter
|
||||||
|
|
||||||
|
const [miterLen, miter] = computeMiter(
|
||||||
|
tangent,
|
||||||
|
vec2.create(),
|
||||||
|
lineA,
|
||||||
|
lineB,
|
||||||
|
this.thickness,
|
||||||
|
);
|
||||||
|
// normal(tmp, lineA)
|
||||||
|
|
||||||
|
// get orientation
|
||||||
|
let flip = vec2.dot(tangent, this.normal) < 0 ? -1 : 1;
|
||||||
|
let bevel = joinBevel;
|
||||||
|
if (!bevel && this.join === 'miter') {
|
||||||
|
const limit = miterLen;
|
||||||
|
if (limit > this.miterLimit) {
|
||||||
|
bevel = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bevel) {
|
||||||
|
normals.push(this.normal[0], this.normal[1], 0);
|
||||||
|
normals.push(miter[0], miter[1], 0);
|
||||||
|
positions.push(
|
||||||
|
cur[0],
|
||||||
|
cur[1],
|
||||||
|
0,
|
||||||
|
this.totalDistance,
|
||||||
|
-this.thickness * flip,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
positions.push(
|
||||||
|
cur[0],
|
||||||
|
cur[1],
|
||||||
|
0,
|
||||||
|
this.totalDistance,
|
||||||
|
this.thickness * flip,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
indices.push(
|
||||||
|
...(this.lastFlip !== -flip
|
||||||
|
? [index, index + 2, index + 3]
|
||||||
|
: [index + 2, index + 1, index + 3]),
|
||||||
|
);
|
||||||
|
|
||||||
|
// now add the bevel triangle
|
||||||
|
indices.push(index + 2, index + 3, index + 4);
|
||||||
|
|
||||||
|
computeNormal(tmp, lineB);
|
||||||
|
vec2.copy(this.normal, tmp); // store normal for next round
|
||||||
|
normals.push(this.normal[0], this.normal[1], 0);
|
||||||
|
positions.push(
|
||||||
|
cur[0],
|
||||||
|
cur[1],
|
||||||
|
0,
|
||||||
|
this.totalDistance,
|
||||||
|
-this.thickness * flip,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
count += 3;
|
||||||
|
} else {
|
||||||
|
this.extrusions(
|
||||||
|
positions,
|
||||||
|
normals,
|
||||||
|
cur,
|
||||||
|
miter,
|
||||||
|
miterLen,
|
||||||
|
this.totalDistance,
|
||||||
|
);
|
||||||
|
indices.push(
|
||||||
|
...(this.lastFlip === 1
|
||||||
|
? [index, index + 2, index + 3]
|
||||||
|
: [index + 2, index + 1, index + 3]),
|
||||||
|
);
|
||||||
|
|
||||||
|
flip = -1;
|
||||||
|
|
||||||
|
// the miter is now the normal for our next join
|
||||||
|
vec2.copy(this.normal, miter);
|
||||||
|
count += 2;
|
||||||
|
}
|
||||||
|
this.lastFlip = flip;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private extrusions(
|
||||||
|
positions: number[],
|
||||||
|
normals: number[],
|
||||||
|
point: vec2, // 顶点
|
||||||
|
normal: vec2, // 法向量
|
||||||
|
thickness: number, // 高度
|
||||||
|
distanceRadio: number,
|
||||||
|
) {
|
||||||
|
normals.push(normal[0], normal[1], 0);
|
||||||
|
normals.push(normal[0], normal[1], 0);
|
||||||
|
positions.push(point[0], point[1], 0, distanceRadio, -thickness, 0);
|
||||||
|
positions.push(point[0], point[1], 0, distanceRadio, thickness, 0);
|
||||||
|
}
|
||||||
|
private lineSegmentDistance(b1: vec2, a1: vec2) {
|
||||||
|
const dx = a1[0] - b1[0];
|
||||||
|
const dy = a1[1] - b1[1];
|
||||||
|
return Math.sqrt(dx * dx + dy * dy);
|
||||||
|
}
|
||||||
|
}
|
|
@ -71,7 +71,7 @@ export default function(
|
||||||
let lineNormal = null;
|
let lineNormal = null;
|
||||||
const tmp = vec2.create();
|
const tmp = vec2.create();
|
||||||
let count = indexOffset || 0;
|
let count = indexOffset || 0;
|
||||||
const miterLimit = 3;
|
const miterLimit = 4;
|
||||||
|
|
||||||
const out: number[] = [];
|
const out: number[] = [];
|
||||||
const attrPos: number[] = [];
|
const attrPos: number[] = [];
|
||||||
|
@ -172,7 +172,6 @@ export default function(
|
||||||
count += 4;
|
count += 4;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bevel) {
|
if (bevel) {
|
||||||
miterLen = miterLimit;
|
miterLen = miterLimit;
|
||||||
|
|
||||||
|
@ -232,7 +231,7 @@ export default function(
|
||||||
return {
|
return {
|
||||||
normals: out,
|
normals: out,
|
||||||
attrIndex,
|
attrIndex,
|
||||||
attrPos: pickData, // [x,y,z, distance, miter ,tatal ]
|
attrPos: pickData, // [x,y,z, distance, miter ,t0tal ]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// [x,y,z, distance, miter ]
|
// [x,y,z, distance, miter ]
|
||||||
|
|
|
@ -199,16 +199,17 @@ export default class Country extends React.Component {
|
||||||
const Layer = new CountryLayer(scene, {
|
const Layer = new CountryLayer(scene, {
|
||||||
visible: true,
|
visible: true,
|
||||||
data: ProvinceData,
|
data: ProvinceData,
|
||||||
geoDataLevel: 2,
|
geoDataLevel: 1,
|
||||||
joinBy: ['NAME_CHN', 'name'],
|
joinBy: ['NAME_CHN', 'name'],
|
||||||
showBorder: false,
|
showBorder: true,
|
||||||
|
provinceStroke: 'red',
|
||||||
label: {
|
label: {
|
||||||
field: 'name',
|
field: 'name',
|
||||||
size: 10,
|
size: 10,
|
||||||
padding: [5, 5],
|
padding: [5, 5],
|
||||||
textAllowOverlap: true,
|
textAllowOverlap: true,
|
||||||
},
|
},
|
||||||
depth: 2,
|
depth: 1,
|
||||||
fill: {
|
fill: {
|
||||||
color: {
|
color: {
|
||||||
field: 'NAME_CHN',
|
field: 'NAME_CHN',
|
||||||
|
@ -230,52 +231,18 @@ export default class Country extends React.Component {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
Layer.on('loaded', () => {
|
Layer.on('loaded', () => {
|
||||||
const filldata = Layer.getFillData();
|
// const filldata = Layer.getFillData();
|
||||||
const border = new LineLayer({
|
// const border = new LineLayer({
|
||||||
zIndex: 5, // 设置显示层级
|
// zIndex: 5, // 设置显示层级
|
||||||
})
|
// })
|
||||||
.source(filldata)
|
// .source(filldata)
|
||||||
.shape('line')
|
// .shape('line')
|
||||||
.size(0.6)
|
// .size(4)
|
||||||
.color('#a00')
|
// .color('#a00')
|
||||||
.style({
|
// .style({
|
||||||
opacity: 1,
|
// opacity: 1,
|
||||||
});
|
// });
|
||||||
const hightLayer = new LineLayer({
|
// scene.addLayer(border);
|
||||||
zIndex: 4, // 设置显示层级
|
|
||||||
name: 'line3',
|
|
||||||
})
|
|
||||||
.source(filldata)
|
|
||||||
.shape('line')
|
|
||||||
.size(1.2)
|
|
||||||
.color('#000')
|
|
||||||
.style({
|
|
||||||
opacity: 1,
|
|
||||||
});
|
|
||||||
const hightLayer2 = new LineLayer({
|
|
||||||
zIndex: 3, // 设置显示层级
|
|
||||||
name: 'line3',
|
|
||||||
})
|
|
||||||
.source(filldata)
|
|
||||||
.shape('line')
|
|
||||||
.size(2.4)
|
|
||||||
.color('#fff')
|
|
||||||
.style({
|
|
||||||
opacity: 1,
|
|
||||||
});
|
|
||||||
scene.addLayer(border);
|
|
||||||
scene.addLayer(hightLayer);
|
|
||||||
scene.addLayer(hightLayer2);
|
|
||||||
Layer.fillLayer.on('click', (feature) => {
|
|
||||||
hightLayer.setData({
|
|
||||||
type: 'FeatureCollection',
|
|
||||||
features: [feature.feature],
|
|
||||||
});
|
|
||||||
hightLayer2.setData({
|
|
||||||
type: 'FeatureCollection',
|
|
||||||
features: [feature.feature],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
|
|
|
@ -14,7 +14,7 @@ export default class Country extends React.Component {
|
||||||
public async componentDidMount() {
|
public async componentDidMount() {
|
||||||
const scene = new Scene({
|
const scene = new Scene({
|
||||||
id: 'map',
|
id: 'map',
|
||||||
map: new Mapbox({
|
map: new GaodeMap({
|
||||||
center: [116.2825, 39.9],
|
center: [116.2825, 39.9],
|
||||||
pitch: 0,
|
pitch: 0,
|
||||||
style: 'blank',
|
style: 'blank',
|
||||||
|
|
|
@ -21,8 +21,8 @@ export default class MultiLine extends React.Component {
|
||||||
map: new GaodeMap({
|
map: new GaodeMap({
|
||||||
pitch: 0,
|
pitch: 0,
|
||||||
style: 'dark',
|
style: 'dark',
|
||||||
center: [101.775374, 3],
|
center: [101.775374, 20],
|
||||||
zoom: 14.1,
|
zoom: 3,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -34,16 +34,18 @@ export default class MultiLine extends React.Component {
|
||||||
type: 'Feature',
|
type: 'Feature',
|
||||||
properties: {},
|
properties: {},
|
||||||
geometry: {
|
geometry: {
|
||||||
type: 'MultiLineString',
|
type: 'LineString',
|
||||||
coordinates: [
|
coordinates: [
|
||||||
[
|
[90.703125, 34.59704151614417],
|
||||||
[100, 0],
|
[112.8515625, 39.095962936305476],
|
||||||
[101, 1],
|
[117.42187500000001, 29.53522956294847],
|
||||||
],
|
[127.61718749999999, 34.016241889667015],
|
||||||
[
|
[129.0234375, 40.713955826286046],
|
||||||
[102, 2],
|
[136.40625, 36.87962060502676],
|
||||||
[103, 3],
|
[136.40625, 28.304380682962783],
|
||||||
],
|
[130.078125, 25.16517336866393],
|
||||||
|
[125.5078125, 20.96143961409684],
|
||||||
|
[130.078125, 17.644022027872726],
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -51,8 +53,11 @@ export default class MultiLine extends React.Component {
|
||||||
})
|
})
|
||||||
.shape('line')
|
.shape('line')
|
||||||
.color('red')
|
.color('red')
|
||||||
|
.size(2)
|
||||||
.style({
|
.style({
|
||||||
opacity: 1.0,
|
opacity: 0.5,
|
||||||
|
lineType: 'dash',
|
||||||
|
dashArray: [2, 2, 4, 2],
|
||||||
});
|
});
|
||||||
scene.addLayer(layer);
|
scene.addLayer(layer);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue