Skip to content

Commit

Permalink
Map resources and JavaScript map client
Browse files Browse the repository at this point in the history
To display a map of the Japanese municipalities, two resources are
needed:
1. The vector tile endpoint to stream the binary vector tiles.
2. A Mapbox Style endpoint to tell the map client how to render the
   vector data.

The JavaScript client can now render this map with the style URL without
further design configuration.
  • Loading branch information
arkirchner committed Feb 17, 2023
1 parent 4efa05d commit f481ac1
Show file tree
Hide file tree
Showing 13 changed files with 105 additions and 16 deletions.
13 changes: 13 additions & 0 deletions app/assets/stylesheets/application.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,16 @@
*= require_tree .
*= require_self
*/

html,
body {
margin: 0;
height: 100%;
}

.map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
3 changes: 3 additions & 0 deletions app/controllers/map_styles_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: true

class MapStylesController < ApplicationController; end
3 changes: 3 additions & 0 deletions app/controllers/maps_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: true

class MapsController < ApplicationController; end
13 changes: 13 additions & 0 deletions app/controllers/tiles_controller.rb
Original file line number Diff line number Diff line change
@@ -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
7 changes: 0 additions & 7 deletions app/javascript/controllers/hello_controller.js

This file was deleted.

16 changes: 16 additions & 0 deletions app/javascript/controllers/map_controller.js
Original file line number Diff line number Diff line change
@@ -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
}
}
4 changes: 2 additions & 2 deletions app/models/municipality.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions app/models/municipality_area.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
38 changes: 38 additions & 0 deletions app/views/map_styles/show.json.jbuilder
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions app/views/maps/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<div class='map' data-controller="map" data-map-url-value="<%= map_style_url(format: :json) -%>">
</div>
5 changes: 5 additions & 0 deletions config/importmap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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:[email protected]/dist/index.js'
pin 'ieee754', to: 'https://ga.jspm.io/npm:[email protected]/index.js'
pin 'ol/', to: 'https://ga.jspm.io/npm:[email protected]/'
pin 'pbf', to: 'https://ga.jspm.io/npm:[email protected]/index.js'
pin 'rbush', to: 'https://ga.jspm.io/npm:[email protected]/rbush.min.js'
3 changes: 3 additions & 0 deletions config/initializers/types.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: true

Mime::Type.register 'application/vnd.mapbox-vector-tile', :mvt
6 changes: 3 additions & 3 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit f481ac1

Please sign in to comment.