mockFarmLayer.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. import Style from "ol/style/Style";
  2. import Photo from "ol-ext/style/Photo";
  3. import { newPolymerFeature, newPoint } from "@/common/util";
  4. import Icon from "ol/style/Icon";
  5. import { Cluster, Vector as VectorSource } from "ol/source.js";
  6. import { Vector } from "ol/layer.js";
  7. import * as KMap from '@/utils/ol-map/KMap';
  8. import { Fill, Text, Circle, Stroke } from "ol/style.js";
  9. import { boundingExtent } from 'ol/extent.js';
  10. import { toLonLat } from 'ol/proj';
  11. import CircleStyle from 'ol/style/Circle.js';
  12. import {base_img_url2} from "@/api/config.js"
  13. import eventBus from "@/api/eventBus";
  14. import router from '@/router'
  15. /**
  16. * 行政区县级天气点位数据
  17. */
  18. class MockFarmLayer {
  19. constructor() {
  20. let that = this
  21. this.nameStyleCache = {}
  22. this.cloudFilenameCache = {}
  23. this.statusTitleStyleCache = {}
  24. this.textBgStyleCache = {}
  25. this.diseaseStyle = new Style({
  26. // image: new Icon({
  27. // src: require("@/assets/status/status_yj.png"),
  28. // scale: 0.7,
  29. // displacement: [2.5, 40],
  30. // }),
  31. });
  32. this.pointStyle = new Style({
  33. renderer: function (coordinates, state) {
  34. let ctx = state.context;
  35. ctx.strokeStyle = 'black'; // 边框颜色
  36. ctx.lineWidth = 2; // 边框宽度
  37. ctx.fillStyle = 'rgba(29,28,28,0.8)'; // 填充颜色
  38. ctx.beginPath();
  39. ctx.ellipse(coordinates[0], coordinates[1], 7 * state.pixelRatio, 2 * state.pixelRatio, 0, 0, 2 * Math.PI);// 绘制椭圆
  40. ctx.fill();// 填充椭圆
  41. ctx.stroke();// 绘制椭圆边框
  42. },
  43. zIndex:-1
  44. });
  45. eventBus.on("warningMap:init", function (kmap) {
  46. that.initLayer(kmap)
  47. VE_API.mini_farm.weatherRiskVirtualFarmList().then(res => {
  48. if(res.code ===0){
  49. const lby = {}
  50. const jgjd = {
  51. disease:'',
  52. grow:'花苞',
  53. img:'https://birdseye-img.sysuimars.com/birdseye-look-mini/img_crop/bch/ch/cropped_DJI_20240707184352_0041_V_9.jpg',
  54. name:'井冈基地',
  55. mapId:2,
  56. nodeType:"mock_farm_data",
  57. mockFarmId:88866,
  58. cloudFilename:'',
  59. dic:{
  60. "病虫异常": 0,
  61. "物候期": "果期",
  62. "比例": 91,
  63. "生育期": "膨果期",
  64. "生长异常": 1
  65. },
  66. targetSampleId:96774,
  67. wkt:'POINT(113.5081595 23.5320866)'
  68. }
  69. res.data.push(jgjd)
  70. console.log('res.data',res.data);
  71. that.setData(res.data)
  72. }
  73. })
  74. })
  75. eventBus.on("weatherTime:changeTime", function ({date}) {
  76. VE_API.mini_farm.weatherRiskVirtualFarmList({date: "2025-"+date}).then(res => {
  77. if(res.code ===0){
  78. that.setData(res.data)
  79. }
  80. })
  81. })
  82. eventBus.on("MockFarmLayer:click", function ({event, feature}) {
  83. let targetSampleId = feature.get("targetSampleId")
  84. let mockFarmId = feature.get("mockFarmId")
  85. // let lonLat = event.map.getCoordinateFromPixel(event.pixel);
  86. // console.log('纬度:', lonlat[1]);
  87. router.push({path:'feature_album',query:{farmId:mockFarmId,sampleId:targetSampleId,timestamp: Date.now()}})
  88. })
  89. }
  90. /*************************************************************************************************
  91. 图层初始化的函数
  92. *************************************************************************************************/
  93. initLayer(kmap){
  94. let that = this;
  95. this.vectorStyle = new KMap.VectorStyle()
  96. this.clusterSource = new VectorSource({})
  97. this.clusterLayer = new Vector({
  98. source: new Cluster({
  99. distance: 50,
  100. source: this.clusterSource,
  101. }),
  102. name: "MockFarmLayer",
  103. minZoom: 5,
  104. maxZoom: 21,
  105. zIndex: 1001,
  106. style: function (feature) {
  107. let f = that.selectFeature(feature)
  108. let disease = f.get("disease");
  109. let grow = (f.get("grow") === "花苞" || f.get("grow") === "露白") ? "谢花" : f.get("grow");
  110. let phenology = "褪绿";
  111. let img = f.get("img");
  112. let name = f.get("name");
  113. let id = f.get("mapId");
  114. let styles = [that.pointStyle, that.cloudStyle(img), that.nameStyle(id, name)];
  115. that.setProperties(feature,f)
  116. let text = "";
  117. let fontColor = "#ffffff"
  118. if(name==='井冈基地'){
  119. console.log('井冈基地',grow);
  120. }
  121. if (disease) {
  122. text = disease;
  123. styles.push(that.textBgStyle("#EFEEEE","#EFEEEE"));
  124. fontColor = "#B6B6B6"
  125. } else if (grow) {
  126. if(grow === "露白"){
  127. styles.push(that.textBgStyle("#EFEEEE","#EFEEEE"));
  128. text = grow;
  129. fontColor = "#B6B6B6"
  130. }else{
  131. styles.push(that.textBgStyle("#fff","#fff"));
  132. text = grow;
  133. fontColor = "#BBBBBB"
  134. }
  135. } else if (phenology) {
  136. styles.push(that.textBgStyle("#90EE90","#008000"));
  137. text = phenology;
  138. fontColor = "#f5f4f4"
  139. }
  140. styles.push(that.statusTitleStyle(text, -60, fontColor,"#ffffff00"));
  141. if (disease) {
  142. styles.push(that.diseaseStyle)
  143. }
  144. return styles;
  145. }
  146. });
  147. kmap.addLayer(this.clusterLayer);
  148. }
  149. /*************************************************************************************************
  150. 加载数据相关的函数
  151. *************************************************************************************************/
  152. setData(data){
  153. this.clusterSource.clear()
  154. let features = []
  155. for(let item of data){
  156. features.push(newPoint(item,"wkt","mock_farm_data"))
  157. }
  158. this.clusterSource.addFeatures(features)
  159. }
  160. /*************************************************************************************************
  161. 样式相关的函数
  162. *************************************************************************************************/
  163. /**
  164. *
  165. * @param startColor '#ffc91a'
  166. * @param endColor '#d2a106'
  167. * @returns {Style}
  168. */
  169. textBgStyle(startColor,endColor){
  170. let key = startColor + endColor
  171. let style = this.textBgStyleCache[key]
  172. if (!style) {
  173. style = new Style({
  174. renderer: function (coordinates, state) {
  175. let ctx = state.context;
  176. // 矩形的参数
  177. const x = coordinates[0]; // 矩形中心点的x坐标
  178. const y = coordinates[1] - 60 * state.pixelRatio; // 矩形中心点的y坐标
  179. const width = 50 * state.pixelRatio; // 矩形的宽度
  180. const height = 20 * state.pixelRatio; // 矩形的高度
  181. const cornerRadius = 4 * state.pixelRatio; // 圆角半径
  182. // 创建渐变
  183. const gradient = ctx.createLinearGradient(x - width / 2, y, x + width / 2, y);
  184. gradient.addColorStop(0, startColor); // 渐变起始颜色
  185. gradient.addColorStop(1, endColor); // 渐变结束颜色
  186. // 绘制圆角矩形
  187. ctx.beginPath();
  188. ctx.moveTo(x - width / 2 + cornerRadius, y - height / 2); // 左上角
  189. ctx.lineTo(x + width / 2 - cornerRadius, y - height / 2); // 上边
  190. ctx.arc(x + width / 2 - cornerRadius, y - height / 2 + cornerRadius, cornerRadius, -Math.PI / 2, 0); // 右上角
  191. ctx.lineTo(x + width / 2, y + height / 2 - cornerRadius); // 右边
  192. ctx.arc(x + width / 2 - cornerRadius, y + height / 2 - cornerRadius, cornerRadius, 0, Math.PI / 2); // 右下角
  193. ctx.lineTo(x - width / 2 + cornerRadius, y + height / 2); // 下边
  194. ctx.arc(x - width / 2 + cornerRadius, y + height / 2 - cornerRadius, cornerRadius, Math.PI / 2, Math.PI); // 左下角
  195. ctx.lineTo(x - width / 2, y - height / 2 + cornerRadius); // 左边
  196. ctx.arc(x - width / 2 + cornerRadius, y - height / 2 + cornerRadius, cornerRadius, Math.PI, -Math.PI / 2); // 左上角
  197. ctx.closePath();
  198. ctx.fillStyle = gradient; // 填充颜色
  199. ctx.fill();
  200. },
  201. zIndex:2
  202. })
  203. this.textBgStyleCache[key] = style
  204. }
  205. return style
  206. }
  207. statusTitleStyle(statusName,offsetY,color,strokeColor){
  208. let style = this.statusTitleStyleCache[statusName]
  209. if (!style) {
  210. style = new Style({
  211. text: new Text({
  212. text: statusName,
  213. offsetX: 0,
  214. offsetY: offsetY,
  215. font: "bold 12px sans-serif",
  216. fill: new Fill({ color }), // 字体颜色
  217. stroke: new Stroke({ color: strokeColor }), // 字体颜色
  218. }),
  219. zIndex:3
  220. });
  221. this.statusTitleStyleCache[statusName] = style
  222. }
  223. return style
  224. }
  225. /**
  226. * 农场名称样式
  227. * @param id
  228. * @param name
  229. * @returns {Style}
  230. */
  231. nameStyle(id, name) {
  232. let nameStyle = this.nameStyleCache[name]
  233. if (!nameStyle) {
  234. nameStyle = new Style({
  235. text: new Text({
  236. text: name,
  237. offsetX: 0,
  238. offsetY: 12,
  239. font: "bold 12px sans-serif",
  240. fill: new Fill({ color: "#2199f8" }), // 字体颜色
  241. stroke: new Stroke({ color: "#fff" }), // 字体颜色
  242. }),
  243. });
  244. this.nameStyleCache[name] = nameStyle
  245. }
  246. return nameStyle
  247. }
  248. /**
  249. * 农场照片样式
  250. * @param cloudFilename
  251. * @returns {Style}
  252. */
  253. cloudStyle(cloudFilename){
  254. let that= this
  255. let cloudStyle = this.cloudFilenameCache[cloudFilename]
  256. if (!cloudStyle) {
  257. let cloudUrl = `${cloudFilename}?imageView2/1/w/100`
  258. cloudStyle = new Style({
  259. image: new Photo({
  260. src: cloudUrl,
  261. radius: 20,
  262. kind:"anchored",
  263. shadow: 5,
  264. crop: true,
  265. displacement: [2.5, 20-4],
  266. stroke: new Stroke({
  267. width: 3,
  268. color: "#fff",
  269. }),
  270. onload: function () {
  271. that.clusterLayer &&
  272. that.clusterLayer.changed();
  273. },
  274. })
  275. })
  276. this.cloudFilenameCache[cloudFilename] = cloudStyle
  277. }
  278. return cloudStyle
  279. }
  280. /*************************************************************************************************
  281. 其他函数
  282. *************************************************************************************************/
  283. setProperties(feature,f) {
  284. let disease = f.get("disease");
  285. let cloudFilename = f.get("cloudFilename");
  286. let mockFarmId = f.get("mockFarmId");
  287. let id = f.get("mapId");
  288. let targetSampleId = f.get("targetSampleId");
  289. feature.set("id",id)
  290. feature.set("mockFarmId",mockFarmId)
  291. feature.set("targetSampleId",targetSampleId)
  292. }
  293. selectFeature(feature) {
  294. let fs = feature.get("features");
  295. if (fs.length === 1) {
  296. return fs[0];
  297. } else {
  298. // 优先返回有 grow 的项
  299. for (let item of fs) {
  300. if (item.get("grow")) {
  301. return item;
  302. }
  303. }
  304. // 其次返回有 disease 的项
  305. for (let item of fs) {
  306. if (item.get("disease")) {
  307. return item;
  308. }
  309. }
  310. // 如果都没有,返回第一个项
  311. return fs[0];
  312. }
  313. }
  314. }
  315. new MockFarmLayer()