Skip to content

Commit 1542745

Browse files
committed
openlayer高性能图层代码优化。review by songyumeng.
1 parent e94e88c commit 1542745

File tree

10 files changed

+689
-532
lines changed

10 files changed

+689
-532
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@
7777
- 增加 `ol.style.CloverShape` `ol.style.HitCloverShape` 类,`ol.source.Graphic` 支持三叶草要素风格
7878

7979
- 废弃 `ol.source.TileSuperMapRest` `ol.source.ImageSuperMapRest` 类的 `options._cache` 参数,由 `options.cacheEnabled` 代替
80+
81+
- 废弃 `ol.source.Graphic` 类的 `onClick` 参数
82+
83+
- `ol.source.Graphic` 类新增 `isHighLight` 参数,支持高亮响应事件
84+
8085
### for MapboxGL
8186

8287
- 废弃 `SuperMap.ElasticSearch``options.change` 参数,直接使用 `SuperMap.ElasticSearch.msearch` `SuperMap.ElasticSearch.msearch``callback` 参数

dist/iclient9-openlayers.js

Lines changed: 519 additions & 435 deletions
Large diffs are not rendered by default.

dist/iclient9-openlayers.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/openlayers/07_graphiclayer_clover.html

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -133,15 +133,10 @@
133133
}
134134

135135
//设置每个点的经纬度和传入三叶草样式
136-
for (var i = 0; i < count; ++i) {
136+
for (var i = 0; i < count; i++) {
137137
var coordinates = [2 * e * Math.random() - e, 2 * e * Math.random() - e];
138138
graphics[i] = new ol.Graphic(new ol.geom.Point(coordinates));
139139
graphics[i].setStyle(clovers[Math.floor(Math.random() * randCount)]);
140-
var pointVector = graphics[i];
141-
pointVector.style = {
142-
image: clovers[i % symbolCount]
143-
};
144-
graphics.push(pointVector);
145140
}
146141

147142
map.once('postrender', function () {

src/mapboxgl/core/Base.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
* 定义命名空间
44
*/
55
import mapboxgl from 'mapbox-gl';
6-
import '../core/MapExtend';
6+
import './MapExtend';
77

88
mapboxgl.supermap = mapboxgl.supermap || {};

src/mapboxgl/core/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
export {Util} from './Util';
1+
export {Util} from './Util';
2+
export {MapExtend} from './MapExtend';

src/openlayers/core/MapExtend.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import ol from 'openlayers';
2+
3+
/**
4+
* @function MapExtend
5+
* @description 扩展openlayers的一些原始方法
6+
* @private
7+
*/
8+
export var MapExtend = function () {
9+
ol.Map.prototype.forEachFeatureAtPixelDefault = ol.Map.prototype.forEachFeatureAtPixel;
10+
11+
ol.Map.prototype.forEachFeatureAtPixel = function (pixel, callback, opt_options) {
12+
13+
this.forEachFeatureAtPixelDefault(pixel, callback, opt_options);
14+
15+
let layers = this.getLayers().getArray();
16+
let resolution = this.getView().getResolution();
17+
let coordinate = this.getCoordinateFromPixel(pixel);
18+
for (let i = 0; i < layers.length; i++) {
19+
if (layers[i].getSource()._forEachFeatureAtCoordinate) {
20+
layers[i].getSource()._forEachFeatureAtCoordinate(coordinate, resolution, callback, pixel);
21+
}
22+
}
23+
}
24+
}();

src/openlayers/core/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export {StyleUtils} from './StyleUtils';
2-
export {Util} from './Util';
2+
export {Util} from './Util';
3+
export {MapExtend} from './MapExtend';

src/openlayers/overlay/Graphic.js

Lines changed: 122 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import ol from 'openlayers';
2+
import '../core/MapExtend';
23
import {
34
Util
45
} from '../core/Util';
@@ -13,7 +14,12 @@ import {
1314
* @class ol.source.Graphic
1415
* @category Visualization Graphic
1516
* @classdesc 高效率点图层源。
16-
* @param options -{Object} 图形参数
17+
* @param options -{Object} 图形参数。如:<br>
18+
* graphics - {ol.Graphic} 高效率点图层点要素。<br>
19+
* map - [ol.Map]{@linkdoc-openlayers/ol.Map.html} openlayers 面对象。<br>
20+
* isHighLight - {boolean} 事件响应是否支持要素高亮。默认为 true,即默认支持高亮。<br>
21+
* highLightStyle - [ol.style]{@linkdoc-openlayers/ol.style.html} 高亮风格,默认为 defaultHighLightStyle。<br>
22+
* onClick - {function} 点击事件方法。将在下个版本弃用。<br>
1723
* @extends ol.source.ImageCanvas{@linkdoc-openlayers/ol.source.ImageCanvas}
1824
*/
1925
export class Graphic extends ol.source.ImageCanvas {
@@ -31,16 +37,20 @@ export class Graphic extends ol.source.ImageCanvas {
3137
this.graphics_ = options.graphics;
3238
this.map = options.map;
3339
this.highLightStyle = options.highLightStyle;
40+
//是否支持高亮,默认支持
41+
this.isHighLight = typeof options.isHighLight === "undefined" ? true : options.isHighLight;
3442
this.hitGraphicLayer = null;
35-
43+
this._forEachFeatureAtCoordinate = _forEachFeatureAtCoordinate;
3644

3745
var me = this;
46+
47+
//todo 将被弃用
3848
if (options.onClick) {
3949
me.map.on('click', function (e) {
4050
var coordinate = e.coordinate;
4151
var resolution = e.frameState.viewState.resolution;
4252
var pixel = e.pixel;
43-
me.forEachFeatureAtCoordinate(coordinate, resolution, options.onClick,pixel);
53+
me._forEachFeatureAtCoordinate(coordinate, resolution, options.onClick, pixel);
4454
});
4555
}
4656

@@ -118,6 +128,115 @@ export class Graphic extends ol.source.ImageCanvas {
118128
var y = (pixelP[1] - center[1]) * scaleRatio + center[1];
119129
return [x, y];
120130
}
131+
132+
/**
133+
* @private
134+
* @function ol.source.Graphic.prototype._forEachFeatureAtCoordinate
135+
* @description 获取在视图上的要素
136+
* @param coordinate -{string} 坐标
137+
* @param resolution -{number} 分辨率
138+
* @param callback -{function} 回调函数
139+
*/
140+
function _forEachFeatureAtCoordinate(coordinate, resolution, callback, evtPixel) {
141+
let graphics = me.getGraphicsInExtent();
142+
for (let i = graphics.length - 1; i >= 0; i--) {
143+
//已经被高亮的graphics 不被选选中
144+
if (graphics[i].getStyle() instanceof HitCloverShape) {
145+
continue;
146+
}
147+
let center = graphics[i].getGeometry().getCoordinates();
148+
let image = new ol.style.Style({
149+
image: graphics[i].getStyle()
150+
}).getImage();
151+
let extent = [];
152+
extent[0] = center[0] - image.getAnchor()[0] * resolution;
153+
extent[2] = center[0] + image.getAnchor()[0] * resolution;
154+
extent[1] = center[1] - image.getAnchor()[1] * resolution;
155+
extent[3] = center[1] + image.getAnchor()[1] * resolution;
156+
if (ol.extent.containsCoordinate(extent, coordinate)) {
157+
if (me.isHighLight) {
158+
me._highLight(center, image, graphics[i], evtPixel);
159+
}
160+
return callback(graphics[i]);
161+
}
162+
if (me.isHighLight) {
163+
me._highLightClose();
164+
}
165+
}
166+
return undefined;
167+
}
168+
169+
}
170+
171+
/**
172+
* @function ol.source.Graphic.prototype._highLightClose
173+
* @description 关闭高亮要素显示
174+
* @private
175+
*/
176+
_highLightClose() {
177+
this.selected = null;
178+
if (this.hitGraphicLayer) {
179+
this.map.removeLayer(this.hitGraphicLayer);
180+
this.hitGraphicLayer = null;
181+
}
182+
this.changed();
183+
}
184+
185+
/**
186+
* @function ol.source.Graphic.prototype._highLight
187+
* @description 高亮显示选中要素
188+
* @param selectGraphic - {ol.Graphic} 高效率点图层点要素
189+
* @param evtPixel - [ol.Pixel]{@linkdoc-openlayers/ol.html#.Pixel} 当前选中的屏幕像素坐标
190+
* @private
191+
*/
192+
_highLight(center, image, selectGraphic, evtPixel) {
193+
if (selectGraphic.getStyle() instanceof CloverShape) {
194+
if (this.hitGraphicLayer) {
195+
this.map.removeLayer(this.hitGraphicLayer);
196+
this.hitGraphicLayer = null;
197+
}
198+
var pixel = this.map.getPixelFromCoordinate([center[0], center[1]]);
199+
//点击点与中心点的角度
200+
evtPixel = evtPixel || [0, 0];
201+
var angle = (Math.atan2(evtPixel[1] - pixel[1], evtPixel[0] - pixel[0])) / Math.PI * 180;
202+
angle = angle > 0 ? angle : 360 + angle;
203+
//确定扇叶
204+
var index = Math.ceil(angle / (image.getAngle() + image.getSpaceAngle()));
205+
//扇叶的起始角度
206+
var sAngle = (index - 1) * (image.getAngle() + image.getSpaceAngle());
207+
//渲染参数
208+
var opts = {
209+
stroke: new ol.style.Stroke({
210+
color: "#ff0000",
211+
width: 1
212+
}),
213+
fill: new ol.style.Fill({
214+
color: "#0099ff"
215+
}),
216+
radius: image.getRadius(),
217+
angle: image.getAngle(),
218+
eAngle: sAngle + image.getAngle(),
219+
sAngle: sAngle
220+
};
221+
if (this.highLightStyle && this.highLightStyle instanceof HitCloverShape) {
222+
opts.stroke = this.highLightStyle.getStroke();
223+
opts.fill = this.highLightStyle.getFill();
224+
opts.radius = this.highLightStyle.getRadius();
225+
opts.angle = this.highLightStyle.getAngle();
226+
}
227+
var hitGraphic = new ol.Graphic(new ol.geom.Point(center));
228+
hitGraphic.setStyle(new HitCloverShape(opts));
229+
this.hitGraphicLayer = new ol.layer.Image({
230+
source: new ol.source.Graphic({
231+
map: this.map,
232+
graphics: [hitGraphic]
233+
})
234+
});
235+
this.map.addLayer(this.hitGraphicLayer);
236+
} else {
237+
this.selected = selectGraphic;
238+
this.changed();
239+
}
121240
}
122241

123242
/**
@@ -143,86 +262,6 @@ export class Graphic extends ol.source.ImageCanvas {
143262
return graphics;
144263
}
145264

146-
/**
147-
* @private
148-
* @function ol.source.Graphic.prototype.forEachFeatureAtCoordinate
149-
* @description 获取在视图上的要素
150-
* @param coordinate -{string} 坐标
151-
* @param resolution -{number} 分辨率
152-
* @param callback -{function} 回调函数
153-
*/
154-
forEachFeatureAtCoordinate(coordinate, resolution, callback, evtPixel) {
155-
var graphics = this.getGraphicsInExtent();
156-
for (var i = graphics.length - 1; i > 0; i--) {
157-
var center = graphics[i].getGeometry().getCoordinates();
158-
var image = new ol.style.Style({
159-
image: graphics[i].getStyle()
160-
}).getImage();
161-
var extent = [];
162-
extent[0] = center[0] - image.getAnchor()[0] * resolution;
163-
extent[2] = center[0] + image.getAnchor()[0] * resolution;
164-
extent[1] = center[1] - image.getAnchor()[1] * resolution;
165-
extent[3] = center[1] + image.getAnchor()[1] * resolution;
166-
if (ol.extent.containsCoordinate(extent, coordinate)) {
167-
if (graphics[i].getStyle() instanceof CloverShape) {
168-
if (this.hitGraphicLayer) {
169-
this.map.removeLayer(this.hitGraphicLayer);
170-
this.hitGraphicLayer = null;
171-
}
172-
var pixel = this.map.getPixelFromCoordinate([center[0], center[1]]);
173-
//点击点与中心点的角度
174-
evtPixel = evtPixel || [0, 0];
175-
var angle = (Math.atan2(evtPixel[1] - pixel[1], evtPixel[0] - pixel[0])) / Math.PI * 180;
176-
angle = angle > 0 ? angle : 360 + angle;
177-
//确定扇叶
178-
var index = Math.ceil(angle / (image.getAngle() + image.getSpaceAngle()));
179-
//扇叶的起始角度
180-
var sAngle = (index - 1) * (image.getAngle() + image.getSpaceAngle());
181-
//渲染参数
182-
var opts = {
183-
stroke: new ol.style.Stroke({
184-
color: "#ff0000",
185-
width: 1
186-
}),
187-
fill: new ol.style.Fill({
188-
color: "#0099ff"
189-
}),
190-
radius: image.getRadius(),
191-
angle: image.getAngle(),
192-
eAngle: sAngle + image.getAngle(),
193-
sAngle: sAngle
194-
};
195-
if (this.highLightStyle && this.highLightStyle instanceof HitCloverShape) {
196-
opts.stroke = this.highLightStyle.getStroke();
197-
opts.fill = this.highLightStyle.getFill();
198-
opts.radius = this.highLightStyle.getRadius();
199-
opts.angle = this.highLightStyle.getAngle();
200-
}
201-
var hitGraphic = new ol.Graphic(new ol.geom.Point(center));
202-
hitGraphic.setStyle(new HitCloverShape(opts));
203-
this.hitGraphicLayer = new ol.layer.Image({
204-
source: new ol.source.Graphic({
205-
map: this.map,
206-
graphics: [hitGraphic]
207-
})
208-
});
209-
this.map.addLayer(this.hitGraphicLayer);
210-
} else {
211-
this.selected = graphics[i];
212-
this.changed();
213-
}
214-
callback(graphics[i]);
215-
return;
216-
}
217-
this.selected = null;
218-
if (this.hitGraphicLayer) {
219-
this.map.removeLayer(this.hitGraphicLayer);
220-
this.hitGraphicLayer = null;
221-
}
222-
this.changed();
223-
}
224-
callback();
225-
}
226265
}
227266

228267
ol.source.Graphic = Graphic;

test/openlayers/overlay/GraphicSpec.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ describe('openlayers_GraphicLayer', () => {
9696
var a = new Graphic({
9797
graphics: graphics,
9898
map: map
99-
}).forEachFeatureAtCoordinate(coors[1], 1, (result) => {
99+
})._forEachFeatureAtCoordinate(coors[1], 1, (result) => {
100100
console.log(result);
101101
});
102102
expect(a).not.toBeNull();
@@ -228,17 +228,25 @@ describe('openlayers_GraphicLayer', () => {
228228
});
229229
map.addLayer(graphicLayer);
230230
});
231+
231232
setTimeout(() => {
232233
expect(1).not.toBeNull();
233-
graphicLayer.getSource().forEachFeatureAtCoordinate(coors[2], 1, (result) => {
234+
graphicLayer.getSource()._forEachFeatureAtCoordinate(coors[2], 1, (result) => {
234235
console.log(result);
235236
});
236-
graphicLayer.getSource().forEachFeatureAtCoordinate(coors[1], 1, (result) => {
237+
graphicLayer.getSource()._forEachFeatureAtCoordinate(coors[1], 1, (result) => {
237238
console.log(result);
238239
});
239-
graphicLayer.getSource().forEachFeatureAtCoordinate([-126.16, 39.05], 1, (result) => {
240+
graphicLayer.getSource()._forEachFeatureAtCoordinate([-126.16, 39.05], 1, (result) => {
240241
console.log(result);
241242
});
243+
244+
let pixel = map.getPixelFromCoordinate([-36.16, 39.05]);
245+
map.forEachFeatureAtPixel(pixel,
246+
(graphic) => {
247+
expect(graphic).not.toBeNull();
248+
console.log(graphic);
249+
});
242250
map.removeLayer(graphicLayer);
243251
done();
244252
}, 1000)

0 commit comments

Comments
 (0)