背景
????最近看到ArcGIS Maps SDK for JavaScript官網(wǎng)有個聚焦效果的例子,于是想在MapTalks上也試試。

屏幕截圖 2023-03-05 102128.png
原理
????濾鏡的原理主要是用的canvas的cssfilter屬性,讓它整體有模糊或者高亮的功能。另外高亮區(qū)域使用的是canvas的裁剪。
方案一
????使用maptalks原生api,對底圖進(jìn)行模糊和蒙版操作,由于這里要兩種濾鏡,所以需要有兩個底圖方便處理,一個進(jìn)行模糊處理,一個設(shè)置蒙版。
設(shè)置模糊濾鏡效果
var map = new maptalks.Map('map', {
center: [109.191369116306319, 19.736612649767874],
zoom: 16,
pitch : 0,
dragPitch:false,
baseLayer : new maptalks.TileLayer('tile1', {
urlTemplate: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
cssFilter : 'blur(10px) grayscale(1.2)',
})
});
????設(shè)置模蒙版和高亮濾鏡效果
var boundary = [ [ [ 109.191369116306319, 19.736612649767874 ], [ 109.191347658634214, 19.736794423924326 ], [ 109.19259220361711, 19.736531861187487 ], [ 109.195274412632031, 19.735562395035053 ], [ 109.209500849247036, 19.730068642352247 ], [ 109.209565222263379, 19.72653395894347 ], [ 109.209264814853711, 19.726453165265738 ], [ 109.209028780460415, 19.726069394738637 ], [ 109.203707277774839, 19.726089593210407 ], [ 109.203664362430601, 19.726594554174969 ], [ 109.202827513217969, 19.727099513543749 ], [ 109.201840460300488, 19.728028634612741 ], [ 109.2000594735146, 19.728715372799819 ], [ 109.195961058139844, 19.730270621899336 ], [ 109.192656576633482, 19.731401702643819 ], [ 109.192999899387388, 19.731745064856661 ], [ 109.192849695682554, 19.732048030902128 ], [ 109.192163050174742, 19.73196724001286 ], [ 109.191154539585142, 19.732674158908559 ], [ 109.19169098138812, 19.735461408639065 ], [ 109.191369116306319, 19.736612649767874 ] ] ]
var mask = new maptalks.Polygon(boundary, {
'symbol' : [
{
'polygonOpacity': 1,
'polygonFill': 'rgb(0,0,0)',
'lineColor': 'rgb(0,0,0)',
'lineWidth': 1,
}
]
});
var maskedLayer = new maptalks.TileLayer('tile2', {
zIndex:100,
urlTemplate: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
cssFilter : 'drop-shadow(0px 0px 20px black) brightness(1.0)',
})
.setMask(mask) // set boundary as the mask to the tilelayer
.addTo(map);
????由于底圖的drop-shadow濾鏡效果不太明顯,需要繪制一個vectorlayer
var outline = new maptalks.Polygon(boundary, {
'symbol' : [
{
'polygonOpacity': 1,
'polygonFill': 'rgb(0,0,0)',
'lineColor': 'rgb(0,0,0)',
'lineWidth': 1,
}
]
});
new maptalks.VectorLayer('v', [outline],{
enableSimplify:false,
cssFilter : 'drop-shadow(-6px -6px 16px black)',
}
).addTo(map);
????優(yōu)點:二三維均可使用,圖形繪制簡單。缺點:一個圖層使用cssfilter影響過大
方案二
????使用底圖監(jiān)聽繪制事件,繪制完成以后,通過canvas上下文獲取到圖片,對圖片進(jìn)行上述模糊蒙版高亮等處理。
function onRenderEnd(e) {
console.time('draw')
// map's canvas context
var ctx = e.context;
ctx.filter= 'drop-shadow(-6px -6px 16px black)';
var c=ctx.canvas;
var imgData=ctx.getImageData(0,0,c.width,c.height);
ctx.drawImage(createBg(imgData, c.width,c.height,'blur(10px) '),0,0);
ctx.drawImage(createMagCircle(imgData,c.width,c.height,boundary), 0, 0);
console.timeEnd('draw')
}
map.on('renderend', onRenderEnd);
????新建canvas,轉(zhuǎn)換坐標(biāo)后繪制圖形,接著繪制當(dāng)前底圖圖片,返回canvas元素
function createMagCircle(imageData,width,height,coords) {
var magImg = document.createElement('canvas');
var magCircle = document.createElement('canvas');
//console.log(sw,sh)
magImg.width = magCircle.width =width
magImg.height = magCircle.height = height
magImg.getContext('2d').putImageData(imageData, 0, 0);
var ctx = magCircle.getContext('2d');
ctx.beginPath();
for(let i=0;i<coords[0].length;i++){
var center = new maptalks.Coordinate(coords[0][i]);
let containerPoint = map.coordinateToContainerPoint(center).round();
let cx = containerPoint.x
let cy = containerPoint.y
if(i==0){
ctx.moveTo(cx,cy);
}else{
ctx.lineTo(cx,cy);
}
}
ctx.stroke();
ctx.clip();
ctx.drawImage(magImg, 0, 0);
return magCircle;
}
????新建canvas元素,繪制繪制當(dāng)前底圖圖片,進(jìn)行模糊濾鏡處理
function createBg(imageData, width,height,cssfilter) {
var magImg = document.createElement('canvas');
var magCircle = document.createElement('canvas');
magImg.width =width
magImg.height = height
magCircle.width = width
magCircle.height = height;
magImg.getContext('2d').putImageData(imageData, 0, 0);
var ctx = magCircle.getContext('2d');
ctx.filter= cssfilter
ctx.drawImage(magImg, 0, 0);
return magCircle;
}
????優(yōu)點:只要一個地圖并且不用再繪制vectorlayer。缺點:只能二維使用,三維沒有處理所以不可用,圖形繪制處理比較復(fù)雜需要知道一些canvas知識
效果

屏幕截圖 2023-03-05 101534.png

屏幕截圖 2023-03-05 101741.png