ShapefileをOpenLayersで表示する。[その1]
Shapefileを直接読み込んで、OpenLayer上で表示してみます。
元ネタは、js-shapefile-to-geojsonで公開されているJavaScriptを使いました。
開発環境は、Windows 7 32bit,Aptana Studio 3.4
Firefox 20.0とGoogle Chromeで確認しました。IE9では表示できないみたいです。
必要なJavaScript
js-shapefile-to-geojsonからmasterのZIPをdownloadして、unzipします。 とりあえずDesktopでも大丈夫です。
後は、OpenLayersをここから2.12をdownloadして解凍しておきます。
testdata folderに表示させてたいShapefile一式をcopy、その際にshp,shx、dbfの3つのファイルが必要になります。
ここで、htmlファイルは、私が作成したものです。また、ecl.js,encoding.js,utf8.jsは書き加えたものです。OpenLayers-Proj4.jsは必要ありません。
Shapefileを表示してみる。
HTML5で作成します。file名は、shp2json.htmlです。
codeは簡単です。exmaple folderをhtmlを参考にして若干手を加えています。
<!doctype html> <html> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> <title>js-shapefile-to-geojson Demo Page</title> <script src="lib/OpenLayers/OpenLayers.js"></script> <script src="stream.js"></script> <script src="shapefile.js"></script> <script src="dbf.js"></script> <link rel="stylesheet" href="lib/OpenLayers/theme/default/style.css" type="text/css" /> <script type="text/javascript"> var map; function init() { map = new OpenLayers.Map("map", { allOverlays : true }), parser = new OpenLayers.Format.GeoJSON(), vector = new OpenLayers.Layer.Vector("Converted"), shapefile = new Shapefile({ shp : "testdata/c14_region.shp", dbf : "testdata/c14_region.dbf" }, function(data) { var features = parser.read(data.geojson); vector.addFeatures(features); map.zoomToExtent(vector.getDataExtent()); }) map.addLayer(vector); map.addControl(new OpenLayers.Control.LayerSwitcher()); map.addControl(new OpenLayers.Control.Attribution()); map.addControl(new OpenLayers.Control.ScaleLine()); map.addControl(new OpenLayers.Control.MousePosition()); // Interaction; not needed for initial display. selectControl = new OpenLayers.Control.SelectFeature(vector); map.addControl(selectControl); selectControl.activate(); vector.events.on({ 'featureselected' : onFeatureSelect, 'featureunselected' : onFeatureUnselect }); } // Needed only for interaction, not for the display. function onPopupClose(evt) { // 'this' is the popup. var feature = this.feature; if (feature.layer) {// The feature is not destroyed selectControl.unselect(feature); } else {// After "moveend" or "refresh" events on POIs layer all // features have been destroyed by the Strategy.BBOX this.destroy(); } } function onFeatureSelect(evt) { feature = evt.feature; var table = '<table>'; table += '<p>属性値</p>'; for (var attr in feature.attributes) { table += '<tr><td>' + attr + '</td><td>' + feature.attributes[attr] + '</td></tr>'; } table += '</table>'; popup = new OpenLayers.Popup.FramedCloud("featurePopup", feature.geometry.getBounds().getCenterLonLat(), new OpenLayers.Size(100, 100), table, null, true, onPopupClose); feature.popup = popup; popup.feature = feature; map.addPopup(popup, true); } function onFeatureUnselect(evt) { feature = evt.feature; if (feature.popup) { popup.feature = null; map.removePopup(feature.popup); feature.popup.destroy(); feature.popup = null; } } </script> <style type="text/css"> html, body { height: 100%; width: 100%; } #map { height: 400px; width: 600px; background-color: #eee; } </style> </head> <body onload="init()"> <div id="map"></div> <p> View project at <a href="http://github.com/wavded/js-shapefile-to-geojson"> http://github.com/wavded/js-shapefile-to-geojson</a>. </body> </html>
要するに、Shapefileを読み込んで、GeoJSONにして、OpenLayers上にVectorのfeatureを作成すると言うことです。
shpとdbfのbinary dataをstream.jsで読み込んで、GeoJSONを作成します。
な感じで、Shapefileが表示されます。Good Job!!ですね。
ここでは、神奈川県の市区町村の行政界を表示しています。
また、GeoJSONに変換して表示されたfeatureをクリックすると属性値が表示されます。
な感じです。
が。。。。 みての通り、nameが日本語表示されません。
どうやっても、属性データが文字化けしてしまいます。
これは、2byte codeで表現される日本語が化けるのです。
utf8変換のjsを利用したり、encodingを試したのですが。。。
問題点は、このbainaryをstream.jsで呼び出す際に1byteごと読み出して、code変換しているため文字化けすることはわかったのですが。Firebugで追っかけてもみました。
いかんせん、力量不足。。。
問題点と修正
またもや、2byteの日本語の壁にぶち当たりました。
変更すべき点は、
-
binary dataをdbfのfield.lengthで一度に呼び込む
-
1byteか2byteかの判断をする。
-
2byteならば、encodingでutf8へ変換する。
これでいけるんじゃない? だからそのcodeは?
何か良い知恵はないでしょうか? ぜひお知恵を拝借させてください。
次回は、https://github.com/RandomEtc/shapefile-jsを使ったexampleについて書きます。
が。。。ここにも問題が。
最近のコメント