track-style.ts 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import * as ol from 'ol'
  2. import * as style from 'ol/style'
  3. import * as layer from 'ol/layer'
  4. import * as source from 'ol/source'
  5. import * as geom from 'ol/geom'
  6. import * as proj from 'ol/proj'
  7. import * as interaction from 'ol/interaction'
  8. import * as extent from "ol/extent";
  9. import * as format from "ol/format";
  10. import { Coordinate } from 'ol/coordinate'
  11. import * as turf from '@turf/turf'
  12. const trackLineStyle = (feature: any, resolution: any, map: any, color: any, pMap: { get: (arg0: string) => any }, callback: (arg0: style.Style[], arg1: any[]) => void) => {
  13. const _style = []
  14. _style.push(new style.Style({
  15. stroke: new style.Stroke({
  16. color: color,
  17. width: 2
  18. })
  19. }))
  20. const geometry = feature.getGeometry();
  21. const length = geometry.getLength();//获取线段长度
  22. const radio = (200 * resolution) / length;
  23. const dradio = 1;//投影坐标系,如3857等,在EPSG:4326下可以设置dradio=10000
  24. const radius = 10
  25. const longRadius = radius * Math.SQRT2;
  26. const judgeIs = (p1: any[], p2: any[], p3: any[]) => {
  27. const E = 0.00000001
  28. const k1 = (ps: any[], pe: number[]) => {
  29. return (pe[1] - ps[1]) / (pe[0] - ps[0])
  30. }
  31. const k2 = (ps: any[], pe: number[]) => {
  32. return (pe[0] - ps[0]) / (pe[1] - ps[0])
  33. }
  34. const a = (ps: any[], pe: any[]) => {
  35. return Math.abs(k1(p1, ps) - k1(p1, pe)) <= E && Math.abs(k1(p1, ps) - k1(p1, pe)) >= -E
  36. }
  37. const d = (ps: any[], pe: any[]) => {
  38. return Math.abs(k2(p1, ps) - k2(p1, pe)) <= E && Math.abs(k2(p1, ps) - k2(p1, pe)) >= -E
  39. }
  40. const s = (p: any[]) => {
  41. return p3[0] === p[0] && p3[1] === p[1]
  42. }
  43. return s(p1) || s(p2) || a(p2, p3) || d(p2, p3)
  44. }
  45. for (let i = 0; i <= 1; i += radio) {
  46. const arrowLocation = geometry.getCoordinateAt(i);
  47. if (extent.containsCoordinate(map.getView().calculateExtent(map.getSize()), arrowLocation)) {
  48. geometry.forEachSegment((start: any[], end: any[]) => {
  49. if (!judgeIs(start, end, arrowLocation)) {
  50. return
  51. }
  52. let rotation = 0;
  53. const dx = end[0] - start[0];
  54. const dy = end[1] - start[1];
  55. rotation = Math.atan2(dy, dx);
  56. const pushStyle = (position: Coordinate) => {
  57. _style.push(new style.Style({
  58. geometry: new geom.Point(position),
  59. image: new style.RegularShape({
  60. stroke: new style.Stroke({
  61. color,
  62. width: 2,
  63. lineDash: [
  64. longRadius - (4 * (radius / 10)),
  65. longRadius + (5.5 * (radius / 10)),
  66. longRadius,
  67. 0
  68. ]
  69. }),
  70. radius: radius / Math.SQRT2,
  71. rotation: -rotation,
  72. angle: Math.PI / (180 / 90),
  73. points: 4
  74. })
  75. }));
  76. }
  77. if (map.getView().getZoom() < map.getView().getMaxZoom()) {
  78. const dx1 = end[0] - arrowLocation[0];
  79. const dy1 = end[1] - arrowLocation[1];
  80. const dx2 = arrowLocation[0] - start[0];
  81. const dy2 = arrowLocation[1] - start[1];
  82. if (dx1 != dx2 && dy1 != dy2) {
  83. if (Math.abs(dradio * dx1 * dy2 - dradio * dx2 * dy1) < 0.001) {
  84. pushStyle(arrowLocation)
  85. }
  86. }
  87. } else {
  88. if (Math.sqrt(Math.pow(start[0] - end[0], 2) + Math.pow(start[1] - end[1], 2)) > resolution * 100) {
  89. pushStyle([(start[0] + end[0]) / 2, (start[1] + end[1]) / 2])
  90. }
  91. }
  92. });
  93. }
  94. }
  95. const pList = []
  96. let lC = 0
  97. // pList.push(pMap.get(geometry.getFirstCoordinate().join('-')))
  98. if (map.getView().getZoom() < map.getView().getMaxZoom()) {
  99. geometry.forEachSegment((start: number | Coordinate, end: number | any[]) => {
  100. // @ts-ignore
  101. const l = new geom.LineString([start, end])
  102. lC += l.getLength()
  103. if (extent.containsCoordinate(map.getView().calculateExtent(map.getSize()), <any>start) && lC > 200 * resolution) {
  104. // @ts-ignore
  105. const current = pMap.get(`${start[0]}-${start[1]}`)
  106. // @ts-ignore
  107. const next = pMap.get(`${end[0]}-${end[1]}`)
  108. pList.push({current, next})
  109. lC = 0
  110. }
  111. });
  112. } else {
  113. geometry.forEachSegment((start: number | Coordinate, end: number | any[]) => {
  114. // @ts-ignore
  115. const l = new geom.LineString([start, end])
  116. if (extent.containsCoordinate(map.getView().calculateExtent(map.getSize()), <any>start)) {
  117. // @ts-ignore
  118. const current = pMap.get(`${start[0]}-${start[1]}`)
  119. // @ts-ignore
  120. const next = pMap.get(`${end[0]}-${end[1]}`)
  121. pList.push({current, next})
  122. }
  123. });
  124. }
  125. pList.push({
  126. current: pMap.get(geometry.getLastCoordinate().join('-')),
  127. next: null
  128. })
  129. callback(_style, pList)
  130. return _style
  131. }
  132. const trackPointStyle = (color: any, current: any, next: any) => {
  133. const _style = []
  134. let _text = String(current.speed) + '节'
  135. if (next) {
  136. const dis = turf.distance(turf.point(current.position), turf.point(next.position), {units: 'meters'})
  137. _text += dis > 1000 ? `\n${(dis / 1000).toFixed(1)}千米` : `\n${dis.toFixed(0)}米`
  138. _text += `\n${(dis / 0.51444444).toFixed(0)}秒`
  139. }
  140. _style.push(new style.Style({
  141. image: new style.Circle({
  142. radius: 10,
  143. fill: new style.Fill({
  144. color: color,
  145. }),
  146. }),
  147. text: new style.Text({
  148. text: _text,
  149. font: "12px Microsoft YaHei", // 设置字体大小
  150. fill: new style.Fill({
  151. // 设置字体颜色
  152. color: "#000",
  153. }),
  154. })
  155. }),)
  156. return _style
  157. }
  158. export default {
  159. trackLineStyle,
  160. trackPointStyle
  161. }