|
25 | 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 | 26 | * POSSIBILITY OF SUCH DAMAGE. |
27 | 27 | */ |
28 | | -import Visualization from 'zeppelin-vis' |
29 | | -import ColumnselectorTransformation from 'zeppelin-tabledata/columnselector' |
| 28 | +import Visualization from 'zeppelin-vis'; |
| 29 | +import ColumnselectorTransformation from 'zeppelin-tabledata/columnselector'; |
30 | 30 |
|
31 | | - |
32 | | -import L from 'leaflet/dist/leaflet' |
33 | | -import 'leaflet/dist/leaflet.css' |
| 31 | +import L from 'leaflet/dist/leaflet'; |
| 32 | +import 'leaflet/dist/leaflet.css'; |
34 | 33 | // workaround https://github.com/Leaflet/Leaflet/issues/4968 |
35 | 34 | import icon from 'leaflet/dist/images/marker-icon.png'; |
36 | 35 | import iconShadow from 'leaflet/dist/images/marker-shadow.png'; |
37 | 36 |
|
38 | 37 | let DefaultIcon = L.icon({ |
39 | | - iconUrl: icon, |
40 | | - iconSize: [25, 41], |
41 | | - iconAnchor: [12, 41], |
42 | | - popupAnchor: [0, -41], |
43 | | - tooltipAnchor: [12, -28], |
44 | | - shadowUrl: iconShadow |
| 38 | + iconUrl: icon, |
| 39 | + iconSize: [25, 41], |
| 40 | + iconAnchor: [12, 41], |
| 41 | + popupAnchor: [0, -41], |
| 42 | + tooltipAnchor: [12, -28], |
| 43 | + shadowUrl: iconShadow, |
45 | 44 | }); |
46 | 45 | L.Marker.prototype.options.icon = DefaultIcon; |
47 | 46 |
|
48 | 47 | export default class LeafletMap extends Visualization { |
49 | | - |
50 | | - constructor(targetEl, config) { |
51 | | - super(targetEl, config); |
52 | | - |
53 | | - const columnSpec = [ |
54 | | - {name: 'mapimage'}, |
55 | | - {name: 'geometry'}, |
56 | | - {name: 'info'} |
57 | | - ]; |
58 | | - |
59 | | - this.transformation = new ColumnselectorTransformation(config, columnSpec); |
60 | | - this.chartInstance = this.createMap(); |
61 | | - } |
62 | | - |
63 | | - getTransformation() { |
64 | | - return this.transformation; |
65 | | - } |
66 | | - |
67 | | - showChart() { |
68 | | - super.setConfig(config); |
69 | | - this.transformation.setConfig(config); |
70 | | - if (!this.chartInstance) { |
71 | | - this.chartInstance = this.createMap(); |
72 | | - } |
73 | | - return this.chartInstance; |
74 | | - }; |
75 | | - |
76 | | - createMap() { |
77 | | - // using canvas renderer to support drawing geometry like LineString, Polygon etc. |
78 | | - return L.map(this.getChartElementId(), {renderer: L.canvas()}); |
79 | | - } |
80 | | - |
81 | | - getChartElementId() { |
82 | | - return this.targetEl[0].id |
83 | | - }; |
84 | | - |
85 | | - getChartElement() { |
86 | | - return document.getElementById(this.getChartElementId()); |
87 | | - }; |
88 | | - |
89 | | - clearChart() { |
90 | | - if (this.chartInstance) { |
91 | | - this.chartInstance.off(); |
92 | | - this.chartInstance.remove(); |
93 | | - this.chartInstance = null; |
94 | | - } |
95 | | - }; |
96 | | - |
97 | | - showError(error) { |
98 | | - this.clearChart(); |
99 | | - this.getChartElement().innerHTML = ` |
| 48 | + constructor(targetEl, config) { |
| 49 | + super(targetEl, config); |
| 50 | + |
| 51 | + const columnSpec = [{name: 'mapimage'}, {name: 'geometry'}, {name: 'info'}]; |
| 52 | + |
| 53 | + this.transformation = new ColumnselectorTransformation(config, columnSpec); |
| 54 | + this.chartInstance = this.createMap(); |
| 55 | + } |
| 56 | + |
| 57 | + getTransformation() { |
| 58 | + return this.transformation; |
| 59 | + } |
| 60 | + |
| 61 | + showChart() { |
| 62 | + super.setConfig(config); |
| 63 | + this.transformation.setConfig(config); |
| 64 | + if (!this.chartInstance) { |
| 65 | + this.chartInstance = this.createMap(); |
| 66 | + } |
| 67 | + return this.chartInstance; |
| 68 | + } |
| 69 | + |
| 70 | + createMap() { |
| 71 | + // using canvas renderer to support drawing geometry like LineString, Polygon etc. |
| 72 | + return L.map(this.getChartElementId(), {renderer: L.canvas()}); |
| 73 | + } |
| 74 | + |
| 75 | + getChartElementId() { |
| 76 | + return this.targetEl[0].id; |
| 77 | + } |
| 78 | + |
| 79 | + getChartElement() { |
| 80 | + return document.getElementById(this.getChartElementId()); |
| 81 | + } |
| 82 | + |
| 83 | + clearChart() { |
| 84 | + if (this.chartInstance) { |
| 85 | + this.chartInstance.off(); |
| 86 | + this.chartInstance.remove(); |
| 87 | + this.chartInstance = null; |
| 88 | + } |
| 89 | + } |
| 90 | + |
| 91 | + showError(error) { |
| 92 | + this.clearChart(); |
| 93 | + this.getChartElement().innerHTML = ` |
100 | 94 | <div style="margin-top: 60px; text-align: center; font-weight: 100"> |
101 | 95 | <span style="font-size:30px;"> |
102 | 96 | ${error.message} |
103 | 97 | </span> |
104 | | - </div>` |
105 | | - } |
106 | | - |
107 | | - drawMapChart(chartDataModel) { |
108 | | - const map = this.showChart(); |
109 | | - L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { |
110 | | - attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' |
111 | | - }).addTo(map); |
112 | | - |
113 | | - this.getChartElement().style.height = this.targetEl.height(); |
114 | | - map.invalidateSize(true) |
115 | | - |
116 | | - var imageBounds = null |
117 | | - const markers = chartDataModel.rows.flatMap( |
118 | | - row => { |
119 | | - const {image, boundary, info} = row; |
120 | | - var markers = []; |
121 | | - |
122 | | - // throw new Error(image); |
123 | | - var jsts = require("jsts"); |
124 | | - // Read WKT string from Sedona |
125 | | - var reader = new jsts.io.WKTReader(); |
126 | | - var obj = reader.read(boundary); |
127 | | - // Collect the centroid point of the input geometry |
128 | | - var centroid = obj.getCentroid() |
129 | | - var marker = L.marker([centroid.getY(), centroid.getX()]); |
130 | | - const mapMarker = marker.addTo(map); |
131 | | - markers.push(marker); |
132 | | - |
133 | | - if (obj.getGeometryType() !== 'Point') { |
134 | | - var writer = new jsts.io.GeoJSONWriter(); |
135 | | - var geojson = writer.write(obj); |
136 | | - marker = L.geoJSON(geojson); |
137 | | - marker.addTo(map); |
138 | | - markers.push(marker); |
139 | | - } |
140 | | - |
141 | | - // Attach the marker information if exists |
142 | | - if(info){ |
143 | | - mapMarker.bindTooltip(info); |
144 | | - } |
145 | | - // Overlay the generated image over the tile layer |
146 | | - if (image) { |
147 | | - var envelope = obj.getEnvelopeInternal() |
148 | | - // Read the boundary of the map viewport |
149 | | - imageBounds = [[envelope.getMinY(), envelope.getMinX()], [envelope.getMaxY(), envelope.getMaxX()]] |
150 | | - var imageUrl = 'data:image/png;base64,' + image; |
151 | | - L.imageOverlay(imageUrl, imageBounds).addTo(map); |
152 | | - } |
153 | | - return markers; |
154 | | - } |
155 | | - ); |
156 | | - // Adjust the location of the viewport |
157 | | - // If imageBounds was initialized, use imageBounds instead |
158 | | - var bounds = null |
159 | | - if (imageBounds) { |
160 | | - bounds = imageBounds; |
161 | | - } |
162 | | - else { |
163 | | - let featureGroup = L.featureGroup(markers); |
164 | | - bounds = featureGroup.getBounds().pad(0.5); |
165 | | - } |
166 | | - // throw new Error(featureGroup.getBounds().pad(0.5).toString()) |
167 | | - map.fitBounds(bounds); |
168 | | - |
169 | | - }; |
170 | | - |
171 | | - createMapDataModel(data) { |
172 | | - const getColumnIndex = (config, fieldName, isOptional) => { |
173 | | - const fieldConf = config[fieldName]; |
174 | | - if (fieldConf instanceof Object) { |
175 | | - return fieldConf.index |
176 | | - } |
177 | | - else if (isOptional) { |
178 | | - return -1 |
179 | | - } |
180 | | - else { |
181 | | - throw { |
182 | | - message: "Please set " + fieldName + " in Settings" |
183 | | - } |
184 | | - } |
185 | | - }; |
186 | | - |
187 | | - const config = this.getTransformation().config; |
188 | | - const imageIdx = getColumnIndex(config, 'mapimage', true); |
189 | | - const boundaryIdx = getColumnIndex(config, 'geometry'); |
190 | | - const infoIdx = getColumnIndex(config, 'info', true); |
191 | | - const rows = data.rows.map(tableRow => { |
192 | | - const image = imageIdx < 0 ? null : tableRow[imageIdx]; |
193 | | - const boundary = tableRow[boundaryIdx]; |
194 | | - const info = infoIdx < 0 ? null : tableRow[infoIdx]; |
195 | | - return { |
196 | | - image, boundary, info |
197 | | - }; |
198 | | - }); |
199 | | - |
200 | | - return { |
201 | | - rows |
202 | | - }; |
203 | | - } |
204 | | - |
205 | | - render(data) { |
206 | | - try { |
207 | | - const mapDataModel = this.createMapDataModel(data); |
208 | | - this.clearChart(); |
209 | | - this.drawMapChart(mapDataModel) |
210 | | - } |
211 | | - catch (error) { |
212 | | - console.error(error); |
213 | | - this.showError(error) |
214 | | - } |
215 | | - } |
| 98 | + </div>`; |
| 99 | + } |
| 100 | + |
| 101 | + drawMapChart(chartDataModel) { |
| 102 | + const map = this.showChart(); |
| 103 | + L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { |
| 104 | + attribution: |
| 105 | + '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors', |
| 106 | + }).addTo(map); |
| 107 | + |
| 108 | + this.getChartElement().style.height = this.targetEl.height(); |
| 109 | + map.invalidateSize(true); |
| 110 | + |
| 111 | + var imageBounds = null; |
| 112 | + const markers = chartDataModel.rows.flatMap((row) => { |
| 113 | + const {image, boundary, info} = row; |
| 114 | + var markers = []; |
| 115 | + |
| 116 | + // throw new Error(image); |
| 117 | + var jsts = require('jsts'); |
| 118 | + // Read WKT string from Sedona |
| 119 | + var reader = new jsts.io.WKTReader(); |
| 120 | + var obj = reader.read(boundary); |
| 121 | + // Collect the centroid point of the input geometry |
| 122 | + var centroid = obj.getCentroid(); |
| 123 | + var marker = L.marker([centroid.getY(), centroid.getX()]); |
| 124 | + const mapMarker = marker.addTo(map); |
| 125 | + markers.push(marker); |
| 126 | + |
| 127 | + if (obj.getGeometryType() !== 'Point') { |
| 128 | + var writer = new jsts.io.GeoJSONWriter(); |
| 129 | + var geojson = writer.write(obj); |
| 130 | + marker = L.geoJSON(geojson); |
| 131 | + marker.addTo(map); |
| 132 | + markers.push(marker); |
| 133 | + } |
| 134 | + |
| 135 | + // Attach the marker information if exists |
| 136 | + if (info) { |
| 137 | + mapMarker.bindTooltip(info); |
| 138 | + } |
| 139 | + // Overlay the generated image over the tile layer |
| 140 | + if (image) { |
| 141 | + var envelope = obj.getEnvelopeInternal(); |
| 142 | + // Read the boundary of the map viewport |
| 143 | + imageBounds = [ |
| 144 | + [envelope.getMinY(), envelope.getMinX()], |
| 145 | + [envelope.getMaxY(), envelope.getMaxX()], |
| 146 | + ]; |
| 147 | + var imageUrl = 'data:image/png;base64,' + image; |
| 148 | + L.imageOverlay(imageUrl, imageBounds).addTo(map); |
| 149 | + } |
| 150 | + return markers; |
| 151 | + }); |
| 152 | + // Adjust the location of the viewport |
| 153 | + // If imageBounds was initialized, use imageBounds instead |
| 154 | + var bounds = null; |
| 155 | + if (imageBounds) { |
| 156 | + bounds = imageBounds; |
| 157 | + } else { |
| 158 | + let featureGroup = L.featureGroup(markers); |
| 159 | + bounds = featureGroup.getBounds().pad(0.5); |
| 160 | + } |
| 161 | + // throw new Error(featureGroup.getBounds().pad(0.5).toString()) |
| 162 | + map.fitBounds(bounds); |
| 163 | + } |
| 164 | + |
| 165 | + createMapDataModel(data) { |
| 166 | + const getColumnIndex = (config, fieldName, isOptional) => { |
| 167 | + const fieldConf = config[fieldName]; |
| 168 | + if (fieldConf instanceof Object) { |
| 169 | + return fieldConf.index; |
| 170 | + } else if (isOptional) { |
| 171 | + return -1; |
| 172 | + } else { |
| 173 | + throw { |
| 174 | + message: 'Please set ' + fieldName + ' in Settings', |
| 175 | + }; |
| 176 | + } |
| 177 | + }; |
| 178 | + |
| 179 | + const config = this.getTransformation().config; |
| 180 | + const imageIdx = getColumnIndex(config, 'mapimage', true); |
| 181 | + const boundaryIdx = getColumnIndex(config, 'geometry'); |
| 182 | + const infoIdx = getColumnIndex(config, 'info', true); |
| 183 | + const rows = data.rows.map((tableRow) => { |
| 184 | + const image = imageIdx < 0 ? null : tableRow[imageIdx]; |
| 185 | + const boundary = tableRow[boundaryIdx]; |
| 186 | + const info = infoIdx < 0 ? null : tableRow[infoIdx]; |
| 187 | + return { |
| 188 | + image, |
| 189 | + boundary, |
| 190 | + info, |
| 191 | + }; |
| 192 | + }); |
| 193 | + |
| 194 | + return { |
| 195 | + rows, |
| 196 | + }; |
| 197 | + } |
| 198 | + |
| 199 | + render(data) { |
| 200 | + try { |
| 201 | + const mapDataModel = this.createMapDataModel(data); |
| 202 | + this.clearChart(); |
| 203 | + this.drawMapChart(mapDataModel); |
| 204 | + } catch (error) { |
| 205 | + console.error(error); |
| 206 | + this.showError(error); |
| 207 | + } |
| 208 | + } |
216 | 209 | } |
0 commit comments