osmTile.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. function makeOSMTiles(geo) {
  2. if (geo["latitude"] !== undefined && geo["longitude"] !== undefined &&
  3. geo["latitude"] >= -90 && geo["latitude"] <= 90 &&
  4. geo["longitude"] >= -180 && geo["longitude"] <= 180) {
  5. var tileServer = "https://c.tile.openstreetmap.org",
  6. currentVersion = 0,
  7. getTile = function(zoom, x, y, result) {
  8. return new Promise(function(resolve, reject) {
  9. var img = new Image();
  10. img.addEventListener("load", function() {
  11. result.img = img;
  12. resolve(result);
  13. });
  14. img.addEventListener("error", function() {
  15. console.warn("Error loading tile ", {
  16. "zoom":zoom,
  17. "x": x,
  18. "y": y
  19. });
  20. reject(img);
  21. });
  22. img.crossOrigin = "anonymous";
  23. img.src = tileServer + '/' +zoom +'/' +x +'/' +y +'.png';
  24. });
  25. },
  26. canvas = document.createElement("canvas"),
  27. mapCanvas = document.createElement("canvas");
  28. var imgSize = 300,
  29. tileSize = imgSize /3;
  30. canvas.height = canvas.width = mapCanvas.height = mapCanvas.width = imgSize;
  31. var ctx = canvas.getContext("2d"),
  32. mapCtx = mapCanvas.getContext("2d");
  33. var drawPlot = function(centerX, centerY, radius) {
  34. centerX = tileSize *centerX +tileSize;
  35. centerY = tileSize *centerY +tileSize;
  36. ctx.putImageData(mapCtx.getImageData(0, 0, imgSize, imgSize), 0, 0);
  37. if (radius !== undefined) {
  38. ctx.beginPath();
  39. ctx.arc(centerX, centerY, Math.max(radius, 10), 0, 2 * Math.PI, false);
  40. ctx.lineWidth = 2;
  41. ctx.fillStyle = 'rgba(244, 146, 66, 0.4)';
  42. ctx.strokeStyle = 'rgba(244, 146, 66, 0.8)';
  43. ctx.stroke();
  44. ctx.fill();
  45. }
  46. if (radius === undefined || radius > 25) {
  47. ctx.strokeStyle = 'rgba(244, 146, 66, 1)';
  48. ctx.beginPath();
  49. ctx.moveTo(centerX -5, centerY -5);
  50. ctx.lineTo(centerX +5, centerY +5);
  51. ctx.stroke();
  52. ctx.moveTo(centerX +5, centerY -5);
  53. ctx.lineTo(centerX -5, centerY +5);
  54. ctx.stroke();
  55. }
  56. },
  57. distanceLatlonlon = function(lat, lon0, lon1) {
  58. lat = lat * Math.PI / 180;
  59. lon0 = lon0 *Math.PI / 180;
  60. lon1 = lon1 *Math.PI / 180;
  61. return Math.abs(6371e3 * Math.acos(Math.pow(Math.sin(lat), 2) +Math.pow(Math.cos(lat), 2) *Math.cos(lon1 -lon0)));
  62. },
  63. drawTiles = function(zoom, lat, lon, acc) {
  64. mapCtx.fillStyle = "#808080";
  65. mapCtx.fillRect(0, 0, imgSize, imgSize);
  66. ctx.fillStyle = "#808080";
  67. ctx.fillRect(0, 0, imgSize, imgSize);
  68. var nbTiles = Math.pow(2, zoom),
  69. px = ((lon +180) / 360) * nbTiles,
  70. py = (1 -Math.log(Math.tan(lat *Math.PI / 180) + 1 / Math.cos(lat * Math.PI / 180))/Math.PI) / 2 *nbTiles,
  71. absoluteX = Math.floor(px),
  72. absoluteY = Math.floor(py),
  73. accRadiusPx = acc ? acc * 100 /distanceLatlonlon(180/Math.PI*Math.atan(0.5*(Math.exp(Math.PI-2*Math.PI*absoluteY/nbTiles)-Math.exp(-(Math.PI-2*Math.PI*absoluteY/nbTiles)))), absoluteX / nbTiles * 360.0 - 180.0, (absoluteX +1) / nbTiles * 360.0 - 180.0) : 0,
  74. v = currentVersion;
  75. for (var i =0; i < 3; i++)
  76. for (var j =0; j < 3; j++)
  77. getTile(zoom, absoluteX +i -1, absoluteY +j -1, { i: i, j: j, v: v }).then(function(img) {
  78. if (img.v === currentVersion) {
  79. mapCtx.drawImage(img.img, tileSize *img.i, tileSize *img.j, tileSize, tileSize);
  80. drawPlot(px -absoluteX, py -absoluteY, accRadiusPx);
  81. }
  82. }).catch(function() {});
  83. },
  84. currentZoom,
  85. setZoom = function(val) {
  86. var newZoom = Math.max(4, Math.min(19, val));
  87. if (currentZoom !== newZoom) {
  88. currentVersion++;
  89. currentZoom = newZoom;
  90. drawTiles(currentZoom, Number(geo["latitude"]), Number(geo["longitude"]), Number(geo["accuracy"]));
  91. }
  92. };
  93. setZoom(12);
  94. var canvasWrapper = document.createElement("div"),
  95. buttonContainer = document.createElement("div"),
  96. zoomP = document.createElement("button"),
  97. zoomM = document.createElement("button");
  98. canvasWrapper.className = R.klass.map.container;
  99. canvas.className = R.klass.map.canvas;
  100. buttonContainer.className = R.klass.map.buttonContainer;
  101. zoomM.className = R.klass.map.buttonM;
  102. zoomP.className = R.klass.map.buttonP;
  103. zoomM.addEventListener("click", function() {
  104. setZoom(currentZoom -1);
  105. });
  106. zoomP.addEventListener("click", function() {
  107. setZoom(currentZoom +1);
  108. });
  109. buttonContainer.appendChild(zoomM);
  110. buttonContainer.appendChild(zoomP);
  111. canvasWrapper.appendChild(canvas);
  112. canvasWrapper.appendChild(buttonContainer);
  113. return canvasWrapper;
  114. }
  115. }