index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. <!-- 地图 -->
  2. <template>
  3. <div class="mapBox">
  4. <div class="chartsdom" id="3DMap"></div>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. data() {
  10. return {
  11. option: null,
  12. information: {},
  13. }
  14. },
  15. props: {
  16. getJson: {
  17. type: Object,
  18. },
  19. },
  20. async mounted() {
  21. this.getEchart()
  22. },
  23. methods: {
  24. getEchart() {
  25. let that = this
  26. let myChart = echarts.init(document.getElementById(`3DMap`))
  27. let img2 = `image://data:image/png;base64,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`
  28. let uploadedDataURL = this.getJson
  29. let geoCoordMap = {
  30. 印江土家族苗族自治县: [108.405517, 27.997976],
  31. 石阡县: [108.229854, 27.519386],
  32. 江口县: [108.848427, 27.691904],
  33. 玉屏侗族自治县: [108.917882, 27.238024],
  34. 思南县: [108.255827, 27.941331],
  35. 德江县: [108.117317, 28.26094],
  36. 沿河土家族自治县: [108.495746, 28.560487],
  37. 松桃苗族自治县: [109.202627, 28.165419],
  38. 碧江区: [109.192117, 27.718745],
  39. 万山区: [109.21199, 27.51903],
  40. }
  41. let customerBatteryCityData = [
  42. {
  43. name: `印江土家族苗族自治县`,
  44. value: 0.5,
  45. adcode: `520625`,
  46. },
  47. { name: `石阡县`, value: 0.3, adcode: `520623` },
  48. { name: `江口县`, value: 0.5, adcode: `520621` },
  49. { name: `玉屏侗族自治县`, value: 0.5, adcode: `520622` },
  50. { name: `思南县`, value: 0.5, adcode: ` 520624` },
  51. { name: `德江县`, value: 0.5, adcode: `520626` },
  52. { name: `沿河土家族自治县`, value: 0.5, adcode: `520627` },
  53. { name: `松桃苗族自治县`, value: 0.5, adcode: `520628` },
  54. { name: `碧江区`, value: 0.5, adcode: `520602` },
  55. { name: `万山区`, value: 0.5, adcode: `520603` },
  56. ]
  57. echarts.registerMap(`guangdong`, uploadedDataURL, {})
  58. this.option = {
  59. tooltip: {
  60. trigger: `item`,
  61. triggerOn: `click`,
  62. showDelay: 0, // 浮层显示的延迟
  63. transitionDuration: 0.2, // 提示框浮层的移动动画过渡时间
  64. enterable: true,
  65. formatter: function (item) {
  66. if (item.componentSubType == `map`) {
  67. // 详情
  68. return
  69. }
  70. },
  71. // position: [10, 10],
  72. backgroundColor: `#fff`,
  73. },
  74. geo: [
  75. {
  76. map: `guangdong`,
  77. aspectScale: 1.2,
  78. roam: false, // 是否允许缩放
  79. zoom: 1, // 默认显示级别
  80. layoutSize: `95%`,
  81. layoutCenter: [`55%`, `50%`],
  82. itemStyle: {
  83. normal: {
  84. areaColor: {
  85. type: `linear-gradient`,
  86. x: 0,
  87. y: 400,
  88. x2: 0,
  89. y2: 0,
  90. colorStops: [
  91. {
  92. offset: 0,
  93. color: `rgba(37,108,190,0.3)`, // 0% 处的颜色
  94. },
  95. {
  96. offset: 1,
  97. color: `rgba(15,169,195,0.3)`, // 50% 处的颜色
  98. },
  99. ],
  100. global: true, // 缺省为 false
  101. },
  102. borderColor: `#4ecee6`,
  103. borderWidth: 1,
  104. },
  105. emphasis: {
  106. areaColor: {
  107. type: `linear-gradient`,
  108. x: 0,
  109. y: 300,
  110. x2: 0,
  111. y2: 0,
  112. colorStops: [
  113. {
  114. offset: 0,
  115. color: `rgba(37,108,190,1)`, // 0% 处的颜色
  116. },
  117. {
  118. offset: 1,
  119. color: `rgba(15,169,195,1)`, // 50% 处的颜色
  120. },
  121. ],
  122. global: false, // 缺省为 false
  123. },
  124. },
  125. },
  126. emphasis: {
  127. itemStyle: {
  128. areaColor: `#0160AD`,
  129. },
  130. label: {
  131. show: 0,
  132. color: `transparent`,
  133. },
  134. },
  135. zlevel: 3,
  136. },
  137. {
  138. map: `guangdong`,
  139. aspectScale: 1.2,
  140. roam: false, // 是否允许缩放
  141. zoom: 1, // 默认显示级别
  142. layoutSize: `95%`,
  143. layoutCenter: [`55%`, `50%`],
  144. itemStyle: {
  145. normal: {
  146. borderColor: `rgba(192,245,249,.6)`,
  147. borderWidth: 2,
  148. shadowColor: `#2C99F6`,
  149. shadowOffsetY: 0,
  150. shadowBlur: 120,
  151. areaColor: `rgba(29,85,139,.2)`,
  152. },
  153. },
  154. zlevel: 2,
  155. silent: true,
  156. },
  157. {
  158. map: `guangdong`,
  159. aspectScale: 1.2,
  160. roam: false, // 是否允许缩放
  161. zoom: 1, // 默认显示级别
  162. layoutSize: `95%`,
  163. layoutCenter: [`55%`, `51.5%`],
  164. itemStyle: {
  165. areaColor: `rgba(0,27,95,0.4)`,
  166. borderColor: `#004db5`,
  167. borderWidth: 1,
  168. },
  169. zlevel: 1,
  170. silent: true,
  171. },
  172. ],
  173. series: [
  174. // map
  175. {
  176. geoIndex: 0,
  177. showLegendSymbol: true,
  178. type: `map`,
  179. roam: true,
  180. label: {
  181. normal: {
  182. show: false,
  183. textStyle: {
  184. color: `#fff`,
  185. },
  186. },
  187. emphasis: {
  188. show: false,
  189. textStyle: {
  190. color: `#fff`,
  191. },
  192. },
  193. },
  194. itemStyle: {
  195. normal: {
  196. borderColor: `#2ab8ff`,
  197. borderWidth: 1.5,
  198. areaColor: `#12235c`,
  199. },
  200. emphasis: {
  201. areaColor: `#2AB8FF`,
  202. borderWidth: 0,
  203. color: `red`,
  204. },
  205. },
  206. map: `guangdong`, // 使用
  207. data: customerBatteryCityData,
  208. // data: this.difficultData //热力图数据 不同区域 不同的底色
  209. },
  210. // 柱状体的主干
  211. {
  212. type: `lines`,
  213. zlevel: 5,
  214. effect: {
  215. show: false,
  216. symbolSize: 5, // 图标大小
  217. },
  218. lineStyle: {
  219. width: 2, // 尾迹线条宽度
  220. color: `rgb(22,255,255, .6)`,
  221. opacity: 1, // 尾迹线条透明度
  222. curveness: 0, // 尾迹线条曲直度
  223. },
  224. label: {
  225. show: 0,
  226. position: `end`,
  227. formatter: `245`,
  228. },
  229. silent: true,
  230. data: lineData(),
  231. },
  232. // 柱状体的顶部
  233. {
  234. type: `scatter`,
  235. coordinateSystem: `geo`,
  236. geoIndex: 0,
  237. zlevel: 5,
  238. label: {
  239. normal: {
  240. show: true,
  241. formatter: function (params) {
  242. let name = params.data[2].name
  243. let value = params.data[2].fdl
  244. let text = `{fline|${name.slice(0, 2)}}`
  245. return text
  246. },
  247. color: `#fff`,
  248. rich: {
  249. fline: {
  250. // padding: [0, 25],
  251. color: `#fff`,
  252. fontSize: 14,
  253. fontWeight: 400,
  254. },
  255. tline: {
  256. // padding: [0, 27],
  257. color: `#ABF8FF`,
  258. fontSize: 12,
  259. },
  260. },
  261. },
  262. emphasis: {
  263. show: true,
  264. },
  265. },
  266. itemStyle: {
  267. color: `#000FFF`,
  268. opacity: 1,
  269. },
  270. symbol: img2,
  271. symbolSize: [100, 50],
  272. symbolOffset: [0, -20],
  273. z: 999,
  274. data: scatterData(),
  275. },
  276. // 柱状体的底部
  277. {
  278. geoIndex: 0,
  279. zlevel: 4,
  280. type: `effectScatter`,
  281. coordinateSystem: `geo`,
  282. rippleEffect: {
  283. scale: 10,
  284. brushType: `stroke`,
  285. },
  286. showEffectOn: `render`,
  287. label: {
  288. normal: {
  289. formatter: `{b}`,
  290. position: `bottom`,
  291. color: `#fff`,
  292. fontSize: 12,
  293. distance: 10,
  294. show: true,
  295. },
  296. },
  297. symbol: `circle`,
  298. symbolSize: [10, 5],
  299. itemStyle: {
  300. // color: '#F7AF21',
  301. color: `rgb(22,255,255, 1)`,
  302. opacity: 1,
  303. },
  304. data: scatterData2(),
  305. },
  306. // 底部外框
  307. {
  308. type: `scatter`,
  309. coordinateSystem: `geo`,
  310. geoIndex: 0,
  311. zlevel: 4,
  312. label: {
  313. show: false,
  314. },
  315. symbol: `circle`,
  316. symbolSize: [1, 1],
  317. itemStyle: {
  318. color: {
  319. type: `radial`,
  320. x: 0.5,
  321. y: 0.5,
  322. r: 0.5,
  323. colorStops: [
  324. {
  325. offset: 0,
  326. color: `rgb(22,255,255, 0)`, // 0% 处的颜色
  327. },
  328. {
  329. offset: 0.75,
  330. color: `rgb(22,255,255, 0)`, // 100% 处的颜色
  331. },
  332. {
  333. offset: 0.751,
  334. color: `rgb(22,255,255, 1)`, // 100% 处的颜色
  335. },
  336. {
  337. offset: 1,
  338. color: `rgb(22,255,255, 1)`, // 100% 处的颜色
  339. },
  340. ],
  341. global: false, // 缺省为 false
  342. },
  343. opacity: 1,
  344. },
  345. silent: true,
  346. data: scatterData2(),
  347. },
  348. ],
  349. }
  350. // 动态计算柱形图的高度(定一个max)
  351. function lineMaxHeight() {
  352. const maxValue = Math.max(
  353. ...customerBatteryCityData.map((item) => item.value)
  354. )
  355. return 0.3
  356. }
  357. // 柱状体的主干
  358. function lineData() {
  359. return customerBatteryCityData.map((item) => {
  360. return {
  361. coords: [
  362. geoCoordMap[item.name],
  363. [
  364. geoCoordMap[item.name][0],
  365. geoCoordMap[item.name][1] + item.value * lineMaxHeight(),
  366. ],
  367. ],
  368. }
  369. })
  370. }
  371. // 柱状体的顶部
  372. function scatterData() {
  373. return customerBatteryCityData.map((item) => {
  374. return [
  375. geoCoordMap[item.name][0],
  376. geoCoordMap[item.name][1] + item.value * lineMaxHeight(),
  377. item,
  378. ]
  379. })
  380. }
  381. // 柱状体的底部
  382. function scatterData2() {
  383. return customerBatteryCityData.map((item) => {
  384. return {
  385. // name: item.name,
  386. value: geoCoordMap[item.name],
  387. }
  388. })
  389. }
  390. myChart.setOption(this.option)
  391. myChart.on(`click`, function (params) {
  392. console.log(params)
  393. const idx = params.dataIndex
  394. that.$emit(`toView`, params.data.name)
  395. })
  396. },
  397. },
  398. }
  399. </script>
  400. <style lang="less" scoped>
  401. .chartsdom {
  402. width: 980px;
  403. height: 760px;
  404. .chartsdom {
  405. width: 100%;
  406. height: 100%;
  407. }
  408. }
  409. </style>