属性表示画面の吹き出しを作成しようと思い、OpenLayersの拡張版であるol-extの最新版v3.2.1にFixed popupとして機能が提供されていたのですが…
吹き出しの描画が、地図上でしか機能しないため、JavaScriptの「canvas」の勉強を兼ねて、自作することにしました。今回は、JavaScriptのみの修正でしたので、意外と簡単に実装できました。
処理概要は以下の通りです。
- 属性表示画面は、ASPxPopupControlクラスで作成していますが、画面移動時のイベントが提供されていなかったので、 windows全体のmousemoveイベントリスナーを登録します。
- mousemoveイベントで、属性表示画面が表示されている場合は、canvasを利用して、図形の座標位置から、属性表示画面への中心までの吹き出し画像を描画します。
- あと、マウスイベント以外にも、地図スクロール操作で図形位置が変わるため、OpenlayersのViewクラスに、’change:resolution’イベントリスナーを登録し、スクロールが発生した際も吹き出し画像を描画させます。
- 後処理として、属性表示画面が閉じた際に、吹き出し画像が残ってしまうので、画像をクリアします。
map.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
var map; var canvasElm; var canvasCtx; window.addEventListener('mousemove', onMousemove); function onMousemove() { redrawCallout(); } function InitMap() { map = new ol.Map({ layers: [], target: 'map', controls: ol.control.defaults({ attributionOptions: { collapsible: false } }), view: new ol.View({ center: [14897735, 4070125], zoom: 10 }) }); map.getView().on('change:resolution', onChangeResolution); } function onChangeResolution(evt) { redrawCallout(); } function redrawCallout() { if (ReportEditPopup.IsVisible()) { if (canvasCtx === undefined) { canvasElm = document.getElementById('canvas'); canvasCtx = canvasElm.getContext('2d'); canvasCtx.imageSmoothingEnabled = true; canvasElm.width = 100; canvasElm.height = 100; } var mainElm = document.getElementById('bodyMain'); canvasElm.width = mainElm.clientWidth; canvasElm.height = mainElm.clientHeight; var mapRect = document.getElementById('map').getBoundingClientRect(); var coord = selectFeature.getGeometry().getFirstCoordinate(); var pixel = map.getPixelFromCoordinate(coord); var margin = 8; var startX = mapRect.left + pixel[0] - margin; var startY = mapRect.top + pixel[1] - margin; var centerOffset = 30; var popupElm = ReportEditPopup.GetWindowElement(-1); var centerX = (popupElm.offsetLeft + popupElm.offsetLeft + popupElm.offsetWidth) / 2; var centerY = (popupElm.offsetTop + popupElm.offsetTop + popupElm.offsetHeight) / 2; var popupLeft = centerX - centerOffset; var popupTop = centerY - centerOffset; var popupRight = centerX + centerOffset; var popupBottom = centerY + centerOffset; canvasCtx.clearRect(0, 0, canvasElm.width, canvasElm.height); canvasCtx.shadowColor = "#808080"; canvasCtx.shadowOffsetX = 5; canvasCtx.shadowOffsetY = 5; canvasCtx.shadowBlur = 10; canvasCtx.strokeStyle = "#efefef"; canvasCtx.beginPath(); canvasCtx.moveTo(startX, startY); canvasCtx.lineTo(startX, startY); canvasCtx.lineTo(popupLeft, popupTop); canvasCtx.lineTo(popupRight, popupBottom); canvasCtx.lineTo(startX, startY); canvasCtx.closePath(); canvasCtx.stroke(); canvasCtx.fillStyle = "#fafafa"; canvasCtx.fill(); } } |
以下、画面イメージです。
属性表示画面を移動すると、吹き出しが付いてきます。
拡大縮小しても、吹き出しが付いてきます。