diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 288b9ab..2e0dbf5 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -13,3 +13,16 @@ *= require_tree . *= require_self */ + +html, +body { + margin: 0; + height: 100%; +} + +.map { + position: absolute; + top: 0; + bottom: 0; + width: 100%; +} diff --git a/app/controllers/map_styles_controller.rb b/app/controllers/map_styles_controller.rb new file mode 100644 index 0000000..9156991 --- /dev/null +++ b/app/controllers/map_styles_controller.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +class MapStylesController < ApplicationController; end diff --git a/app/controllers/maps_controller.rb b/app/controllers/maps_controller.rb new file mode 100644 index 0000000..f56c758 --- /dev/null +++ b/app/controllers/maps_controller.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +class MapsController < ApplicationController; end diff --git a/app/controllers/tiles_controller.rb b/app/controllers/tiles_controller.rb new file mode 100644 index 0000000..f3854c4 --- /dev/null +++ b/app/controllers/tiles_controller.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class TilesController < ApplicationController + def show + zoom, x, y = params.values_at(:zoom, :x, :y).map(&:to_i) + + respond_to do |format| + format.mvt do + send_data(Municipality.as_mvt_for(zoom:, x:, y:)) + end + end + end +end diff --git a/app/javascript/controllers/hello_controller.js b/app/javascript/controllers/hello_controller.js deleted file mode 100644 index 5975c07..0000000 --- a/app/javascript/controllers/hello_controller.js +++ /dev/null @@ -1,7 +0,0 @@ -import { Controller } from "@hotwired/stimulus" - -export default class extends Controller { - connect() { - this.element.textContent = "Hello World!" - } -} diff --git a/app/javascript/controllers/map_controller.js b/app/javascript/controllers/map_controller.js new file mode 100644 index 0000000..e913ea0 --- /dev/null +++ b/app/javascript/controllers/map_controller.js @@ -0,0 +1,16 @@ +import { Controller } from "@hotwired/stimulus" +import { apply } from "ol-mapbox-style" + +export default class extends Controller { + static values = { url: String } + + connect() { + apply(this.element, this.urlValue) + .then((value) => { this.map = value }) + } + + disconnect() { + this.map.setTarget(null) + this.map = null + } +} diff --git a/app/models/municipality.rb b/app/models/municipality.rb index 7a266ed..344f8f8 100644 --- a/app/models/municipality.rb +++ b/app/models/municipality.rb @@ -5,8 +5,8 @@ class Municipality < ApplicationRecord def self.as_mvt_for(zoom:, x:, y:) relation = joins(:municipality_areas) - .merge(MunicipalityArea.as_mvt_geom_for(zoom:, x:, y:)) - .select(:id, :name) + .merge(MunicipalityArea.as_mvt_geom_for(zoom:, x:, y:)) + .select(:id, :name) all.unscoped.from(relation, :mvtgeom).select('ST_AsMVT(mvtgeom.*) mvt').take.mvt end diff --git a/app/models/municipality_area.rb b/app/models/municipality_area.rb index 9693833..85c7c54 100644 --- a/app/models/municipality_area.rb +++ b/app/models/municipality_area.rb @@ -8,10 +8,10 @@ def self.for_map_tile(zoom:, x:, y:) end def self.as_mvt_geom_for(zoom:, x:, y:) - sql = sanitize_sql_array([ - "ST_AsMVTGeom(area, ST_TileEnvelope(:zoom, :x, :y)) AS geom", - zoom:, x:, y:, - ]) + sql = sanitize_sql_array( + ['ST_AsMVTGeom(area, ST_TileEnvelope(:zoom, :x, :y)) AS geom', + { zoom:, x:, y: }] + ) for_map_tile(zoom:, x:, y:).select(sql) end diff --git a/app/views/map_styles/show.json.jbuilder b/app/views/map_styles/show.json.jbuilder new file mode 100644 index 0000000..61bdb6d --- /dev/null +++ b/app/views/map_styles/show.json.jbuilder @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +json.version 8 + +json.center [130.399994, 33.583332] # Fukuoka + +json.zoom 12 + +json.sources do + json.map do + json.type 'vector' + json.tiles [tile_url('{z}', '{x}', '{y}', format: :mvt)] + end +end + +json.layers do + json.child! do + json.id 'municipality-label' + json.type 'symbol' + json.source 'map' + json.set! 'source-layer', 'default' + json.layout do + json.set! 'text-field', %w[get name] + json.set! 'symbol-placement', 'line-center' + end + end + + json.child! do + json.id 'municipality-outline' + json.type 'line' + json.source 'map' + json.set! 'source-layer', 'default' + json.paint do + json.set! 'line-color', '#3EA5F5' + json.set! 'line-width', 3 + end + end +end diff --git a/app/views/maps/show.html.erb b/app/views/maps/show.html.erb new file mode 100644 index 0000000..36117a5 --- /dev/null +++ b/app/views/maps/show.html.erb @@ -0,0 +1,2 @@ +
+
diff --git a/config/importmap.rb b/config/importmap.rb index b57e7be..002a9fe 100644 --- a/config/importmap.rb +++ b/config/importmap.rb @@ -7,3 +7,8 @@ pin '@hotwired/stimulus', to: 'stimulus.min.js', preload: true pin '@hotwired/stimulus-loading', to: 'stimulus-loading.js', preload: true pin_all_from 'app/javascript/controllers', under: 'controllers' +pin 'ol-mapbox-style', to: 'https://ga.jspm.io/npm:ol-mapbox-style@9.5.0/dist/index.js' +pin 'ieee754', to: 'https://ga.jspm.io/npm:ieee754@1.2.1/index.js' +pin 'ol/', to: 'https://ga.jspm.io/npm:ol@7.2.2/' +pin 'pbf', to: 'https://ga.jspm.io/npm:pbf@3.2.1/index.js' +pin 'rbush', to: 'https://ga.jspm.io/npm:rbush@3.0.1/rbush.min.js' diff --git a/config/initializers/types.rb b/config/initializers/types.rb new file mode 100644 index 0000000..4ea309c --- /dev/null +++ b/config/initializers/types.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +Mime::Type.register 'application/vnd.mapbox-vector-tile', :mvt diff --git a/config/routes.rb b/config/routes.rb index 7b329f5..a6817f5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true Rails.application.routes.draw do - # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html + get 'tiles/:zoom/:x/:y', to: 'tiles#show', as: :tile + resource :map_style, only: :show - # Defines the root path route ("/") - # root "articles#index" + root 'maps#show' end