shipStyle.ts 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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 {isValue} from "@/utils/util";
  9. import * as extent from "ol/extent";
  10. // @ts-ignore
  11. import AIS from './AIS.svg'
  12. const speedStyle = (lineRadius, rotation) => {
  13. return new style.Style({
  14. image: new style.RegularShape({
  15. stroke: new style.Stroke({
  16. color: '#000000',
  17. width: 1
  18. }),
  19. displacement: [0, lineRadius],
  20. radius: lineRadius,
  21. rotation,
  22. points: 2
  23. })
  24. })
  25. }
  26. const headingStyle = (lineRadius, headAngle, rotation) => {
  27. const headRadius = 6
  28. return new style.Style({
  29. image: new style.RegularShape({
  30. stroke: new style.Stroke({
  31. color: '#ee1919',
  32. width: 1
  33. }),
  34. displacement: [
  35. headRadius * Math.sin(headAngle / 180 * Math.PI),
  36. (lineRadius * 2) + headRadius * Math.cos(headAngle / 180 * Math.PI)
  37. ], //这是偏移量
  38. radius: headRadius,
  39. rotation,
  40. angle: Math.PI / (180 / headAngle), //这是角度计算出的地图上显示的角度
  41. points: 2
  42. })
  43. })
  44. }
  45. const shipActiveStyle = (color = '#9F2EFF') => {
  46. const radius = 25
  47. const longRadius = radius * Math.SQRT2
  48. return new style.Style({
  49. image: new style.RegularShape({
  50. stroke: new style.Stroke({
  51. color,
  52. width: 2,
  53. lineDash: [
  54. (longRadius * 3) / 10,
  55. (longRadius * 4) / 10,
  56. (longRadius * 3) / 10,
  57. 0
  58. ]
  59. }),
  60. radius1: radius,
  61. rotation: Math.PI / (180 / 45),
  62. points: 4
  63. })
  64. })
  65. }
  66. const ShipNormalStyle = ({
  67. course = 0,
  68. speed = 0,
  69. head = null,
  70. color = '#01f200'
  71. }) => {
  72. const _style: any = []
  73. const allRotation = Math.PI / (180 / course)
  74. const lineRadius = speed * 5
  75. // 船速
  76. _style.push(speedStyle(lineRadius, allRotation))
  77. if (head) {
  78. const headAngle = head + (360 - course)
  79. // 船首向
  80. _style.push(headingStyle(lineRadius, headAngle, allRotation))
  81. }
  82. _style.push(new style.Style({
  83. image: new style.Icon({
  84. color: color,
  85. src: AIS,
  86. rotation: allRotation,
  87. scale: 1
  88. }),
  89. }))
  90. return _style
  91. }
  92. const trackStyle = (feature, resolution, map, color, callback) => {
  93. const geometry = feature.getGeometry();
  94. const length = geometry.getLength();//获取线段长度
  95. const radio = (200 * resolution) / length;
  96. const dradio = 1;//投影坐标系,如3857等,在EPSG:4326下可以设置dradio=10000
  97. const _style = [
  98. new style.Style({
  99. stroke: new style.Stroke({
  100. color: color,
  101. width: 2,
  102. })
  103. })
  104. ];
  105. const radius = 10
  106. const longRadius = radius * Math.SQRT2;
  107. const judgeIs = (p1, p2, p3) => {
  108. const k1 = (ps, pe) => {
  109. return (pe[1] - ps[1]) / (pe[0] - ps[0])
  110. }
  111. const k2 = (ps, pe) => {
  112. return (pe[0] - ps[0]) / (pe[1] - ps[0])
  113. }
  114. const a = (ps, pe) => {
  115. return Math.abs(k1(p1, ps) - k1(p1, pe)) <= E && Math.abs(k1(p1, ps) - k1(p1, pe)) >= -E
  116. }
  117. const d = (ps, pe) => {
  118. return Math.abs(k2(p1, ps) - k2(p1, pe)) <= E && Math.abs(k2(p1, ps) - k2(p1, pe)) >= -E
  119. }
  120. const s = (p) => {
  121. return p3[0] === p[0] && p3[1] === p[1]
  122. }
  123. const E = 0.00000001
  124. return s(p1) || s(p2) || a(p2, p3) || d(p2, p3)
  125. }
  126. for (let i = 0; i <= 1; i += radio) {
  127. const arrowLocation = geometry.getCoordinateAt(i);
  128. if (extent.containsCoordinate(map.getView().calculateExtent(map.getSize()), arrowLocation)) {
  129. geometry.forEachSegment((start, end) => {
  130. if (!judgeIs(start, end, arrowLocation)) {
  131. return
  132. }
  133. let rotation = 0;
  134. const dx = end[0] - start[0];
  135. const dy = end[1] - start[1];
  136. rotation = Math.atan2(dy, dx);
  137. const pushStyle = (position) => {
  138. _style.push(new style.Style({
  139. geometry: new geom.Point(position),
  140. image: new style.RegularShape({
  141. stroke: new style.Stroke({
  142. color,
  143. width: 2,
  144. lineDash: [
  145. longRadius - (4 * (radius / 10)),
  146. longRadius + (5.5 * (radius / 10)),
  147. longRadius,
  148. 0
  149. ]
  150. }),
  151. radius: radius / Math.SQRT2,
  152. rotation: -rotation,
  153. angle: Math.PI / (180 / 90),
  154. points: 4
  155. })
  156. }));
  157. }
  158. if (map.getView().getZoom() < map.getView().getMaxZoom()) {
  159. const dx1 = end[0] - arrowLocation[0];
  160. const dy1 = end[1] - arrowLocation[1];
  161. const dx2 = arrowLocation[0] - start[0];
  162. const dy2 = arrowLocation[1] - start[1];
  163. if (dx1 != dx2 && dy1 != dy2) {
  164. if (Math.abs(dradio * dx1 * dy2 - dradio * dx2 * dy1) < 0.001) {
  165. pushStyle(arrowLocation)
  166. }
  167. }
  168. } else {
  169. if (Math.sqrt(Math.pow(start[0] - end[0], 2) + Math.pow(start[1] - end[1], 2)) > resolution * 100) {
  170. pushStyle([(start[0] + end[0]) / 2, (start[1] + end[1]) / 2])
  171. }
  172. }
  173. });
  174. }
  175. }
  176. const trackPointList = feature.get('trackPointList')
  177. const pList: any = []
  178. let trackPointListIndex = 0
  179. let lC = 0
  180. pList.push(trackPointList[0])
  181. if (map.getView().getZoom() < map.getView().getMaxZoom() - 1) {
  182. geometry.forEachSegment((start, end) => {
  183. trackPointListIndex++
  184. const l = new geom.LineString([start,end])
  185. lC += l.getLength()
  186. if (extent.containsCoordinate(map.getView().calculateExtent(map.getSize()), end) && lC > 200 * resolution) {
  187. pList.push(trackPointList[trackPointListIndex])
  188. lC = 0
  189. }
  190. });
  191. } else {
  192. geometry.forEachSegment((start, end) => {
  193. trackPointListIndex++
  194. const l = new geom.LineString([start,end])
  195. if (extent.containsCoordinate(map.getView().calculateExtent(map.getSize()), end)) {
  196. pList.push(trackPointList[trackPointListIndex])
  197. }
  198. });
  199. }
  200. return callback(_style, pList)
  201. }
  202. const trackPointNormalStyle = (color) => {
  203. const _style: any = []
  204. _style.push(new style.Style({
  205. image: new style.Circle({
  206. radius: 4,
  207. fill: new style.Fill({
  208. color: color,
  209. }),
  210. stroke: new style.Stroke({
  211. color: '#ffffff',
  212. width: 2,
  213. }),
  214. })
  215. }))
  216. return _style
  217. }
  218. const trackPointHoverStyle = (color) => {
  219. const _style: any = []
  220. _style.push(new style.Style({
  221. image: new style.Circle({
  222. radius: 6,
  223. fill: new style.Fill({
  224. color: color,
  225. }),
  226. })
  227. }))
  228. return _style
  229. }
  230. export default {
  231. ShipNormalStyle,
  232. shipActiveStyle,
  233. trackStyle,
  234. trackPointNormalStyle,
  235. trackPointHoverStyle
  236. }