Skip to content

Instantly share code, notes, and snippets.

@hitsujixgit
Last active August 29, 2015 14:14
Show Gist options
  • Save hitsujixgit/1562c11d53bcfc2bc92f to your computer and use it in GitHub Desktop.
Save hitsujixgit/1562c11d53bcfc2bc92f to your computer and use it in GitHub Desktop.
横浜市の地図を、人口に応じて色分け表示する
'use strict'
###
* 色を変換する関数を定義する
###
hex2rgb = (hexcode) ->
# rgbに変換する
result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hexcode);
if result is null
console.log "error!"
return
[r,g,b] = [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)]
return [r,g,b]
rgb2hsv = (r,g,b) ->
# rgb to hsv
r = r / 255
g = g / 255
b = b / 255
max_v = Math.max(Math.max(r,g), b)
min_v = Math.min(Math.min(r,g), b)
v = max_v
s = max_v - min_v
if min_v == max_v
h = 0
else if min_v == b
h = 60 * (g-r)/s + 60
else if min_v == r
h = 60 * (b-g)/s + 180
else
h = 60 * (r-b)/s + 300
return [h,s,v]
hsv2rgb = (h,s,v) ->
console.log [h,s,v]
if h is null
r = 0
g = 0
b = 0
else
h_dash = h / 60
x = s * (1 - Math.abs(h_dash % 2 - 1))
if h_dash < 1
[r,g,b] = [s,x,0]
else if h_dash < 2
[r,g,b] = [x,s,0]
else if h_dash < 3
[r,g,b] = [0,s,x]
else if h_dash < 4
[r,g,b] = [0,x,s]
else if h_dash < 5
[r,g,b] = [x,0,s]
else if h_dash < 6
[r,g,b] = [s,0,x]
else
console.log '変換エラー'
return
r += (v-s)
g += (v-s)
b += (v-s)
r *= 255
g *= 255
b *= 255
return [Math.round(r),Math.round(g),Math.round(b)]
readTopoFileDone = false
readAttrFileDone = false
# fileから読み込んだdataの格納変数
topo_data = null
attr_data = null
map_width = 500
map_height = 650
svg = null
###
* JSONファイルを読み込み、地図描画関数mainを呼び出す
###
readTopoFile = (json) ->
topo_data = json
readTopoFileDone = true
readAttrFile = (json) ->
attr_data = json
readAttrFileDone = true
d3.json("yokohama_topo_out.json", (error, json) ->
if error
return console.warn error
readTopoFile(json)
if readTopoFileDone and readAttrFileDone
main(topo_data, attr_data))
d3.json("yokohama_codes_and_stat.json", (error, json) ->
if error
return console.warn(error)
readAttrFile(json)
if readTopoFileDone and readAttrFileDone
main(topo_data, attr_data))
###
* 地図を描画する
###
main = (topo, attr) ->
labelLineHeight = 16
# 属性情報を入れ直すためのHash Table
attrHash = []
# attr情報を、IDをkeyとするhash-tableに変換する
# idをKeyとしたhashテーブル&property毎のhashテーブルを作成する
for e in attr
attrHash[e.cityid]=e
# 人口の最大値と最小値を求めておく
# --全年齢人口データのみを入れた配列を作成する
elements = []
target_key = "ttl"
for e in attr
elements.push(e[target_key])
# -- maxとminをとる
target_max = Math.max.apply(null, elements)
target_min = Math.min.apply(null, elements)
# svgを追加
svg = d3.select("body #map").append("svg").attr("width", map_width).attr("height", map_height)
# 横浜市のmapを描画する
yokohama = topojson.object(topo, topo.objects.yokohama)
# 横浜市を中心に指定したメルカトル図法で10万分の1で描画する
projection = d3.geo.mercator().center([139.59,35.45]).scale(100000).translate([map_width / 2, map_height / 2])
# pathを作成する
path = d3.geo.path().projection(projection)
svg.append("path").datum(yokohama).attr("d", path)
# classを指定する
svg.selectAll(".yokohama").data(yokohama.geometries).enter().append("path").attr("class", (d) ->
return "yokohama " + d.properties.name).attr("d", path)
# 色を塗る
hexcode_max = "#ee0000"
hexcode_min = "#00ee00"
# 念のためあらかじめ塗っておく
svg.selectAll("path").attr("fill", "#bee59e")
# HEXカラーコードからRGBに変換
[r_min,g_min,b_min] = hex2rgb(hexcode_min)
[r_max,g_max,b_max] = hex2rgb(hexcode_max)
# RGB(0-255)からHSVに変換
[h_min,s_min,v_min] = rgb2hsv(r_min,g_min,b_min)
[h_max,s_max,v_max] = rgb2hsv(r_max,g_max,b_max)
areaGrad = d3.scale.linear().domain([target_min, target_max]).range([[h_min,s_min,v_min], [h_max,s_max,v_max]])
for k, v of attrHash
[h,s,v] = areaGrad(attrHash[k][target_key])
[r,g,b] = hsv2rgb(h,s,v)
svg.selectAll("."+k).attr("fill", "rgba(#{r},#{g},#{b},1)")
# 内部境界に線を引く
svg.append("path")
.datum(topojson.mesh(topo, topo.objects.yokohama, (a, b) ->
return a isnt b))
.attr("d", path)
.attr("class", "subunit-boundary")
# 区コードのラベル貼り
city_labels = new Array()
svg.selectAll(".cityname-label")
.data(yokohama.geometries)
.enter()
.append("text")
.attr("class", (d) ->
if not (city_labels.indexOf(d.properties.name) > -1)
city_labels.push(d.properties.name)
return "cityname-label "+d.properties.name)
.attr("transform", (d) ->
# 文字をpath中央から、文字高さ1/2分高い位置に貼る
pos = path.centroid(d)
pos[1] -= labelLineHeight / 2
return "translate(" + pos + ")")
.attr("dy", ".35em")
.text((d) ->
return attrHash[d.properties.name].name)
# 値ラベル貼り
svg.selectAll(".stat-label")
.data(yokohama.geometries)
.enter()
.append("text")
.attr("class", (d) ->
if not (city_labels.indexOf(d.properties.name) > -1)
city_labels.push(d.properties.name)
return "stat-label "+d.properties.name)
.attr("transform", (d) ->
# 文字をpath中央から、文字高さ1/2分高い位置に貼る
pos = path.centroid(d)
pos[1] += labelLineHeight / 2
return "translate(" + pos + ")")
.attr("dy", ".35em")
.text((d) ->
return attrHash[d.properties.name][target_key])
# 各最初のエリアのみラベルを表示する
for id in city_labels
svg.select(".cityname-label."+id).style("display", "block")
svg.select(".stat-label."+id).style("display", "block")
return true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment