先看看效果图
实现多边形发光效果+中间半透明纹理
实现原理
使用高德GLCustomLayer自定义图层+webgl shader 渲染
主要发光算法比较简单就是当前的点到边线的距离
上代码
var map = new AMap.Map('container', {
center: [121.3435, 31.5120],
zooms: [2, 20],
zoom: 10.3,
viewMode: '3D',
mapStyle: "amap://styles/dark"
// pitch: 50,
});
var regl;
var draw;
// 数据转换工具
var customCoords = map.customCoords;
console.log(customCoords);
// 数据使用转换工具进行转换,这个操作必须要提前执行(在获取镜头参数 函数之前执行),否则将会获得一个错误信息。
let coords = [
[116.52, 39.79],
[116.56, 39.79],
[116.56, 39.77],
[116.52, 39.77],
];
coords = suzhou;
coords.forEach((coord,index) =>{
// new AMap.Marker({
// content:'index'+index,
// position:coord,
// map,
// })
})
var data = customCoords.lngLatsToCoords(coords);
//data = [[0,0],[0,1],[1,1],[1,0]]
let u_resolution = [document.body.clientWidth,document.body.clientHeight];
let point_params = {};
var texture = null;
// 创建 GL 图层
var gllayer = new AMap.GLCustomLayer({
// 图层的层级
zIndex: 100,
// 初始化的操作,创建图层过程中执行一次。
init: (gl) => {
// var ext = gl.getExtension('OES_texture_float');
// console.log(ext);
// console.log(available_extensions);
regl = createREGL({
gl,
// extensions:['OES_texture_float'],
});
console.log(gl);
const im = new Image();
im.crossOrigin = "anonymous";
im.src = "bg1.png";
im.onload = function (){
let points1 = data.map((item,index) => {
let next = data[index+1]?data[index+1]:data[0];
return [
item[0],
item[1],
next[0],
next[1],
]
})
// points1.push(...[-1,0,0,0])
points1.forEach((p,index) =>{
point_params['colors['+index+']'] = p;
})
if(points1.length < 1000){
points1.push(
[-1,-1,-1,-1]
)
}
window.points1 = points1;
draw = regl({
frag: `
precision mediump float;
uniform vec4 color;
uniform mat4 mvp;
uniform vec4 colors[1000];
uniform sampler2D texture;
varying vec2 vUv;
uniform vec2 u_resolution;
float dist(vec2 pt1, vec2 pt2, vec2 testPt)
{
if(dot(testPt - pt1,pt2-pt1) <=0.){
return length(testPt - pt1);
}
if(dot(testPt - pt2,pt1-pt2) <=0.){
return length(testPt - pt2);
}
vec2 lineDir = pt2 - pt1;
vec2 perpDir = vec2(lineDir.y, -lineDir.x);
vec2 dirToPt1 = pt1 - testPt;
return abs(dot(normalize(perpDir), dirToPt1));
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution;
float dis = 0.;
st = gl_FragCoord.xy/u_resolution;
dis = 0.;
for(int i=0;i<1000;i++){
if(colors[i].x == -1.0 && colors[i].y == -1.0){
break;
}
vec4 c_mvp = mvp * vec4(colors[i].xy, 0, 1);
vec2 point = (c_mvp.xy/c_mvp.w+1.0)/2.0;
vec4 c_mvp1 = mvp * vec4(colors[i].zw, 0, 1);
vec2 point1 = (c_mvp1.xy/c_mvp1.w+1.0)/2.0;
point.x = point.x * u_resolution.x;
point.y = point.y * u_resolution.y;
point1.x = point1.x * u_resolution.x;
point1.y = point1.y * u_resolution.y;
float dis_tmp = dist(point,point1,gl_FragCoord.xy);
if(dis_tmp>0.){
if(dis == 0.){
dis = dis_tmp;
}else{
dis = min(dis_tmp,dis);
}
}
}
if(dis > 15.){
dis = 1.;
}else {
dis = smoothstep(0.,1.,dis/15.0);
}
vec4 c_mvp = mvp * vec4(colors[0].xy, 0, 1);
vec2 point = (c_mvp.xy/c_mvp.w+1.0)/2.0;
point.x = point.x * u_resolution.x;
point.y = point.y * u_resolution.y;
vec4 vx = texture2D(texture,mod(gl_FragCoord.xy-point,64.)/64.);
vec4 color = vec4(vx.xyz,.5);
if(dis < 1.){
color = vec4( .1,.88,.9, dis);
}
if(dis > 0.9 && dis < 1.0){
color = vec4( .1,.88,.9, 1.0);
}
gl_FragColor = color;
}`,
vert: `
precision mediump float;
uniform vec2 aspectRatio;
attribute vec2 position;
attribute vec2 uv;
varying vec2 vUv;
varying vec4 v_position;
uniform mat4 mvp;
void main() {
vUv = uv;
gl_Position = mvp * vec4(position, 0, 1);
v_position = gl_Position;
gl_PointSize = 40.;
}`,
attributes: {
position: data,
uv: regl.buffer([[0.0, 1.0,],[0.0, 0.0],[1.0,1.0],[1.0,0.0]]),
},
elements:earcut(data.flat()),
blend:{
enable: true,
func: {
srcRGB: 'src alpha',
srcAlpha: 1,
dstRGB: 'one minus src alpha',
dstAlpha: 1
},
equation: {
rgb: 'add',
alpha: 'add'
},
color: [0, 0, 0, 0]
},
// primitive: 'points',
uniforms: {
color: [0.2, 0.4, 0.7, 1],
mvp: regl.prop('mvp'),
texture: regl.texture({
width :64,
height:64,
wrapS:'repeat',
wrapT:'repeat',
data:im,flipY:true
}),
...point_params,
u_resolution:u_resolution,
},
})
}
},
render: () => {
// 这里必须执行!!重新设置 three 的 gl 上下文状态。
regl._refresh();
if(draw){
let mvpMatrix = customCoords.getMVPMatrix();
draw({
mvp: mvpMatrix
});
}
},
});
map.add(gllayer);
代码说明
主要核心代码: mvp是高德的视图矩阵,转成point的屏幕坐标,colors为边框数组
vec4 c_mvp = mvp * vec4(colors[0].xy, 0, 1);
vec2 point = (c_mvp.xy/c_mvp.w+1.0)/2.0;
point.x = point.x * u_resolution.x;
point.y = point.y * u_resolution.y;