From 4ed55c57e7a4c202f8b8a76e847bfe7616191668 Mon Sep 17 00:00:00 2001 From: thinkinggis Date: Mon, 20 Jan 2020 18:06:02 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20pointlayer=20image=20=E6=A8=A1=E7=B3=8A&?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6&=20marker=20add=20some=20new=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .storybook/main.js | 13 +++++ docs/api/component/marker.zh.md | 16 +++++- docs/api/component/markerLayer.zh.md | 7 ++- docs/api/component/popup.zh.md | 8 +++ docs/api/layer/point_layer/cluster.zh.md | 7 +++ docs/api/source/source.en.md | 43 +++++++++++++++ docs/api/source/source.zh.md | 4 +- packages/component/src/marker.ts | 52 +++++++++++++++++++ packages/component/src/popup.ts | 10 ++++ .../src/services/component/IMarkerService.ts | 3 ++ .../src/services/component/IPopupService.ts | 2 + packages/layers/src/point/models/image.ts | 2 + .../layers/src/point/shaders/image_frag.glsl | 3 +- .../layers/src/point/shaders/image_vert.glsl | 2 + .../layers/src/point/shaders/text_frag.glsl | 2 + .../layers/src/point/shaders/text_vert.glsl | 3 +- packages/utils/src/dom.ts | 10 ++++ stories/Components/components/Marker.tsx | 23 ++++++-- stories/Layers/components/PointImage.tsx | 3 ++ stories/Layers/components/Text.tsx | 3 ++ .../MapAdaptor/components/multiMaptest.tsx | 2 - 21 files changed, 203 insertions(+), 15 deletions(-) create mode 100644 .storybook/main.js diff --git a/.storybook/main.js b/.storybook/main.js new file mode 100644 index 0000000000..fdc6fb8885 --- /dev/null +++ b/.storybook/main.js @@ -0,0 +1,13 @@ +const path = require('path'); + +// Export a function. Accept the base config as the only param. +module.exports = { + webpackFinal: async (config, { configType }) => { + config.module.rules.push({ + test: /\.stories\**.svg$/, + loader: 'svg-inline-loader' + } + ); + return config; + }, +}; diff --git a/docs/api/component/marker.zh.md b/docs/api/component/marker.zh.md index acebab05f0..32903cc18e 100644 --- a/docs/api/component/marker.zh.md +++ b/docs/api/component/marker.zh.md @@ -15,7 +15,7 @@ Marker - color        `string`   ![map-marker.png](https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*BJ6cTpDcuLcAAAAAAAAAAABkARQnAQ)  设置默认 marker 的颜色 - element    `Dom|string`    自定义 marker Dom 节点,可以是 dom 实例,也可以是 dom id -- anchor     `string`  锚点位置   支持 center, top, top-left, top-right, bottom, bottom-left,bottom-                        right,left, right +- anchor     `string`  锚点位置   支持 center, top, top-left, top-right, bottom, bottom-left,bottom-right,left, right - offset    `Array`  偏移量  [ 0, 0 ] 分别表示 X, Y 的偏移量 - extData 用户自定义属性,支持任意数据类型,存储 marker 属性信息 @@ -37,6 +37,12 @@ Marker 获取 marker dom Element +### setElement + +- element `dom` + +设置 element 通过此方法更新 Marker 样式 + #### getLngLat 获取 marker 经纬度坐标 @@ -45,6 +51,14 @@ Marker 开启或者关闭 marker 弹出框 +#### openPopup + +打开 Popup + +### closePopup + +关闭 popup + #### setPopup 为 marker 设置 popup diff --git a/docs/api/component/markerLayer.zh.md b/docs/api/component/markerLayer.zh.md index 6bfb7c39ba..36845e100c 100644 --- a/docs/api/component/markerLayer.zh.md +++ b/docs/api/component/markerLayer.zh.md @@ -33,11 +33,10 @@ scene.addMarkerLayer(markerLayer); #### option -- cluster 是部分聚合 `boolean` 默认 `false` +- cluster 聚合 `boolean` 默认 `false` - clusterOption 聚合配置 -- cluster 是部分聚合 - - element `function` + - element `function` 通过回调函数设置聚合 Marker 的样式,返回 dom 元素 后续会增加更多配置项目 @@ -47,7 +46,7 @@ scene.addMarkerLayer(markerLayer); 参数 -- marker `Marker` 需要添加的 Marker +- marker `IMarker` 需要添加的 Marker 添加 Marker diff --git a/docs/api/component/popup.zh.md b/docs/api/component/popup.zh.md index 3155708790..4e89361f8c 100644 --- a/docs/api/component/popup.zh.md +++ b/docs/api/component/popup.zh.md @@ -60,6 +60,14 @@ var html = popup.setHtml(html); ``` +#### setDOMContent + +- 参数 htmlNode dom 对象 + 区别于 setHtml 对象只能传字符串 + +**tips** +如果需要将 react 组件渲染到 popup 可以用此方法。 + #### setText 设置 popup 显示文本内容 diff --git a/docs/api/layer/point_layer/cluster.zh.md b/docs/api/layer/point_layer/cluster.zh.md index 014d341e42..77d22310c5 100644 --- a/docs/api/layer/point_layer/cluster.zh.md +++ b/docs/api/layer/point_layer/cluster.zh.md @@ -73,6 +73,13 @@ const pointLayer = new PointLayer({}) strokeWidth: 1, }); ``` +[聚合图使用案例](../../../examples/point/cluster) + +### FAQ +PointLayer的聚合图采用WebGL绘制,不支持自定义具体聚合样式,如果有自定义的需求可以使用MarkerLayer的聚合功能,你可以通过Dom完全自定义样式。 + +[MarkerLayer聚合](../../component/markerLayer) + diff --git a/docs/api/source/source.en.md b/docs/api/source/source.en.md index 23d82db659..8ee985718b 100644 --- a/docs/api/source/source.en.md +++ b/docs/api/source/source.en.md @@ -7,6 +7,13 @@ order: 0 source 地理数据处理模块,主要包含数据解析(parser),和数据处理(transform); +- data +- option + - cluster **boolean** 是否聚合 + - clusterOption 聚合配置项 + - parser 数据解析配置 + - transforms 数据处理配置 + ### parser 不同数据类型处理成统一数据格式。矢量数据包括 GeoJON, CSV,Json 等不同数据格式,栅格数据,包括 Raster,Image 数据。将来还会支持瓦片格式数据。 @@ -23,6 +30,14 @@ source 地理数据处理模块,主要包含数据解析(parser),和数据 ## API +### cluster `boolean` 可选 可以只设置 + +### clusterOption 可选 + +- radius 聚合半径 **number** default 40 +- minZoom: 最小聚合缩放等级 **number** default 0 +- maxZoom: 最大聚合缩放等级 **number** default 16 + ### parser **配置项** @@ -38,6 +53,17 @@ source 地理数据处理模块,主要包含数据解析(parser),和数据 layer.source(data); ``` +### Source 更新 + +如果数据发生改变,可以需要更新数据 +可以通过调用 layer 的 setData 方法实现数据的更新 + +具体见 [Layer](../layer/layer/#setdata) + +```javascript +layer.setData(data); +``` + #### JSON [JSON 数据格式解析](./json) @@ -54,6 +80,23 @@ layer.source(data); ### transforms +tranforms 处理的是的标准化之后的数据 +标准化之后的数据结构包括 coordinates 地理坐标字段,以及其他属性字段。 + +处理完之后返回的也是标准数据 + +```json +[ + { + "coordinates": [[]], // 地理坐标字段 + "_id": "122", // 标准化之后新增字段 + "name": "test", + "value": 1 + // .... + } +] +``` + 目前支持两种热力图使用的数据处理方法 grid,hexagon transform 配置项 - type 数据处理类型 diff --git a/docs/api/source/source.zh.md b/docs/api/source/source.zh.md index 0fa935b026..306d1242b6 100644 --- a/docs/api/source/source.zh.md +++ b/docs/api/source/source.zh.md @@ -30,7 +30,7 @@ source 地理数据处理模块,主要包含数据解析(parser),和数据 ## API -### cluster ``boolean` 可选 可以只设置 +### cluster `boolean` 可选 可以只设置 ### clusterOption 可选 @@ -38,6 +38,8 @@ source 地理数据处理模块,主要包含数据解析(parser),和数据 - minZoom: 最小聚合缩放等级 **number** default 0 - maxZoom: 最大聚合缩放等级 **number** default 16 +[聚合图使用案例](../../../examples/point/cluster) + ### parser **配置项** diff --git a/packages/component/src/marker.ts b/packages/component/src/marker.ts index 5b1a8fca83..50fac01e2f 100644 --- a/packages/component/src/marker.ts +++ b/packages/component/src/marker.ts @@ -20,6 +20,7 @@ export default class Marker extends EventEmitter { private mapsService: IMapService; private lngLat: ILngLat; private scene: Container; + private added: boolean = false; constructor(option?: Partial) { super(); this.markerOption = { @@ -49,6 +50,8 @@ export default class Marker extends EventEmitter { this.registerMarkerEvent(element as HTMLElement); this.mapsService.on('camerachange', this.update); this.update(); + this.added = true; + this.emit('added'); return this; } @@ -97,6 +100,55 @@ export default class Marker extends EventEmitter { return this.markerOption.element as HTMLElement; } + public setElement(el: HTMLElement): this { + if (!this.added) { + this.once('added', () => { + this.setElement(el); + }); + return this; + } + const { element } = this.markerOption; + if (element) { + DOM.remove(element); + } + this.markerOption.element = el; + this.init(); + this.mapsService.getMarkerContainer().appendChild(el as HTMLElement); + this.registerMarkerEvent(el as HTMLElement); + this.update(); + return this; + } + + public openPopup(): this { + if (!this.added) { + this.once('added', () => { + this.openPopup(); + }); + return this; + } + const popup = this.popup; + if (!popup) { + return this; + } + if (!popup.isOpen()) { + popup.addTo(this.scene); + } + return this; + } + + public closePopup(): this { + if (!this.added) { + this.once('added', () => { + this.closePopup(); + }); + } + const popup = this.popup; + if (popup) { + popup.remove(); + } + return this; + } + public setPopup(popup: IPopup) { this.popup = popup; if (this.lngLat) { diff --git a/packages/component/src/popup.ts b/packages/component/src/popup.ts index 76fee84a81..e9b217b8b5 100644 --- a/packages/component/src/popup.ts +++ b/packages/component/src/popup.ts @@ -23,6 +23,7 @@ export default class Popup extends EventEmitter implements IPopup { private timeoutInstance: any; private container: HTMLElement; private tip: HTMLElement; + private scene: Container; constructor(cfg?: Partial) { super(); @@ -36,6 +37,7 @@ export default class Popup extends EventEmitter implements IPopup { public addTo(scene: Container) { this.mapsService = scene.get(TYPES.IMapService); this.mapsService.on('camerachange', this.update); + this.scene = scene; this.update(); if (this.popupOption.closeOnClick) { this.timeoutInstance = setTimeout(() => { @@ -45,6 +47,14 @@ export default class Popup extends EventEmitter implements IPopup { return this; } + public close(): void { + this.remove(); + } + + public open(): void { + this.addTo(this.scene); + } + public setHTML(html: string) { const frag = window.document.createDocumentFragment(); const temp = window.document.createElement('body'); diff --git a/packages/core/src/services/component/IMarkerService.ts b/packages/core/src/services/component/IMarkerService.ts index c0a3e097db..c017969259 100644 --- a/packages/core/src/services/component/IMarkerService.ts +++ b/packages/core/src/services/component/IMarkerService.ts @@ -19,6 +19,9 @@ export interface IMarker { setExtData(data: any): void; setPopup(popup: IPopup): void; togglePopup(): this; + openPopup(): this; + closePopup(): this; + setElement(el: HTMLElement): this; } export interface IMarkerService { container: HTMLElement; diff --git a/packages/core/src/services/component/IPopupService.ts b/packages/core/src/services/component/IPopupService.ts index d0f208099c..a5521ae8ed 100644 --- a/packages/core/src/services/component/IPopupService.ts +++ b/packages/core/src/services/component/IPopupService.ts @@ -10,6 +10,8 @@ export interface IPopup { setText(text: string): this; setMaxWidth(maxWidth: string): this; isOpen(): boolean; + open(): void; + close(): void; } export interface IPopupService { addPopup(popup: IPopup): void; diff --git a/packages/layers/src/point/models/image.ts b/packages/layers/src/point/models/image.ts index 6d26b6eb27..c0a4948d3a 100644 --- a/packages/layers/src/point/models/image.ts +++ b/packages/layers/src/point/models/image.ts @@ -106,6 +106,8 @@ export default class ImageModel extends BaseModel { const { createTexture2D } = this.rendererService; this.texture = createTexture2D({ data: this.iconService.getCanvas(), + mag: gl.LINEAR, + min: gl.LINEAR, width: 1024, height: this.iconService.canvasHeight || 128, }); diff --git a/packages/layers/src/point/shaders/image_frag.glsl b/packages/layers/src/point/shaders/image_frag.glsl index 58992a075f..258655d32e 100644 --- a/packages/layers/src/point/shaders/image_frag.glsl +++ b/packages/layers/src/point/shaders/image_frag.glsl @@ -9,6 +9,7 @@ uniform float u_stroke_opacity : 1; uniform float u_opacity : 1; varying float v_size; +#pragma include "picking" void main(){ vec2 pos= v_uv / u_textSize + gl_PointCoord / u_textSize * 64.; vec2 fragmentPosition = 2.0*gl_PointCoord - 1.0; @@ -24,5 +25,5 @@ float r = 1.0 - smoothstep(radius-(radius*0.01), }else { gl_FragColor= step(0.01, textureColor.x) * v_color; } - return; + gl_FragColor = filterColor(gl_FragColor); } diff --git a/packages/layers/src/point/shaders/image_vert.glsl b/packages/layers/src/point/shaders/image_vert.glsl index 7aa6a25aa7..f8f7356d7f 100644 --- a/packages/layers/src/point/shaders/image_vert.glsl +++ b/packages/layers/src/point/shaders/image_vert.glsl @@ -11,6 +11,7 @@ uniform float u_stroke_width : 1; varying float v_size; #pragma include "projection" +#pragma include "picking" void main() { v_color = a_Color; @@ -20,5 +21,6 @@ void main() { gl_Position = project_common_position_to_clipspace(vec4(project_pos.xyz, 1.0)); gl_PointSize = a_Size * 2.0 * u_DevicePixelRatio; + setPickingColor(a_PickingColor); } diff --git a/packages/layers/src/point/shaders/text_frag.glsl b/packages/layers/src/point/shaders/text_frag.glsl index 11b8520478..d118777f7e 100644 --- a/packages/layers/src/point/shaders/text_frag.glsl +++ b/packages/layers/src/point/shaders/text_frag.glsl @@ -13,6 +13,7 @@ varying vec4 v_color; varying vec2 v_uv; varying float v_gamma_scale; +#pragma include "picking" void main() { // get sdf from atlas float dist = texture2D(u_sdf_map, v_uv).a; @@ -27,4 +28,5 @@ void main() { highp float alpha = smoothstep(buff - gamma_scaled, buff + gamma_scaled, dist); gl_FragColor = mix(v_color * u_opacity, u_stroke, smoothstep(0., 0.5, 1. - dist)) * alpha; + gl_FragColor = filterColor(gl_FragColor); } diff --git a/packages/layers/src/point/shaders/text_vert.glsl b/packages/layers/src/point/shaders/text_vert.glsl index 268c31c124..09b5da654b 100644 --- a/packages/layers/src/point/shaders/text_vert.glsl +++ b/packages/layers/src/point/shaders/text_vert.glsl @@ -14,6 +14,7 @@ varying float v_gamma_scale; varying vec4 v_color; #pragma include "projection" +#pragma include "picking" void main() { v_color = a_Color; @@ -29,6 +30,6 @@ void main() { gl_Position = vec4(projected_position.xy / projected_position.w + a_textOffsets * fontScale / u_ViewportSize * 2. * u_DevicePixelRatio, 0.0, 1.0); v_gamma_scale = gl_Position.w; - + setPickingColor(a_PickingColor); } diff --git a/packages/utils/src/dom.ts b/packages/utils/src/dom.ts index 65a0540393..e6788f52c7 100644 --- a/packages/utils/src/dom.ts +++ b/packages/utils/src/dom.ts @@ -142,3 +142,13 @@ export function triggerResize() { window.dispatchEvent(evt); } } + +export function printCanvas(canvas: HTMLCanvasElement) { + const css = [ + 'padding: ' + (canvas.height / 2 - 8) + 'px ' + canvas.width / 2 + 'px;', + 'line-height: ' + canvas.height + 'px;', + 'background-image: url(' + canvas.toDataURL() + ');', + ]; + // tslint:disable-next-line:no-console + console.log('%c\n', css.join('')); +} diff --git a/stories/Components/components/Marker.tsx b/stories/Components/components/Marker.tsx index 48716491ac..bfeeaca8f7 100644 --- a/stories/Components/components/Marker.tsx +++ b/stories/Components/components/Marker.tsx @@ -1,5 +1,5 @@ // @ts-ignore -import { Marker, PointLayer, PolygonLayer, Scene } from '@antv/l7'; +import { Marker, PointLayer, PolygonLayer, Popup, Scene } from '@antv/l7'; import { GaodeMap, Mapbox } from '@antv/l7-maps'; import * as React from 'react'; @@ -26,10 +26,22 @@ export default class MarkerComponent extends React.Component { }); this.scene = scene; - const marker = new Marker().setLnglat({ - lng: 120.184824, - lat: 30.248341, - }); + const popup = new Popup({ + offsets: [0, 20], + }).setText('hello'); + + const marker = new Marker() + .setLnglat({ + lng: 120.184824, + lat: 30.248341, + }) + .setPopup(popup); + + scene.addMarker(marker); + + const el = document.createElement('h1'); + el.innerHTML = 'Marker'; + marker.setElement(el); const arr = [ { @@ -54,6 +66,7 @@ export default class MarkerComponent extends React.Component { .style({ opacity: 1, }); + scene.addLayer(pointLayer); scene.addMarker(marker); diff --git a/stories/Layers/components/PointImage.tsx b/stories/Layers/components/PointImage.tsx index a5241d1e6b..a6db650ed9 100644 --- a/stories/Layers/components/PointImage.tsx +++ b/stories/Layers/components/PointImage.tsx @@ -47,6 +47,9 @@ export default class PointImage extends React.Component { .shape('name', ['00', '01', '02']) .size(30); scene.addLayer(imageLayer); + imageLayer.on('click', (e) => { + console.log(e); + }); } public render() { diff --git a/stories/Layers/components/Text.tsx b/stories/Layers/components/Text.tsx index b057f9cf74..14868ababa 100644 --- a/stories/Layers/components/Text.tsx +++ b/stories/Layers/components/Text.tsx @@ -53,6 +53,9 @@ export default class TextLayerDemo extends React.Component { // strokeOpacity: 1.0, }); scene.addLayer(pointLayer); + pointLayer.on('click', (e) => { + console.log(e); + }); this.scene = scene; diff --git a/stories/MapAdaptor/components/multiMaptest.tsx b/stories/MapAdaptor/components/multiMaptest.tsx index 04220e3630..b95cf7afdf 100644 --- a/stories/MapAdaptor/components/multiMaptest.tsx +++ b/stories/MapAdaptor/components/multiMaptest.tsx @@ -2,8 +2,6 @@ import { PointLayer, Scene } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; import * as React from 'react'; -// import imageIcon from './image/icon.svg'; - export default class MultiGaodeMap extends React.Component { private scene1: Scene; private scene2: Scene;