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) => {
|
||||
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;
|
||||
const verticesNumForCurrentFeature =
|
||||
verticesForCurrentFeature.length / vertexSize;
|
||||
|
@ -252,21 +240,20 @@ export default class StyleAttributeService implements IStyleAttributeService {
|
|||
vertexIdx < verticesNumForCurrentFeature;
|
||||
vertexIdx++
|
||||
) {
|
||||
const normal =
|
||||
normalsForCurrentFeature?.slice(vertexIdx * 3, vertexIdx * 3 + 3) ||
|
||||
[];
|
||||
const vertice = verticesForCurrentFeature.slice(
|
||||
vertexIdx * vertexSize,
|
||||
vertexIdx * vertexSize + vertexSize,
|
||||
);
|
||||
descriptors.forEach((descriptor, attributeIdx) => {
|
||||
if (descriptor && descriptor.update) {
|
||||
const normal =
|
||||
normalsForCurrentFeature?.slice(
|
||||
vertexIdx * 3,
|
||||
vertexIdx * 3 + 3,
|
||||
) || [];
|
||||
(descriptor.buffer.data as number[]).push(
|
||||
...descriptor.update(
|
||||
feature,
|
||||
featureIdx,
|
||||
verticesForCurrentFeature.slice(
|
||||
vertexIdx * vertexSize,
|
||||
vertexIdx * vertexSize + vertexSize,
|
||||
),
|
||||
vertice,
|
||||
vertexIdx, // 当前顶点所在feature索引
|
||||
normal,
|
||||
// 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://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>
|
||||
console.log(L7);
|
||||
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://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>
|
||||
console.log(L7);
|
||||
const scene = new L7.Scene({
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<div id="map"></div>
|
||||
<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="../dist/l7.js"></script>
|
||||
<script src="../dist/l7-dev.js"></script>
|
||||
<script>
|
||||
const data =
|
||||
{"type":"FeatureCollection","features":[
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
"d3-scale": "2",
|
||||
"earcut": "^2.2.1",
|
||||
"eventemitter3": "^4.0.0",
|
||||
"extrude-polyline": "^1.0.6",
|
||||
"gl-matrix": "^3.1.0",
|
||||
"gl-vec2": "^1.3.0",
|
||||
"inversify": "^5.0.1",
|
||||
|
|
|
@ -2,8 +2,8 @@ import { IEncodeFeature } from '@antv/l7-core';
|
|||
import { aProjectFlat, lngLatToMeters } from '@antv/l7-utils';
|
||||
import earcut from 'earcut';
|
||||
import { vec3 } from 'gl-matrix';
|
||||
import ExtrudePolyline from '../utils/extrude_polyline';
|
||||
import { calculteCentroid } from '../utils/geo';
|
||||
import getNormals from '../utils/polylineNormal';
|
||||
import extrudePolygon, {
|
||||
extrude_PolygonNormal,
|
||||
fillPolygon,
|
||||
|
@ -74,11 +74,16 @@ export function LineTriangulation(feature: IEncodeFeature) {
|
|||
if (Array.isArray(path[0][0])) {
|
||||
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 {
|
||||
vertices: line.attrPos, // [ x,y,z, distance, miter,total ]
|
||||
indices: line.attrIndex,
|
||||
normals: line.normals,
|
||||
vertices: linebuffer.positions, // [ x,y,z, distance, miter,total ]
|
||||
indices: linebuffer.indices,
|
||||
normals: linebuffer.normals,
|
||||
size: 6,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ export default class LineModel extends BaseModel {
|
|||
vertexShader: line_vert,
|
||||
fragmentShader: line_frag,
|
||||
triangulation: LineTriangulation,
|
||||
primitive: gl.TRIANGLES,
|
||||
blend: this.getBlend(),
|
||||
depth: { enable: false },
|
||||
}),
|
||||
|
@ -146,6 +147,7 @@ export default class LineModel extends BaseModel {
|
|||
type: gl.FLOAT,
|
||||
},
|
||||
size: 3,
|
||||
// @ts-ignore
|
||||
update: (
|
||||
feature: IEncodeFeature,
|
||||
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;
|
||||
const tmp = vec2.create();
|
||||
let count = indexOffset || 0;
|
||||
const miterLimit = 3;
|
||||
const miterLimit = 4;
|
||||
|
||||
const out: number[] = [];
|
||||
const attrPos: number[] = [];
|
||||
|
@ -172,7 +172,6 @@ export default function(
|
|||
count += 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bevel) {
|
||||
miterLen = miterLimit;
|
||||
|
||||
|
@ -232,7 +231,7 @@ export default function(
|
|||
return {
|
||||
normals: out,
|
||||
attrIndex,
|
||||
attrPos: pickData, // [x,y,z, distance, miter ,tatal ]
|
||||
attrPos: pickData, // [x,y,z, distance, miter ,t0tal ]
|
||||
};
|
||||
}
|
||||
// [x,y,z, distance, miter ]
|
||||
|
|
|
@ -199,16 +199,17 @@ export default class Country extends React.Component {
|
|||
const Layer = new CountryLayer(scene, {
|
||||
visible: true,
|
||||
data: ProvinceData,
|
||||
geoDataLevel: 2,
|
||||
geoDataLevel: 1,
|
||||
joinBy: ['NAME_CHN', 'name'],
|
||||
showBorder: false,
|
||||
showBorder: true,
|
||||
provinceStroke: 'red',
|
||||
label: {
|
||||
field: 'name',
|
||||
size: 10,
|
||||
padding: [5, 5],
|
||||
textAllowOverlap: true,
|
||||
},
|
||||
depth: 2,
|
||||
depth: 1,
|
||||
fill: {
|
||||
color: {
|
||||
field: 'NAME_CHN',
|
||||
|
@ -230,52 +231,18 @@ export default class Country extends React.Component {
|
|||
},
|
||||
});
|
||||
Layer.on('loaded', () => {
|
||||
const filldata = Layer.getFillData();
|
||||
const border = new LineLayer({
|
||||
zIndex: 5, // 设置显示层级
|
||||
})
|
||||
.source(filldata)
|
||||
.shape('line')
|
||||
.size(0.6)
|
||||
.color('#a00')
|
||||
.style({
|
||||
opacity: 1,
|
||||
});
|
||||
const hightLayer = new LineLayer({
|
||||
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],
|
||||
});
|
||||
});
|
||||
// const filldata = Layer.getFillData();
|
||||
// const border = new LineLayer({
|
||||
// zIndex: 5, // 设置显示层级
|
||||
// })
|
||||
// .source(filldata)
|
||||
// .shape('line')
|
||||
// .size(4)
|
||||
// .color('#a00')
|
||||
// .style({
|
||||
// opacity: 1,
|
||||
// });
|
||||
// scene.addLayer(border);
|
||||
});
|
||||
});
|
||||
this.scene = scene;
|
||||
|
|
|
@ -14,7 +14,7 @@ export default class Country extends React.Component {
|
|||
public async componentDidMount() {
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new Mapbox({
|
||||
map: new GaodeMap({
|
||||
center: [116.2825, 39.9],
|
||||
pitch: 0,
|
||||
style: 'blank',
|
||||
|
|
|
@ -21,8 +21,8 @@ export default class MultiLine extends React.Component {
|
|||
map: new GaodeMap({
|
||||
pitch: 0,
|
||||
style: 'dark',
|
||||
center: [101.775374, 3],
|
||||
zoom: 14.1,
|
||||
center: [101.775374, 20],
|
||||
zoom: 3,
|
||||
}),
|
||||
});
|
||||
|
||||
|
@ -34,16 +34,18 @@ export default class MultiLine extends React.Component {
|
|||
type: 'Feature',
|
||||
properties: {},
|
||||
geometry: {
|
||||
type: 'MultiLineString',
|
||||
type: 'LineString',
|
||||
coordinates: [
|
||||
[
|
||||
[100, 0],
|
||||
[101, 1],
|
||||
],
|
||||
[
|
||||
[102, 2],
|
||||
[103, 3],
|
||||
],
|
||||
[90.703125, 34.59704151614417],
|
||||
[112.8515625, 39.095962936305476],
|
||||
[117.42187500000001, 29.53522956294847],
|
||||
[127.61718749999999, 34.016241889667015],
|
||||
[129.0234375, 40.713955826286046],
|
||||
[136.40625, 36.87962060502676],
|
||||
[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')
|
||||
.color('red')
|
||||
.size(2)
|
||||
.style({
|
||||
opacity: 1.0,
|
||||
opacity: 0.5,
|
||||
lineType: 'dash',
|
||||
dashArray: [2, 2, 4, 2],
|
||||
});
|
||||
scene.addLayer(layer);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue