Skip to content

Commit 47caeee

Browse files
authored
fix layer clip when mask has holes (#1891)
* fix layer clip when polygon has holes * add spec
1 parent eba9c2f commit 47caeee

File tree

3 files changed

+68
-32
lines changed

3 files changed

+68
-32
lines changed

src/core/Canvas.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,11 +505,17 @@ const Canvas = {
505505
},
506506

507507
polygon(ctx, points, lineOpacity, fillOpacity, lineDashArray, smoothness) {
508-
// if MultiClip
508+
// if MultiPolygon clip
509509
if (ctx.isMultiClip) {
510510
Canvas._multiClip(ctx, points);
511511
return;
512512
}
513+
//polygon clip
514+
if (ctx.isClip) {
515+
// if points[0] is array ,the polygon has hole,ignore holes
516+
Canvas._multiClip(ctx, Array.isArray(points[0]) ? points : [points]);
517+
return;
518+
}
513519
if (!isArrayHasData(points)) {
514520
return;
515521
}

src/renderer/layer/CanvasRenderer.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -581,10 +581,13 @@ class CanvasRenderer extends Class {
581581
painter.paint(null, context);
582582
});
583583
context.stroke();
584-
delete context.isMultiClip;
584+
context.isMultiClip = false;
585585
} else {
586+
context.isClip = true;
587+
context.beginPath();
586588
const painter = mask._getMaskPainter();
587589
painter.paint(null, context);
590+
context.isClip = false;
588591
}
589592
if (dpr !== 1) {
590593
context.restore();

test/layer/MaskSpec.js

Lines changed: 57 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,26 @@ describe('Spec of Masks', function () {
88
var context = {
99
};
1010

11+
function createRing(offset) {
12+
var center = map.getCenter();
13+
var x = center.x, y = center.y;
14+
var minx = x - offset, maxx = x + offset, miny = y - offset, maxy = y + offset;
15+
return [
16+
[minx, miny],
17+
[minx, maxy],
18+
[maxx, maxy],
19+
[maxx, miny],
20+
[minx, miny]
21+
];
22+
}
23+
1124
beforeEach(function () {
1225
container = document.createElement('div');
1326
container.style.width = '150px';
1427
container.style.height = '150px';
1528
document.body.appendChild(container);
1629
var option = {
17-
centerCross : true,
30+
centerCross: true,
1831
zoom: 17,
1932
center: center
2033
};
@@ -52,38 +65,38 @@ describe('Spec of Masks', function () {
5265
done();
5366
});
5467
layer.setMask(new maptalks.Marker(map.getCenter(), {
55-
'symbol' : {
56-
'markerType' : 'ellipse',
57-
'markerWidth' : 20,
58-
'markerHeight' : 20,
59-
'markerFill' : '#fff',
60-
'markerFillOpacity' : 1,
61-
'markerLineWidth' : 3,
62-
'markerDy' : 5
68+
'symbol': {
69+
'markerType': 'ellipse',
70+
'markerWidth': 20,
71+
'markerHeight': 20,
72+
'markerFill': '#fff',
73+
'markerFillOpacity': 1,
74+
'markerLineWidth': 3,
75+
'markerDy': 5
6376
}
6477
}));
6578
done();
6679
});
6780
layer.setMask(new maptalks.Circle(map.getCenter(), 5, {
68-
symbol : {
69-
'polygonFill' : 'rgba(255, 255, 255, 0.1)'
81+
symbol: {
82+
'polygonFill': 'rgba(255, 255, 255, 0.1)'
7083
}
7184
}));
7285

7386
}
7487

7588
var tileLayer = new maptalks.TileLayer('tile', {
76-
urlTemplate : TILE_IMAGE,
77-
renderer:'canvas'
89+
urlTemplate: TILE_IMAGE,
90+
renderer: 'canvas'
7891
});
7992
//test tilelayer
8093
runTests(tileLayer, context);
8194

8295
//test vectorlayer
8396
var vlayer = new maptalks.VectorLayer('v').addGeometry(new maptalks.Circle(center, 2000, {
84-
symbol : {
85-
'polygonFill' : 'rgba(0, 0, 0, 0.1)',
86-
'polygonOpacity' : 1
97+
symbol: {
98+
'polygonFill': 'rgba(0, 0, 0, 0.1)',
99+
'polygonOpacity': 1
87100
}
88101
}));
89102

@@ -108,12 +121,12 @@ describe('Spec of Masks', function () {
108121

109122
it('can remove mask,' + layerToTest.getJSONType(), function (done) {
110123
layerToTest.setMask(new maptalks.Marker(map.getCenter(), {
111-
'symbol' : {
112-
'markerType' : 'ellipse',
113-
'markerWidth' : 10,
114-
'markerHeight' : 10,
115-
'markerFill' : '#000',
116-
'markerFillOpacity' : 1
124+
'symbol': {
125+
'markerType': 'ellipse',
126+
'markerWidth': 10,
127+
'markerHeight': 10,
128+
'markerFill': '#000',
129+
'markerFillOpacity': 1
117130
}
118131
}));
119132
setTimeout(function () {
@@ -152,12 +165,12 @@ describe('Spec of Masks', function () {
152165

153166
it('#713', function (done) {
154167
vlayer.setMask(new maptalks.Marker(map.getCenter(), {
155-
'symbol' : {
156-
'markerType' : 'ellipse',
157-
'markerWidth' : 10,
158-
'markerHeight' : 10,
159-
'markerFill' : '#000',
160-
'markerFillOpacity' : 1
168+
'symbol': {
169+
'markerType': 'ellipse',
170+
'markerWidth': 10,
171+
'markerHeight': 10,
172+
'markerFill': '#000',
173+
'markerFillOpacity': 1
161174
}
162175
}));
163176
map.addLayer(vlayer);
@@ -212,8 +225,8 @@ describe('Spec of Masks', function () {
212225
new maptalks.Circle(map.locate(map.getCenter(), 10, 0), 5).getShell()
213226
]);
214227
var tileLayer = new maptalks.TileLayer('tile', {
215-
urlTemplate : TILE_IMAGE,
216-
renderer:'canvas'
228+
urlTemplate: TILE_IMAGE,
229+
renderer: 'canvas'
217230
});
218231
tileLayer.setMask(mask);
219232
map.addLayer(tileLayer);
@@ -222,4 +235,18 @@ describe('Spec of Masks', function () {
222235
expect(extent.ymin).to.be.ok();
223236
});
224237

238+
it('mask has hole', function () {
239+
var layer = new maptalks.VectorLayer('layer').addTo(map);
240+
new maptalks.Marker(map.getCenter().toArray()).addTo(layer);
241+
var ring = createRing(0.2), hole = createRing(0.1);
242+
var polygon = new maptalks.Polygon([ring, hole]);
243+
map.on('frameend', function () {
244+
expect(layer).to.be.painted(0, 0);
245+
layer.setMask(polygon);
246+
map.on('frameend', function () {
247+
expect(layer).to.be.painted(0, 0);
248+
})
249+
})
250+
});
251+
225252
});

0 commit comments

Comments
 (0)