mirror of https://gitee.com/antv-l7/antv-l7
线支持pattern
This commit is contained in:
parent
3ed7ed4d25
commit
ebc892607a
Binary file not shown.
After Width: | Height: | Size: 811 B |
Binary file not shown.
After Width: | Height: | Size: 647 B |
|
@ -0,0 +1,100 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<meta name="geometry" content="diagram">
|
||||
<link rel="stylesheet" href="./assets/common.css">
|
||||
<title>city demo</title>
|
||||
<style>
|
||||
#map {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#timepannel {
|
||||
background: white;
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
right: 50px;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id='timepannel'>时间: 6时</div>
|
||||
<div id="map">
|
||||
|
||||
</div>
|
||||
<script src="https://webapi.amap.com/maps?v=1.4.8&key=f28fca5384129d180ad82915156a9baf&plugin=Map3D"></script>
|
||||
<script src="./assets/jquery-3.2.1.min.js"></script>
|
||||
<script src="../build/L7.js"></script>
|
||||
<script>
|
||||
var buildLayer = null;
|
||||
const scene = new L7.Scene({
|
||||
id: 'map',
|
||||
mapStyle: 'amap://styles/c9f1d10cae34f8ab05e425462c5a58d7', // 样式URL
|
||||
center: [120.102915, 30.261396],
|
||||
pitch: 0,
|
||||
zoom: 12,
|
||||
minZoom: 5,
|
||||
maxZoom: 18
|
||||
});
|
||||
scene.on('loaded', () => {
|
||||
scene.image.addImage('arrow', '/demos/assets/arrow.png');
|
||||
scene.image.addImage('right', '/demos/assets/right.png');
|
||||
|
||||
const mapData = {
|
||||
"type": "FeatureCollection",
|
||||
"features": [{
|
||||
"type": "Feature",
|
||||
"properties": { "type": 'right' },
|
||||
"geometry": {
|
||||
"type": "LineString",
|
||||
"coordinates": [
|
||||
[120.294931, 30.224459],
|
||||
[120.194847, 30.224384],
|
||||
[120.294847, 30.274384],
|
||||
[120.344847, 30.34384],
|
||||
[120.364847, 30.374384],
|
||||
[120.364847, 30.074384],
|
||||
]
|
||||
}
|
||||
}, {
|
||||
"type": "Feature",
|
||||
"properties": { "type": 'arrow' },
|
||||
"geometry": {
|
||||
"type": "LineString",
|
||||
"coordinates": [
|
||||
[120.394931, 30.324459],
|
||||
[120.494847, 30.324384],
|
||||
[120.494847, 30.374384],
|
||||
]
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
const linelayer = scene.LineLayer({
|
||||
zIndex: 2
|
||||
}).shape('line')
|
||||
.size([10, 0])
|
||||
.source(mapData)
|
||||
.color('#fff')
|
||||
.pattern('type', function (type) {
|
||||
return type;
|
||||
})
|
||||
.style({
|
||||
patternSpacing: 20
|
||||
})
|
||||
.render();
|
||||
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -76,6 +76,7 @@ export default class LineBuffer extends BufferBase {
|
|||
_getMeshLineAttributes() {
|
||||
const layerData = this.get('layerData');
|
||||
const { dashArray } = this.get('style');
|
||||
const imagePos = this.get('imagePos');
|
||||
const positions = [];
|
||||
const pickingIds = [];
|
||||
const normal = [];
|
||||
|
@ -85,10 +86,16 @@ export default class LineBuffer extends BufferBase {
|
|||
const sizes = [];
|
||||
const attrDistance = [];
|
||||
const attrDashArray = [];
|
||||
const textureCoord = [];
|
||||
const totalDistance = [];
|
||||
layerData.forEach(item => {
|
||||
const props = item;
|
||||
const positionCount = positions.length / 3;
|
||||
const attr = lineShape.Line(item.coordinates, props, positionCount, dashArray);
|
||||
let patternPos = { x: 0, y: 0 };
|
||||
if (item.pattern && imagePos[item.pattern]) {
|
||||
patternPos = imagePos[item.pattern];
|
||||
}
|
||||
const attr = lineShape.Line(item.coordinates, props, positionCount, dashArray, patternPos);
|
||||
positions.push(...attr.positions);
|
||||
normal.push(...attr.normal);
|
||||
miter.push(...attr.miter);
|
||||
|
@ -98,6 +105,8 @@ export default class LineBuffer extends BufferBase {
|
|||
attrDistance.push(...attr.attrDistance);
|
||||
pickingIds.push(...attr.pickingIds);
|
||||
attrDashArray.push(...attr.dashArray);
|
||||
textureCoord.push(...attr.textureCoordArray);
|
||||
totalDistance.push(...attr.totalDistances);
|
||||
});
|
||||
return {
|
||||
positions,
|
||||
|
@ -108,7 +117,9 @@ export default class LineBuffer extends BufferBase {
|
|||
pickingIds,
|
||||
sizes,
|
||||
attrDistance,
|
||||
attrDashArray
|
||||
attrDashArray,
|
||||
textureCoord,
|
||||
totalDistance
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -6,22 +6,42 @@ uniform float u_dash_ratio : 0.0;
|
|||
uniform float u_blur : 0.9;
|
||||
|
||||
varying vec4 v_color;
|
||||
varying float v_distance;
|
||||
#ifdef DASHLINE
|
||||
varying float v_distance_ratio;
|
||||
#endif
|
||||
varying float v_dash_array;
|
||||
varying float v_time;
|
||||
varying vec2 v_normal;
|
||||
|
||||
#ifdef TEXTURE
|
||||
uniform sampler2D u_texture;
|
||||
varying vec2 v_uv;
|
||||
varying float v_texture_y;
|
||||
varying float v_texture_percent;
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
#ifdef TEXTURE
|
||||
float texture_y_fract = fract(v_texture_y);
|
||||
if (texture_y_fract <= v_texture_percent) {
|
||||
vec4 tex_color = texture2D(u_texture, vec2(v_uv.x, 1.0 - 0.125 - v_uv.y + (texture_y_fract / v_texture_percent) * 0.125));
|
||||
// tex_color = texture2D(u_texture, vec2(v_uv.x, v_uv.y));
|
||||
gl_FragColor = vec4(mix(v_color.rgb, tex_color.rgb, tex_color.a), v_color.a);
|
||||
} else {
|
||||
gl_FragColor = v_color;
|
||||
#ifdef DASHLINE
|
||||
gl_FragColor.a *= u_opacity * ceil(mod(v_distance + u_dash_offset, v_dash_array) - (v_dash_array * u_dash_ratio));
|
||||
}
|
||||
#else
|
||||
gl_FragColor.a = v_color.a * u_opacity;
|
||||
gl_FragColor = v_color;
|
||||
#endif
|
||||
|
||||
#ifdef DASHLINE
|
||||
gl_FragColor.a *= u_opacity * ceil(mod(v_distance_ratio + u_dash_offset, v_dash_array) - (v_dash_array * u_dash_ratio));
|
||||
#else
|
||||
gl_FragColor.a *= u_opacity;
|
||||
#endif
|
||||
#ifdef ANIMATE
|
||||
gl_FragColor.a *= v_time;
|
||||
#endif
|
||||
|
||||
// anti-alias
|
||||
float blur = 1. - smoothstep(u_blur, 1., length(v_normal));
|
||||
gl_FragColor.a *= blur;
|
||||
|
|
|
@ -3,6 +3,7 @@ attribute vec4 a_color;
|
|||
attribute float a_size;
|
||||
attribute float a_distance;
|
||||
attribute float a_dash_array;
|
||||
attribute float a_total_distance;
|
||||
|
||||
uniform float u_zoom;
|
||||
uniform float u_time : 0;
|
||||
|
@ -11,9 +12,11 @@ uniform vec4 u_activeColor : [ 1.0, 0, 0, 1.0 ];
|
|||
|
||||
varying float v_time;
|
||||
varying vec4 v_color;
|
||||
varying float v_distance;
|
||||
varying float v_dash_array;
|
||||
varying vec2 v_normal;
|
||||
#ifdef DASHLINE
|
||||
varying float v_distance_ratio;
|
||||
#endif
|
||||
|
||||
#ifdef ANIMATE
|
||||
uniform float u_duration : 2.0;
|
||||
|
@ -21,22 +24,41 @@ uniform float u_interval : 1.0;
|
|||
uniform float u_trailLength : 0.2;
|
||||
#endif
|
||||
|
||||
#ifdef TEXTURE
|
||||
attribute vec2 a_texture_coord;
|
||||
uniform float u_pattern_spacing : 0.0;
|
||||
varying vec2 v_uv;
|
||||
varying float v_texture_y;
|
||||
varying float v_texture_percent;
|
||||
#endif
|
||||
void main() {
|
||||
// extrude along normal
|
||||
float extrude_scale = pow(2.0, 20.0 - u_zoom);
|
||||
v_color = a_color;
|
||||
v_distance = a_distance;
|
||||
v_dash_array = a_dash_array;
|
||||
float distance_ratio = a_distance / a_total_distance;
|
||||
#ifdef DASHLINE
|
||||
v_distance_ratio = distance_ratio;
|
||||
#endif
|
||||
#ifdef TEXTURE
|
||||
v_uv = vec2(a_texture_coord.x + 0.125, a_texture_coord.y);
|
||||
if (a_miter > 0.0) {
|
||||
v_uv.x = a_texture_coord.x;
|
||||
}
|
||||
v_texture_y = a_distance / extrude_scale / (a_size + u_pattern_spacing);
|
||||
v_texture_percent = a_size / (a_size + u_pattern_spacing);
|
||||
#endif
|
||||
|
||||
// anti-alias
|
||||
v_normal = vec2(normal * sign(a_miter));
|
||||
|
||||
// extrude along normal
|
||||
float extrude_scale = pow(2.0, 20.0 - u_zoom);
|
||||
|
||||
vec3 offset = vec3(normal * a_size * extrude_scale / 2.0 * a_miter);
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position.xy + offset.xy, 0., 1.0);
|
||||
// gl_Position.z -=0.8 * gl_Position.w;
|
||||
|
||||
#ifdef ANIMATE
|
||||
float alpha =1.0 - fract( mod(1.0- a_distance,u_interval)* (1.0/u_interval) + u_time / u_duration);
|
||||
float alpha =1.0 - fract( mod(1.0- distance_ratio,u_interval)* (1.0/u_interval) + u_time / u_duration);
|
||||
alpha = (alpha + u_trailLength -1.0) / u_trailLength;
|
||||
v_time = clamp(alpha,0.,1.);
|
||||
#endif
|
||||
|
|
|
@ -66,7 +66,7 @@ export function defaultLine(geo, index) {
|
|||
}
|
||||
// mesh line
|
||||
|
||||
export function Line(path, props, positionsIndex, lengthPerDashSegment = 200) {
|
||||
export function Line(path, props, positionsIndex, lengthPerDashSegment = 200, textureCoord) {
|
||||
if (Array.isArray(path[0][0])) {
|
||||
path = path[0]; // 面坐标转线坐标
|
||||
}
|
||||
|
@ -76,21 +76,23 @@ export function Line(path, props, positionsIndex, lengthPerDashSegment = 200) {
|
|||
const miter = [];
|
||||
const colors = [];
|
||||
const dashArray = [];
|
||||
|
||||
const textureCoordArray = [];
|
||||
const { normals, attrIndex, attrPos, attrDistance } = getNormals(path, false, positionsIndex);
|
||||
|
||||
const sizes = [];
|
||||
const totalDistances = [];
|
||||
let { size, color, id } = props;
|
||||
!Array.isArray(size) && (size = [ size ]);
|
||||
const totalLength = attrDistance[attrDistance.length - 1];
|
||||
attrPos.forEach(point => {
|
||||
colors.push(...color);
|
||||
pickingIds.push(id);
|
||||
sizes.push(size[0]);
|
||||
point[2] = size[1] || 0;
|
||||
positions.push(...point);
|
||||
textureCoordArray.push(textureCoord.x, textureCoord.y);
|
||||
totalDistances.push(totalLength);
|
||||
});
|
||||
|
||||
const totalLength = attrDistance[attrDistance.length - 1];
|
||||
const ratio = lengthPerDashSegment / totalLength;
|
||||
normals.forEach(n => {
|
||||
const norm = n[0];
|
||||
|
@ -100,6 +102,7 @@ export function Line(path, props, positionsIndex, lengthPerDashSegment = 200) {
|
|||
dashArray.push(ratio);
|
||||
});
|
||||
|
||||
|
||||
return {
|
||||
positions,
|
||||
normal,
|
||||
|
@ -108,10 +111,10 @@ export function Line(path, props, positionsIndex, lengthPerDashSegment = 200) {
|
|||
colors,
|
||||
sizes,
|
||||
pickingIds,
|
||||
attrDistance: attrDistance.map(d => {
|
||||
return d / totalLength;
|
||||
}),
|
||||
dashArray
|
||||
attrDistance,
|
||||
dashArray,
|
||||
textureCoordArray,
|
||||
totalDistances
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
import * as THREE from '../../../core/three';
|
||||
import { LineBuffer } from '../../../geom/buffer/index';
|
||||
import { MeshLineMaterial } from '../../../geom/material/lineMaterial';
|
||||
|
||||
export default function DrawLine(layerData, layer) {
|
||||
|
||||
const style = layer.get('styleOptions');
|
||||
const animateOptions = layer.get('animateOptions');
|
||||
const activeOption = layer.get('activedOptions');
|
||||
// const pattern = style.pattern;
|
||||
// const texture = layer.scene.image.singleImages[pattern];
|
||||
const hasPattern = layerData.some(layer => {
|
||||
return layer.pattern;
|
||||
});
|
||||
const { attributes } = new LineBuffer({
|
||||
layerData,
|
||||
shapeType: 'line',
|
||||
style
|
||||
style,
|
||||
imagePos: layer.scene.image.imagePos
|
||||
});
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
geometry.setIndex(attributes.indexArray);
|
||||
|
@ -21,6 +28,8 @@ export default function DrawLine(layerData, layer) {
|
|||
geometry.addAttribute('a_miter', new THREE.Float32BufferAttribute(attributes.miter, 1));
|
||||
geometry.addAttribute('a_distance', new THREE.Float32BufferAttribute(attributes.attrDistance, 1));
|
||||
geometry.addAttribute('a_dash_array', new THREE.Float32BufferAttribute(attributes.attrDashArray, 1));
|
||||
geometry.addAttribute('a_texture_coord', new THREE.Float32BufferAttribute(attributes.textureCoord, 2));
|
||||
geometry.addAttribute('a_total_distance', new THREE.Float32BufferAttribute(attributes.totalDistance, 1));
|
||||
|
||||
const lineMaterial = new MeshLineMaterial({
|
||||
u_opacity: style.opacity,
|
||||
|
@ -28,11 +37,14 @@ export default function DrawLine(layerData, layer) {
|
|||
u_time: 0,
|
||||
u_dash_offset: style.dashOffset,
|
||||
u_dash_ratio: style.dashRatio,
|
||||
activeColor: activeOption.fill
|
||||
activeColor: activeOption.fill,
|
||||
u_pattern_spacing: style.patternSpacing || 0,
|
||||
u_texture: hasPattern ? layer.scene.image.texture : null
|
||||
}, {
|
||||
SHAPE: false,
|
||||
ANIMATE: false,
|
||||
DASHLINE: style.lineType === 'dash'
|
||||
DASHLINE: style.lineType === 'dash',
|
||||
TEXTURE: hasPattern
|
||||
});
|
||||
|
||||
const lineMesh = new THREE.Mesh(geometry, lineMaterial);
|
||||
|
|
|
@ -67,7 +67,7 @@ export default function(points, closed, indexOffset) {
|
|||
extrusions(attrPos, out, last, _normal, 1);
|
||||
}
|
||||
|
||||
attrIndex.push([ index + 0, index + 3, index + 1 ]);
|
||||
attrIndex.push([ index + 0, index + 2, index + 1 ]);
|
||||
|
||||
// no miter, simple segment
|
||||
if (!next) {
|
||||
|
@ -75,9 +75,7 @@ export default function(points, closed, indexOffset) {
|
|||
normal(_normal, lineA);
|
||||
extrusions(attrPos, out, cur, _normal, 1);
|
||||
attrDistance.push(d, d);
|
||||
attrIndex.push(
|
||||
_lastFlip === 1 ? [ index + 1, index + 3, index + 2 ] : [ index, index + 2, index + 3 ]);
|
||||
|
||||
attrIndex.push([ index + 1, index + 2, index + 3 ]);
|
||||
count += 2;
|
||||
} else {
|
||||
// get unit dir of next line
|
||||
|
@ -87,7 +85,7 @@ export default function(points, closed, indexOffset) {
|
|||
let miterLen = computeMiter(tangent, miter, lineA, lineB, 1);
|
||||
|
||||
// get orientation
|
||||
let flip = (dot(tangent, _normal) < 0) ? -1 : 1;
|
||||
const flip = (dot(tangent, _normal) < 0) ? -1 : 1;
|
||||
const bevel = Math.abs(miterLen) > miterLimit;
|
||||
|
||||
// 处理前后两条线段重合的情况,这种情况不需要使用任何接头(miter/bevel)。
|
||||
|
@ -114,38 +112,39 @@ export default function(points, closed, indexOffset) {
|
|||
miterLen = miterLimit;
|
||||
|
||||
// next two points in our first segment
|
||||
addNext(out, _normal, -flip);
|
||||
attrPos.push(cur);
|
||||
addNext(out, miter, miterLen * flip);
|
||||
attrPos.push(cur);
|
||||
extrusions(attrPos, out, cur, _normal, 1);
|
||||
|
||||
attrIndex.push(_lastFlip !== -flip
|
||||
? [ index + 1, index + 3, index + 2 ] : [ index, index + 2, index + 3 ]);
|
||||
attrIndex.push([ index + 1, index + 2, index + 3 ]);
|
||||
|
||||
// now add the bevel triangle
|
||||
attrIndex.push([ index + 2, index + 3, index + 4 ]);
|
||||
attrIndex.push(flip === 1 ? [ index + 2, index + 4, index + 5 ] : [ index + 4, index + 5, index + 3 ]);
|
||||
|
||||
normal(tmp, lineB);
|
||||
copy(_normal, tmp); // store normal for next round
|
||||
|
||||
addNext(out, _normal, -flip);
|
||||
attrPos.push(cur);
|
||||
attrDistance.push(d, d, d);
|
||||
extrusions(attrPos, out, cur, _normal, 1);
|
||||
attrDistance.push(d, d, d, d);
|
||||
|
||||
// the miter is now the normal for our next join
|
||||
count += 3;
|
||||
count += 4;
|
||||
} else {
|
||||
// next two points for our miter join
|
||||
extrusions(attrPos, out, cur, miter, miterLen);
|
||||
attrDistance.push(d, d);
|
||||
attrIndex.push(_lastFlip === 1
|
||||
? [ index + 1, index + 3, index + 2 ] : [ index, index + 2, index + 3 ]);
|
||||
// next two points in our first segment
|
||||
extrusions(attrPos, out, cur, _normal, 1);
|
||||
attrIndex.push([ index + 1, index + 2, index + 3 ]);
|
||||
|
||||
flip = -1;
|
||||
// now add the miter triangles
|
||||
addNext(out, miter, miterLen * -flip);
|
||||
attrPos.push(cur);
|
||||
attrIndex.push([ index + 2, index + 4, index + 3 ]);
|
||||
attrIndex.push([ index + 4, index + 5, index + 6 ]);
|
||||
normal(tmp, lineB);
|
||||
copy(_normal, tmp); // store normal for next round
|
||||
|
||||
extrusions(attrPos, out, cur, _normal, 1);
|
||||
attrDistance.push(d, d, d, d, d);
|
||||
|
||||
// the miter is now the normal for our next join
|
||||
copy(_normal, miter);
|
||||
count += 2;
|
||||
count += 5;
|
||||
}
|
||||
_lastFlip = flip;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue