Skip to content

Commit ea098ed

Browse files
authored
Merge pull request #102 from gtt-project/feature/add-overlay-layers
Feature/add overlay layers
2 parents b662d19 + 465be3f commit ea098ed

File tree

8 files changed

+102
-19
lines changed

8 files changed

+102
-19
lines changed

app/controllers/gtt_tile_sources_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def destroy
6161
def tile_source_params
6262
return {} unless params[:tile_source]
6363

64-
params[:tile_source].permit( :name, :type, :global, :position,
64+
params[:tile_source].permit( :name, :type, :baselayer, :global, :position,
6565
:default, :options_string )
6666
end
6767
end

app/views/gtt_tile_sources/_form.html.erb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<div class="box tabular">
55
<p><%= f.text_field :name, required: true, size: 25 %></p>
66
<p><%= f.text_field :type, required: true, size: 25 %></p>
7+
<p><%= f.check_box :baselayer %></p>
78
<p><%= f.check_box :global %></p>
89
<p><%= f.check_box :default %></p>
910
<p> <%= f.text_area :options_string, rows: 10, cols: 80 %> </p>

app/views/gtt_tile_sources/_tile_source.html.erb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<tr class="<%= cycle("odd", "even") %>">
22
<td><%= tile_source.type %></td>
33
<td><%= link_to tile_source.name, edit_gtt_tile_source_path(tile_source) %></td>
4+
<td><%= checked_image tile_source.baselayer? %></td>
45
<td><%= checked_image tile_source.global? %></td>
56
<td><%= checked_image tile_source.default? %></td>
67
<td><%= tile_source_options tile_source %></td>

app/views/gtt_tile_sources/index.html.erb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<tr>
1111
<th><%= l :label_type %></th>
1212
<th><%= l :label_name %></th>
13+
<th><%= l :label_baselayer %></th>
1314
<th><%= l :label_global %></th>
1415
<th><%= l :label_default %></th>
1516
<th><%= l :label_config %></th>

config/locales/en.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ en:
88
field_location: "Location"
99
field_geom: "Geometry"
1010
field_global: Globally available
11+
field_baselayer: BaseLayer
1112
field_options_string: Options
1213
field_gtt_tile_source_ids: Tile Sources
1314

@@ -16,6 +17,7 @@ en:
1617
label_project_map: "Project Map"
1718
label_user_map: "User Map"
1819
label_name: Name
20+
label_baselayer: BaseLayer
1921
label_nearby: "nearby(lat,lng)"
2022
label_type: Type
2123
label_config: Configuration

config/locales/ja.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ ja:
88
field_location: "場所"
99
field_geom: "所在地"
1010
field_global: 世界的に利用可能
11+
field_baselayer: 背景レイヤー
1112
field_options_string: オプション
1213
field_gtt_tile_source_ids: タイルソース
1314

@@ -16,6 +17,7 @@ ja:
1617
label_project_map: "プロジェクト 地図"
1718
label_user_map: "ユーザ 地図"
1819
label_name: タイトル
20+
label_baselayer: 背景レイヤー
1921
label_nearby: "近く(緯度,経度)"
2022
label_type: タイプ
2123
label_config: 構成
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class AddBaselayerToTileSources < ActiveRecord::Migration[5.2]
2+
def change
3+
add_column :gtt_tile_sources, :baselayer, :boolean, default: true
4+
end
5+
end

src/components/gtt-client.ts

Lines changed: 89 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import { Map, Feature, View, Geolocation } from 'ol'
44
import 'ol-ext/filter/Base'
55
import { Geometry, Point } from 'ol/geom'
66
import { GeoJSON, WKT } from 'ol/format'
7-
import { Layer, Tile } from 'ol/layer'
7+
import { Layer, Tile, Image } from 'ol/layer'
88
import VectorLayer from 'ol/layer/Vector'
9-
import { OSM, XYZ } from 'ol/source'
9+
import { OSM, XYZ, TileWMS, ImageWMS } from 'ol/source'
1010
import { Style, Fill, Stroke, Circle } from 'ol/style'
1111
import { OrderFunction } from 'ol/render'
1212
import {
@@ -32,11 +32,15 @@ import Toggle from 'ol-ext/control/Toggle'
3232
import Button from 'ol-ext/control/Button'
3333
import TextButton from 'ol-ext/control/TextButton'
3434
import LayerPopup from 'ol-ext/control/LayerPopup'
35+
import LayerSwitcher from 'ol-ext/control/LayerSwitcher'
3536
import Popup from 'ol-ext/overlay/Popup'
3637
import { position } from 'ol-ext/control/control'
3738
import { ResizeObserver } from '@juggle/resize-observer'
3839
import VectorSource from 'ol/source/Vector'
3940
import { FeatureLike } from 'ol/Feature'
41+
import TileSource from 'ol/source/Tile'
42+
import ImageSource from 'ol/source/Image'
43+
import { Options as ImageWMSOptions } from 'ol/source/ImageWMS'
4044

4145
interface GttClientOption {
4246
target: HTMLDivElement | null
@@ -46,6 +50,7 @@ interface LayerObject {
4650
type: string
4751
id: number
4852
name: string
53+
baselayer: boolean
4954
options: object
5055
}
5156

@@ -54,6 +59,16 @@ interface FilterOption {
5459
distance: boolean
5560
}
5661

62+
interface TileLayerSource {
63+
layer: typeof Tile
64+
source: typeof OSM | typeof XYZ
65+
}
66+
67+
interface ImageLayerSource {
68+
layer: typeof Image
69+
source: typeof ImageWMS
70+
}
71+
5772
export class GttClient {
5873
readonly map: Map
5974
maps: Array<Map>
@@ -146,26 +161,70 @@ export class GttClient {
146161
const layers = JSON.parse(this.contents.layers) as [LayerObject]
147162
layers.forEach((layer) => {
148163
const s = layer.type.split('.')
149-
const tileSource = getTileSource(s[1], s[2])
150-
if (tileSource) {
151-
const l = new Tile({
164+
const layerSource = getLayerSource(s[1], s[2])
165+
const tileLayerSource = layerSource as TileLayerSource
166+
if (tileLayerSource) {
167+
const l = new (tileLayerSource.layer)({
152168
visible: false,
153-
source: new (tileSource)(layer.options)
169+
source: new (tileLayerSource.source)(layer.options)
154170
})
171+
155172
l.set('lid', layer.id)
156173
l.set('title', layer.name)
157-
l.set('baseLayer', true)
158-
l.on('change:visible', e => {
159-
const target = e.target as Tile<XYZ>
160-
if (target.getVisible()) {
161-
const lid = target.get('lid')
162-
document.cookie = `_redmine_gtt_basemap=${lid};path=/`
163-
}
174+
l.set('baseLayer', layer.baselayer)
175+
if( layer.baselayer ) {
176+
l.on('change:visible', e => {
177+
const target = e.target as Tile<TileSource>
178+
if (target.getVisible()) {
179+
const lid = target.get('lid')
180+
document.cookie = `_redmine_gtt_basemap=${lid};path=/`
181+
}
182+
})
183+
}
184+
this.layerArray.push(l)
185+
} else if (layerSource as ImageLayerSource) {
186+
const imageLayerSource = layerSource as ImageLayerSource
187+
const l = new (imageLayerSource.layer)({
188+
visible: false,
189+
source: new (imageLayerSource.source)(layer.options as ImageWMSOptions)
164190
})
191+
192+
l.set('lid', layer.id)
193+
l.set('title', layer.name)
194+
l.set('baseLayer', layer.baselayer)
195+
if( layer.baselayer ) {
196+
l.on('change:visible', e => {
197+
const target = e.target as Image<ImageSource>
198+
if (target.getVisible()) {
199+
const lid = target.get('lid')
200+
document.cookie = `_redmine_gtt_basemap=${lid};path=/`
201+
}
202+
})
203+
}
165204
this.layerArray.push(l)
166-
this.map.addLayer(l)
167205
}
168206
}, this)
207+
208+
/**
209+
* Ordering the Layers for the LayerSwitcher Control.
210+
* BaseLayers are added first.
211+
*/
212+
this.layerArray.forEach( (l:Layer) => {
213+
if( l.get("baseLayer") ) {
214+
this.map.addLayer(l)
215+
}
216+
}
217+
)
218+
219+
var containsOverlay = false;
220+
221+
this.layerArray.forEach( (l:Layer) => {
222+
if( !l.get("baseLayer") ) {
223+
this.map.addLayer(l)
224+
containsOverlay = true
225+
}
226+
}
227+
)
169228
}
170229

171230
this.setBasemap()
@@ -331,7 +390,15 @@ export class GttClient {
331390
})
332391

333392
// Add LayerSwitcher Image Toolbar
334-
this.map.addControl(new LayerPopup())
393+
if( containsOverlay) {
394+
this.map.addControl(new LayerSwitcher({
395+
reordering: false
396+
}))
397+
}
398+
else {
399+
this.map.addControl(new LayerPopup())
400+
}
401+
335402

336403
// Because Redmine filter functions are applied later, the Window onload
337404
// event provides a workaround to have filters loaded before executing
@@ -1194,12 +1261,16 @@ export class GttClient {
11941261
}
11951262
}
11961263

1197-
const getTileSource = (source: string, class_name: string): any => {
1264+
const getLayerSource = (source: string, class_name: string): TileLayerSource | ImageLayerSource | undefined => {
11981265
if (source === 'source') {
11991266
if (class_name === 'OSM') {
1200-
return OSM
1267+
return { layer: Tile, source: OSM }
12011268
} else if (class_name === 'XYZ') {
1202-
return XYZ
1269+
return { layer: Tile, source: XYZ }
1270+
} else if (class_name === 'TileWMS') {
1271+
return { layer: Tile, source: TileWMS }
1272+
} else if (class_name === 'ImageWMS') {
1273+
return { layer: Image, source: ImageWMS }
12031274
}
12041275
}
12051276
return undefined

0 commit comments

Comments
 (0)