index.vue 16 KB

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