Edge.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. <template>
  2. <div class="edge">
  3. <el-radio-group v-model="radio" :disabled="!elSwitchValue">
  4. <el-radio
  5. v-for="(item, index) in arr"
  6. :key="index"
  7. :value="(index + 1) +''"
  8. @change="change(item)"
  9. >{{ item.label }}</el-radio>
  10. </el-radio-group>
  11. <el-switch
  12. v-model="elSwitchValue"
  13. class="ml-2"
  14. style="--el-switch-on-color: #409eff; --el-switch-off-color: #ff4949"
  15. @change="elSwitchChange"
  16. />
  17. <!-- <el-dialog v-if="from != null" v-model="dialogFormVisible" title="详细信息" width="500">
  18. <div class="info_container">
  19. <el-form :model="form">
  20. <el-form-item
  21. v-for="(value, key) in from"
  22. :key="key"
  23. :label="key"
  24. :label-width="'120px'"
  25. >{{ value }}</el-form-item>
  26. </el-form>
  27. </div>
  28. <template #footer>
  29. <div class="dialog-footer">
  30. <el-button
  31. @click="
  32. dialogFormVisible = false;
  33. from = null;
  34. "
  35. >关闭</el-button>
  36. </div>
  37. </template>
  38. </el-dialog>-->
  39. </div>
  40. </template>
  41. <script>
  42. export default {
  43. data() {
  44. return {
  45. radio: "1",
  46. arr: [
  47. {
  48. label: "行政边界",
  49. url: "./static/data/bianjie/徐泾镇.geojson",
  50. style: {
  51. polygon: {
  52. outerColor: "#ffee00",
  53. outerWidth: 5,
  54. innerColor: "#00c4ff",
  55. alpha: 0.5
  56. }
  57. }
  58. },
  59. {
  60. label: "村居",
  61. url: "./static/data/bianjie/徐泾镇村居数据.geojson",
  62. style: {
  63. polygon: {
  64. outerColor: "#ffee00",
  65. outerWidth: 3,
  66. innerColor: "#00c4ff",
  67. alpha: 0.5
  68. }
  69. }
  70. },
  71. {
  72. label: "责任网格",
  73. url: "./static/data/bianjie/徐泾镇责任网格.geojson",
  74. style: {
  75. polygon: {
  76. outerColor: "#ffee00",
  77. outerWidth: 3,
  78. innerColor: "#00c4ff",
  79. alpha: 0.5
  80. }
  81. }
  82. },
  83. {
  84. label: "微网格",
  85. url: "./static/data/bianjie/徐泾镇微网格.geojson",
  86. style: {
  87. polygon: {
  88. outerColor: "#ffee00",
  89. outerWidth: 3,
  90. innerColor: "#00c4ff",
  91. alpha: 0.5
  92. }
  93. }
  94. }
  95. ],
  96. elSwitchValue: true
  97. // from: null,
  98. // dialogFormVisible: false
  99. };
  100. },
  101. mounted() {
  102. window.edgeQJ = {
  103. geojsonDataSource: null,
  104. edgeEntity: null
  105. };
  106. },
  107. methods: {
  108. change(item) {
  109. this.remove();
  110. this.addGeoJson(item.url, item.style);
  111. },
  112. elSwitchChange(status) {
  113. this.radio == "0";
  114. if (status) {
  115. this.show();
  116. // this.openClick();
  117. } else {
  118. this.hide();
  119. // this.closeClick();
  120. }
  121. },
  122. show() {
  123. if (edgeQJ.geojsonDataSource) edgeQJ.geojsonDataSource.show = true;
  124. if (edgeQJ.lineEntityCollection) edgeQJ.lineEntityCollection.show = true;
  125. if (edgeQJ.edgeEntity) edgeQJ.edgeEntity.show = true;
  126. },
  127. hide() {
  128. if (edgeQJ.geojsonDataSource) edgeQJ.geojsonDataSource.show = false;
  129. if (edgeQJ.lineEntityCollection) edgeQJ.lineEntityCollection.show = false;
  130. if (edgeQJ.edgeEntity) edgeQJ.edgeEntity.show = false;
  131. },
  132. remove() {
  133. if (edgeQJ.geojsonDataSource != null) {
  134. viewer.dataSources.remove(edgeQJ.geojsonDataSource);
  135. edgeQJ.geojsonDataSource = null;
  136. }
  137. if (edgeQJ.lineEntityCollection != null) {
  138. // viewer.dataSources.remove(edgeQJ.geojsonDataSource);
  139. edgeQJ.lineEntityCollection.values.map(function(item) {
  140. viewer.entities.remove(viewer.entities.getById(item._id));
  141. });
  142. edgeQJ.lineEntityCollection.removeAll();
  143. edgeQJ.lineEntityCollection = null;
  144. }
  145. },
  146. openClick() {
  147. let that = this;
  148. if (edgeQJ.handler) return;
  149. // 绑定点击事件
  150. edgeQJ.handler = new SkyScenery.ScreenSpaceEventHandler(viewer.canvas);
  151. edgeQJ.handler.setInputAction(function(movement) {
  152. var pick = viewer.scene.pick(movement.position); // 拾取鼠标所在的entity
  153. if (SkyScenery.defined(pick)) {
  154. let entity = pick.id;
  155. if (!entity) return;
  156. if (entity.type && entity.type == "edge") {
  157. let cartesian = viewer.camera.pickEllipsoid(
  158. movement.position,
  159. viewer.scene.globe.ellipsoid
  160. );
  161. // 空间坐标转世界坐标(弧度)
  162. if (!cartesian) return;
  163. let cartographic = SkyScenery.Cartographic.fromCartesian(cartesian);
  164. if (!cartographic) return;
  165. // 弧度转为角度(经纬度)
  166. let lon = SkyScenery.Math.toDegrees(cartographic.longitude); // 经度值
  167. let lat = SkyScenery.Math.toDegrees(cartographic.latitude); // 纬度值
  168. let showEntity = SkyScenery.Cartesian3.fromDegrees(lon, lat);
  169. showEntity.data = entity.properties.getValue();
  170. that.$store.state.showEntity = showEntity;
  171. }
  172. }
  173. }, SkyScenery.ScreenSpaceEventType.LEFT_CLICK);
  174. },
  175. closeClick() {
  176. if (edgeQJ.handler) {
  177. edgeQJ.handler.removeInputAction(
  178. SkyScenery.ScreenSpaceEventType.LEFT_CLICK
  179. );
  180. edgeQJ.handler = null;
  181. }
  182. this.dialogFormVisible = false;
  183. this.from = null;
  184. },
  185. // 加载geojson数据
  186. addGeoJson(url, options) {
  187. // options = {
  188. // point: {
  189. // imgUrl: ""
  190. // },
  191. // polyline: {
  192. // color: "#ffffff",
  193. // width: 3,
  194. // alpha: 0.7
  195. // },
  196. // polygon: {
  197. // outerColor: "#ffffff",
  198. // outerWidth: 3,
  199. // innerColor: "#ffffff",
  200. // alpha: 0.7
  201. // }
  202. // };
  203. SkyScenery.GeoJsonDataSource.load(url, {
  204. clampToGround: true
  205. }).then(function(dataSource) {
  206. var entities = dataSource.entities.values;
  207. viewer.dataSources.add(dataSource);
  208. edgeQJ.geojsonDataSource = dataSource;
  209. let lineEntityCollection = new SkyScenery.EntityCollection();
  210. for (var i = 0; i < entities.length; i++) {
  211. var entity = entities[i];
  212. // if (entity.billboard) {
  213. // entity.billboard = undefined;
  214. // entity.billboard = new SkyScenery.BillboardGraphics({
  215. // image: options.point.imgUrl,
  216. // width: 50,
  217. // height: 50,
  218. // pixelOffset: new SkyScenery.Cartesian2(0, -25),
  219. // heightReference: SkyScenery.HeightReference.CLAMP_TO_GROUND
  220. // });
  221. // }
  222. // if (entity.polyline) {
  223. // entity.polyline.width = options.polyline.width;
  224. // entity.polyline.material = SkyScenery.Color.fromCssColorString(
  225. // options.polyline.color
  226. // ).withAlpha(options.polyline.alpha); // 颜色
  227. // }
  228. if (entity.polygon) {
  229. // entity.polygon.height = 6;
  230. // entity.polygon.outline = true; // 边框是否显示
  231. // entity.polygon.outlineColor = SkyScenery.Color.fromCssColorString(
  232. // options.polygon.outerColor
  233. // ); // 边框颜色
  234. // entity.polygon.outlineWidth = options.polygon.outerWidth; // 边框宽度
  235. // entity.polygon.material = SkyScenery.Color.fromCssColorString(
  236. // options.polygon.innerColor
  237. // ).withAlpha(options.polygon.alpha); // 填充色
  238. // entity.polygon.zIndex = 99;
  239. let line = viewer.entities.add({
  240. polyline: {
  241. positions: entity.polygon.hierarchy._value.positions,
  242. width: 2,
  243. material: SkyScenery.Color.fromCssColorString("#fff200"),
  244. clampToGround: true, // 这个是线覆盖模型的关键
  245. zIndex: 1000, // 这个是层级,但是必须clampToGround: true
  246. show: true
  247. }
  248. });
  249. lineEntityCollection.add(line);
  250. entity.polygon.material = new SkyScenery.ImageMaterialProperty({
  251. image: "/static/image/b2.png", // 图片路径
  252. transparent: true // 是否透明
  253. });
  254. }
  255. entity.type = "edge";
  256. }
  257. edgeQJ.lineEntityCollection = lineEntityCollection;
  258. });
  259. },
  260. addWall() {
  261. let that = this;
  262. fetch("./static/data/bianjie/徐泾镇.geojson")
  263. .then(resp => resp.json())
  264. .then(data => {
  265. let positions = data.features[0].geometry.coordinates[0][0];
  266. edgeQJ.edgeEntity = that.addDynamicWall(positions, {
  267. maxH: 150,
  268. color: "#0060fc",
  269. duration: 3000
  270. });
  271. this.addWater();
  272. });
  273. },
  274. addWater() {
  275. let that = this;
  276. fetch("./static/data/xujingzhen-hhhd.geojson")
  277. .then(resp => resp.json())
  278. .then(data => {
  279. // 加水
  280. var options = {
  281. frequency: 60000.0, // 控制波数的数字。
  282. animationSpeed: 0.01, // 控制水的动画速度的数字。
  283. amplitude: 20.0, // 控制水波振幅的数字。
  284. specularIntensity: 0.8, // 控制镜面反射强度的数字。
  285. baseWaterColor: "#006ab4", // rgba颜色对象基础颜色的水。#00ffff,#00baff,#006ab4
  286. blendColor: "#006ab4", // 从水中混合到非水域时使用的rgba颜色对象。
  287. height: 0, // 水体下表面与地表之间的高度
  288. extrudedHeight: 0.3, // 水体上表面与地表之间的高度
  289. clampToGround: false, //是否贴地
  290. opacity: 0.7, //透明度
  291. image: "/static/image/water.png"
  292. };
  293. data.features.map(function(feature) {
  294. let waterData = feature.geometry.coordinates[0][0]
  295. .join(",")
  296. .split(",")
  297. .map(num => Number(num));
  298. SkyScenery.Water(
  299. new SkyScenery.PolygonHierarchy(
  300. SkyScenery.Cartesian3.fromDegreesArray(waterData)
  301. ),
  302. options
  303. ).then(waterobj => {
  304. viewer.scene.primitives.add(waterobj);
  305. });
  306. });
  307. });
  308. },
  309. // 加载动态围墙
  310. addDynamicWall(positions, options) {
  311. /**
  312. * options = {
  313. * maxH: 100,
  314. * color: "#00c4ff80",
  315. * duration: 3000,
  316. * }
  317. */
  318. // return viewer.entities.add({
  319. // name: "立体墙效果",
  320. // wall: {
  321. // positions: positions.map(function(item) {
  322. // return SkyScenery.Cartesian3.fromDegrees(item[0], item[1]);
  323. // }),
  324. // // 设置高度
  325. // maximumHeights: new Array(positions.length).fill(options.maxH || 100),
  326. // minimumHeights: new Array(positions.length).fill(0),
  327. // material: new SkyScenery.DynamicWallMaterialProperty({
  328. // color: SkyScenery.Color.fromCssColorString(options.color), // "#"
  329. // trailImage: "/static/image/color.png",
  330. // duration: options.duration || 3000 // 3000
  331. // })
  332. // }
  333. // });
  334. // return
  335. viewer.entities.add({
  336. name: "立体墙效果",
  337. wall: {
  338. positions: positions.map(function(item) {
  339. return SkyScenery.Cartesian3.fromDegrees(item[0], item[1]);
  340. }),
  341. // 设置高度
  342. maximumHeights: new Array(positions.length).fill(options.maxH || 100),
  343. minimumHeights: new Array(positions.length).fill(0),
  344. material: this._initWallCustomMaterialProperty({
  345. image: "./static/image/arrow.png",
  346. freely: "cross",
  347. direction: "-",
  348. count: 3,
  349. color: SkyScenery.Color.BLUE,
  350. duration: 2000
  351. })
  352. }
  353. });
  354. let tp = positions
  355. .join(",")
  356. .split(",")
  357. .map(num => Number(num));
  358. let newTp = [];
  359. for (let i = 0; i < tp.length; i = i + 2) {
  360. const lon = tp[i];
  361. const lat = tp[i + 1];
  362. const height = 250;
  363. newTp.push(lon);
  364. newTp.push(lat);
  365. newTp.push(height);
  366. }
  367. this.craeteDynamicShadeWallGraphics({
  368. positions: SkyScenery.Cartesian3.fromDegreesArrayHeights(newTp),
  369. color: new SkyScenery.Color.fromCssColorString("#109af2"),
  370. image: "./static/image/wl.png"
  371. });
  372. },
  373. // 动态初始化材质线
  374. _initWallCustomMaterialProperty(options) {
  375. let _that = this;
  376. let Cesium = SkyScenery;
  377. var Color = Cesium.Color,
  378. defaultValue = Cesium.defaultValue,
  379. defined = Cesium.defined,
  380. defineProperties = Object.defineProperties,
  381. Event = Cesium.Event,
  382. createPropertyDescriptor = Cesium.createPropertyDescriptor,
  383. Property = Cesium.Property,
  384. Material = Cesium.Material,
  385. MaterialType =
  386. options.MaterialType || "wallType" + parseInt(Math.random() * 1000);
  387. function WallLinkCustomMaterialProperty(options) {
  388. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  389. this._definitionChanged = new Event();
  390. this._color = undefined;
  391. this._colorSubscription = undefined;
  392. this.color = options.color || Color.BLUE;
  393. this.duration = options.duration || 3000;
  394. this._time = new Date().getTime();
  395. }
  396. defineProperties(WallLinkCustomMaterialProperty.prototype, {
  397. isvarant: {
  398. get: function() {
  399. return false;
  400. }
  401. },
  402. definitionChanged: {
  403. get: function() {
  404. return this._definitionChanged;
  405. }
  406. },
  407. color: createPropertyDescriptor("color")
  408. });
  409. WallLinkCustomMaterialProperty.prototype.getType = function(time) {
  410. return MaterialType;
  411. };
  412. WallLinkCustomMaterialProperty.prototype.getValue = function(
  413. time,
  414. result
  415. ) {
  416. if (!defined(result)) {
  417. result = {};
  418. }
  419. result.color = Property.getValueOrClonedDefault(
  420. this._color,
  421. time,
  422. Color.WHITE,
  423. result.color
  424. );
  425. result.image = options.image;
  426. result.time =
  427. ((new Date().getTime() - this._time) % this.duration) / this.duration;
  428. return result;
  429. };
  430. WallLinkCustomMaterialProperty.prototype.equals = function(other) {
  431. return (
  432. this === other ||
  433. (other instanceof WallLinkCustomMaterialProperty &&
  434. Property.equals(this._color, other._color))
  435. );
  436. };
  437. //动态墙
  438. Material._materialCache.addMaterial(MaterialType, {
  439. fabric: {
  440. type: MaterialType,
  441. uniforms: {
  442. color: new Color(1.0, 0.0, 0.0, 0.5),
  443. image: options.image,
  444. time: 0
  445. },
  446. source: _that._getDirectionWallShader({
  447. get: true,
  448. count: options.count,
  449. freely: options.freely,
  450. direction: options.direction
  451. })
  452. },
  453. translucent: function(material) {
  454. return true;
  455. }
  456. });
  457. return new WallLinkCustomMaterialProperty(options);
  458. },
  459. /**
  460. * 带方向的墙体
  461. * @param {*} options
  462. */
  463. _getDirectionWallShader: function(options) {
  464. if (options && options.get) {
  465. var materail =
  466. "czm_material czm_getMaterial(czm_materialInput materialInput)\n\
  467. {\n\
  468. czm_material material = czm_getDefaultMaterial(materialInput);\n\
  469. vec2 st = materialInput.st;\n\
  470. \n ";
  471. if (options.freely == "vertical") {
  472. //(由下到上)
  473. materail +=
  474. "vec4 colorImage = texture2D(image, vec2(fract(float(" +
  475. options.count +
  476. ")*st.t " +
  477. options.direction +
  478. " time), fract(st.s)));\n ";
  479. } else {
  480. //(逆时针)
  481. materail +=
  482. "vec4 colorImage = texture2D(image, vec2(fract(float(" +
  483. options.count +
  484. ")*st.s " +
  485. options.direction +
  486. " time), fract(st.t)));\n ";
  487. }
  488. //泛光
  489. materail +=
  490. "vec4 fragColor;\n\
  491. fragColor.rgb = (colorImage.rgb+color.rgb) / 1.0;\n\
  492. fragColor = czm_gammaCorrect(fragColor);\n ";
  493. materail +=
  494. " material.diffuse = colorImage.rgb;\n\
  495. material.alpha = colorImage.a;\n\
  496. material.emission = fragColor.rgb;\n\
  497. \n\
  498. return material;\n\
  499. }\n\
  500. ";
  501. return materail;
  502. }
  503. },
  504. //动态渐变墙
  505. craeteDynamicShadeWallGraphics: function(options) {
  506. let Cesium = SkyScenery;
  507. if (options && options.positions) {
  508. var alp = options.alp || 1,
  509. num = options.num || 20,
  510. color = options.color || Cesium.Color.RED,
  511. speed = options.speed || 0.003;
  512. var wallEntity = new Cesium.Entity();
  513. wallEntity.wall = {
  514. positions: options.positions,
  515. material: new Cesium.ImageMaterialProperty({
  516. image: options.image,
  517. transparent: true,
  518. color: new Cesium.CallbackProperty(function() {
  519. if (num % 2 === 0) {
  520. alp -= speed;
  521. } else {
  522. alp += speed;
  523. }
  524. if (alp <= 0.1) {
  525. num++;
  526. } else if (alp >= 1) {
  527. num++;
  528. }
  529. return color.withAlpha(alp);
  530. }, false)
  531. })
  532. };
  533. return viewer.entities.add(wallEntity);
  534. }
  535. }
  536. },
  537. computed: {
  538. mapStatus() {
  539. return this.$store.state.initMap;
  540. }
  541. },
  542. watch: {
  543. mapStatus(newVal, oldVal) {
  544. if (newVal) {
  545. // 添加围墙
  546. this.addWall();
  547. // 添加
  548. this.change(this.arr[0]);
  549. }
  550. }
  551. }
  552. };
  553. </script>
  554. <style lang="less" scoped>
  555. .edge {
  556. width: 420px;
  557. background: #00000080;
  558. padding-left: 15px;
  559. padding-right: 15px;
  560. border-radius: 50px;
  561. .el-switch {
  562. margin-left: 20px;
  563. vertical-align: top;
  564. }
  565. .el-radio {
  566. color: #ffffff;
  567. }
  568. .info_container {
  569. height: 300px;
  570. overflow: hidden;
  571. overflow-y: auto;
  572. }
  573. }
  574. </style>