preview.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. * predefined [EPSG:3821] projection
  3. * Please make sure your desired projection can find on http://epsg.io/
  4. *
  5. * Usage :
  6. * loadshp({
  7. * url: '/shp/test.zip', // path or your upload file
  8. * encoding: 'big5' // default utf-8
  9. * EPSG: 3826 // default 4326
  10. * }, function(geojson) {
  11. * // geojson returned
  12. * });
  13. *
  14. * Created by Gipong <sheu781230@gmail.com>
  15. *
  16. */
  17. /*
  18. 2024-08-05
  19. Upgraded jszip.js to from v2.4 to v3.10
  20. Amended preview.js to fit the changes
  21. Updated JSZip function calling methods and syntax to v 3.x
  22. Removed JSZipUtils usage: Replaced it with the fetch API.
  23. Updated FileReader handling: Now JSZip.loadAsync is directly used after reading the file as an ArrayBuffer.
  24. Updated projection definition loading: Using proj4.defs inside the processZip function correctly waits for the async call to complete before proceeding.
  25. Updated by azure7749
  26. */
  27. var inputData = {},
  28. geoData = {},
  29. EPSGUser, url, encoding, EPSG,
  30. EPSG4326 = proj4('EPSG:4326');
  31. function loadshp(config, returnData) {
  32. url = config.url;
  33. encoding = config.encoding || 'utf-8';
  34. EPSG = config.EPSG || 4326;
  35. loadEPSG('https://epsg.io/' + EPSG + '.js', function () {
  36. if (EPSG == 3821) {
  37. proj4.defs([
  38. ['EPSG:3821', '+proj=tmerc +ellps=GRS67 +towgs84=-752,-358,-179,-.0000011698,.0000018398,.0000009822,.00002329 +lat_0=0 +lon_0=121 +x_0=250000 +y_0=0 +k=0.9999 +units=m +no_defs']
  39. ]);
  40. }
  41. EPSGUser = proj4('EPSG:' + EPSG);
  42. if (typeof url !== 'string') {
  43. var reader = new FileReader();
  44. reader.onload = function (e) {
  45. JSZip.loadAsync(e.target.result).then(function (zip) {
  46. processZip(zip, returnData);
  47. });
  48. }
  49. reader.readAsArrayBuffer(url);
  50. } else {
  51. fetch(url)
  52. .then(response => {
  53. if (!response.ok) {
  54. throw new Error('Network response was not ok');
  55. }
  56. return response.arrayBuffer();
  57. })
  58. .then(data => {
  59. JSZip.loadAsync(data).then(function (zip) {
  60. processZip(zip, returnData);
  61. });
  62. })
  63. .catch(err => {
  64. console.error('Failed to fetch binary content:', err);
  65. });
  66. }
  67. });
  68. }
  69. function loadEPSG(url, callback) {
  70. var script = document.createElement('script');
  71. script.src = url;
  72. script.onreadystatechange = callback;
  73. script.onload = callback;
  74. document.getElementsByTagName('head')[0].appendChild(script);
  75. }
  76. function processZip(zip, returnData) {
  77. var URL = window.URL || window.webkitURL;
  78. var shpFile = zip.file(/.shp$/i)[0];
  79. var dbfFile = zip.file(/.dbf$/i)[0];
  80. var prjFile = zip.file(/.prj$/i)[0];
  81. if (prjFile) {
  82. proj4.defs('EPSGUSER', zip.file(prjFile.name).async("string").then(function(text) {
  83. proj4.defs('EPSGUSER', text);
  84. try {
  85. EPSGUser = proj4('EPSGUSER');
  86. } catch (e) {
  87. console.error('Unsupported Projection: ' + e);
  88. }
  89. }));
  90. }
  91. Promise.all([
  92. shpFile.async("arraybuffer").then(arrayBuffer => SHPParser.load(URL.createObjectURL(new Blob([arrayBuffer])), shpLoader, returnData)),
  93. dbfFile.async("arraybuffer").then(arrayBuffer => DBFParser.load(URL.createObjectURL(new Blob([arrayBuffer])), encoding, dbfLoader, returnData))
  94. ]).then(() => {
  95. if (inputData['shp'] && inputData['dbf'] && returnData) {
  96. returnData(toGeojson(inputData));
  97. }
  98. });
  99. }
  100. function TransCoord(x, y) {
  101. if (proj4) {
  102. var p = proj4(EPSGUser, EPSG4326, [parseFloat(x), parseFloat(y)]);
  103. return { x: p[0], y: p[1] };
  104. }
  105. return { x: x, y: y };
  106. }
  107. function shpLoader(data, returnData) {
  108. inputData['shp'] = data;
  109. if (inputData['shp'] && inputData['dbf']) {
  110. if (returnData) returnData(toGeojson(inputData));
  111. }
  112. }
  113. function dbfLoader(data, returnData) {
  114. inputData['dbf'] = data;
  115. if (inputData['shp'] && inputData['dbf']) {
  116. if (returnData) returnData(toGeojson(inputData));
  117. }
  118. }
  119. function toGeojson(geojsonData) {
  120. var geojson = {
  121. type: "FeatureCollection",
  122. features: [],
  123. bbox: [
  124. TransCoord(geojsonData.shp.minX, geojsonData.shp.minY).x,
  125. TransCoord(geojsonData.shp.minX, geojsonData.shp.minY).y,
  126. TransCoord(geojsonData.shp.maxX, geojsonData.shp.maxY).x,
  127. TransCoord(geojsonData.shp.maxX, geojsonData.shp.maxY).y
  128. ]
  129. };
  130. geojsonData.shp.records.forEach(function (record, i) {
  131. var feature = {
  132. type: 'Feature',
  133. geometry: { type: '', coordinates: [] },
  134. properties: geojsonData.dbf.records[i]
  135. };
  136. switch (record.shape.type) {
  137. case 1:
  138. feature.geometry.type = "Point";
  139. feature.geometry.coordinates = [
  140. TransCoord(record.shape.content.x, record.shape.content.y).x,
  141. TransCoord(record.shape.content.x, record.shape.content.y).y
  142. ];
  143. break;
  144. case 3:
  145. case 8:
  146. feature.geometry.type = (record.shape.type == 3 ? "LineString" : "MultiPoint");
  147. record.shape.content.points.forEach(function (point, j) {
  148. if (j % 2 === 0) {
  149. feature.geometry.coordinates.push([
  150. TransCoord(record.shape.content.points[j], record.shape.content.points[j + 1]).x,
  151. TransCoord(record.shape.content.points[j], record.shape.content.points[j + 1]).y
  152. ]);
  153. }
  154. });
  155. break;
  156. case 5:
  157. feature.geometry.type = "Polygon";
  158. record.shape.content.parts.forEach(function (partIndex, pts) {
  159. var part = [];
  160. for (var j = partIndex * 2; j < (record.shape.content.parts[pts + 1] * 2 || record.shape.content.points.length); j += 2) {
  161. part.push([
  162. TransCoord(record.shape.content.points[j], record.shape.content.points[j + 1]).x,
  163. TransCoord(record.shape.content.points[j], record.shape.content.points[j + 1]).y
  164. ]);
  165. }
  166. feature.geometry.coordinates.push(part);
  167. });
  168. break;
  169. default:
  170. }
  171. if ("coordinates" in feature.geometry) geojson.features.push(feature);
  172. });
  173. return geojson;
  174. }