index.ts 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. import { Polygons } from "./polygons";
  2. import {
  3. register,
  4. BoundQueryPlugin,
  5. setGenerateStartId,
  6. inRevise,
  7. Poi,
  8. PoiAttrib,
  9. round,
  10. } from "../../board";
  11. import { PolygonsAttrib } from "./type";
  12. import { Map } from "ol";
  13. import { boundingExtent } from "ol/extent";
  14. import "./icon";
  15. import { Scale, ScaleAttrib } from "../../board/packages/scale/scale";
  16. const boundJoinMap = (
  17. boundQuery: BoundQueryPlugin,
  18. mountDOM?: HTMLDivElement,
  19. map?: Map
  20. ) => {
  21. let mapView = map?.getView();
  22. const getMapBound = () => {
  23. return mapView.calculateExtent(map.getSize());
  24. };
  25. const setMapBound = (bound: number[]) => {
  26. const extent = boundingExtent([
  27. [bound[0], bound[1]],
  28. [bound[2], bound[3]],
  29. ]);
  30. mapView.fit(extent, {
  31. size: map.getSize(),
  32. padding: [0, 0, 0, 0], // 根据需要调整边距
  33. });
  34. // console.log(`每个像素代表的米数: ${metersPerPixel}`);
  35. };
  36. const setBoardBound = () => {
  37. if (mountDOM && map) {
  38. const bound = getMapBound();
  39. if (!boundQuery.bound || inRevise(boundQuery.bound, bound)) {
  40. boundQuery.setSize(mountDOM.offsetWidth, mountDOM.offsetHeight);
  41. boundQuery.setBound([bound[0], bound[3], bound[2], bound[1]]);
  42. }
  43. }
  44. };
  45. const setMap = (bindMap: Map) => {
  46. if (map) {
  47. mapView.removeEventListener("change:center", setBoardBound);
  48. mapView.removeEventListener("change:resolution", setBoardBound);
  49. map.removeEventListener("moveend", setBoardBound);
  50. }
  51. mapView = bindMap.getView();
  52. mapView.addEventListener("change:center", setBoardBound);
  53. mapView.addEventListener("change:resolution", setBoardBound);
  54. map.addEventListener("moveend", setBoardBound);
  55. map = bindMap;
  56. setBoardBound();
  57. };
  58. boundQuery.enableMove((newBound) => {
  59. map && setMapBound(newBound);
  60. return true;
  61. });
  62. boundQuery.enableWheel((newBound) => {
  63. map && setMapBound(newBound);
  64. return true;
  65. });
  66. return {
  67. setMap,
  68. setBoardBound,
  69. setMountDom(dom: HTMLDivElement) {
  70. mountDOM = dom;
  71. setBoardBound();
  72. },
  73. destory() {
  74. mapView.removeEventListener("change:center", setBoardBound);
  75. mapView.removeEventListener("change:resolution", setBoardBound);
  76. map.removeEventListener("moveend", setBoardBound);
  77. },
  78. };
  79. };
  80. function captureMap(canvas: HTMLCanvasElement, map: Map, pixelRatio) {
  81. // 创建一个临时canvas用于绘制截图
  82. const size = map.getSize();
  83. canvas.width = size[0] * pixelRatio;
  84. canvas.height = size[1] * pixelRatio;
  85. canvas.style.width = size[0] + "px";
  86. canvas.style.height = size[1] + "px";
  87. const mapContext = canvas.getContext("2d");
  88. const mapCanvas = map.getViewport().querySelector("canvas")!;
  89. mapContext.drawImage(mapCanvas, 0, 0, canvas.width, canvas.height);
  90. return canvas.toDataURL();
  91. }
  92. const initBoard = register(
  93. { polygons: Polygons, compass: Poi, scale: Scale },
  94. { bound: new BoundQueryPlugin() }
  95. );
  96. setGenerateStartId(5000000);
  97. export const createBoard = (
  98. props: {
  99. dom?: HTMLDivElement;
  100. store?: PolygonsAttrib & { id: string };
  101. map?: Map;
  102. } = {}
  103. ) => {
  104. const compass: PoiAttrib = {
  105. id: "0",
  106. x: 0,
  107. y: 0,
  108. type: "compass",
  109. };
  110. const scale: ScaleAttrib = {
  111. id: "0",
  112. left: 20,
  113. bottom: 20,
  114. minWidth: 100,
  115. maxWidth: 150,
  116. };
  117. const data = props.store || [
  118. { id: "0", points: [], polygons: [], lines: [] },
  119. ];
  120. const board = initBoard(props.dom, { polygons: data, compass, scale }, false);
  121. const mapJoin = boundJoinMap(board.bound, props.dom, props.map);
  122. const setProps = (props: { dom?: HTMLDivElement; map?: Map } = {}) => {
  123. if (props.dom) {
  124. board.mount(props.dom);
  125. mapJoin.setMountDom(props.dom);
  126. }
  127. if (props.map) {
  128. mapJoin.setMap(props.map);
  129. }
  130. };
  131. setProps(props);
  132. let captureCanvas: HTMLCanvasElement;
  133. const scaleEntity = board.tree.entrys.scale[0] as Scale;
  134. scaleEntity.allowable = 0.01;
  135. scaleEntity.getScaleUnit = (data: number[]) => {
  136. if (!props.map) return;
  137. const mapView = props.map.getView();
  138. const projection = mapView.getProjection();
  139. const mpu = projection.getMetersPerUnit();
  140. return data[0] * mpu;
  141. };
  142. scaleEntity.getScaleText = (val: number) => {
  143. if (val > 1000) {
  144. let km = round(val / 1000, 1);
  145. let mkm = km % 1;
  146. km = Math.floor(km) + (mkm > 0.5 ? 1 : mkm < 0.5 ? 0 : 0.5);
  147. return km + " km";
  148. } else {
  149. return Math.floor(val) + " m";
  150. }
  151. };
  152. return {
  153. raw: board,
  154. scale: scaleEntity,
  155. setProps,
  156. getData() {
  157. return board.getData().polygons[0];
  158. },
  159. setData(polygon: PolygonsAttrib & { id: string }) {
  160. board.setData({ polygons: [polygon], compass, scale });
  161. },
  162. destory() {
  163. mapJoin.destory();
  164. board.destory();
  165. },
  166. get polygon() {
  167. return board.tree.children[0] as Polygons;
  168. },
  169. getPixelFromCoordinate(point: number[]) {
  170. return board.tree.getPixelFromStage(point);
  171. },
  172. async toDataURL(pixelRatio = 1) {
  173. const boardDataURL = board.tree.stage.toDataURL({
  174. pixelRatio,
  175. mimeType: '"image/jpeg"',
  176. });
  177. if (!props.map) {
  178. return boardDataURL;
  179. }
  180. const size = [board.tree.stage.width(), board.tree.stage.height()];
  181. if (!captureCanvas) {
  182. captureCanvas = document.createElement("canvas");
  183. }
  184. captureCanvas.width = size[0] * pixelRatio;
  185. captureCanvas.height = size[1] * pixelRatio;
  186. captureCanvas.style.width = size[0] + "px";
  187. captureCanvas.style.height = size[1] + "px";
  188. const captureCtx = captureCanvas.getContext("2d");
  189. captureCtx.clearRect(0, 0, captureCanvas.width, captureCanvas.height);
  190. captureCtx.save();
  191. captureMap(captureCanvas, props.map, pixelRatio);
  192. captureCtx.restore();
  193. return new Promise<string>((resolve, reject) => {
  194. const image = new Image();
  195. image.src = boardDataURL;
  196. image.onload = () => {
  197. captureCtx.drawImage(
  198. image,
  199. 0,
  200. 0,
  201. captureCanvas.width,
  202. captureCanvas.height
  203. );
  204. const dataURL = captureCanvas.toDataURL("image/jpeg");
  205. resolve(dataURL);
  206. };
  207. image.onerror = reject;
  208. });
  209. },
  210. };
  211. };
  212. export * from "../../board";
  213. export * from "./polygons";
  214. export * from "./type";
  215. export * from "./path";
  216. export * from "./point";