index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. <template>
  2. <div
  3. style="width: 100%; height: 100%"
  4. class="bs-design-wrap bs-bar"
  5. >
  6. <div
  7. :id="`chart${config.code}`"
  8. style="width: 100%; height: 100%"
  9. />
  10. </div>
  11. </template>
  12. <script>
  13. import 'insert-css'
  14. import * as echarts from 'echarts'
  15. import {nameMap} from './json/mapData.js'
  16. import commonMixins from 'data-room-ui/js/mixins/commonMixins.js'
  17. import paramsMixins from 'data-room-ui/js/mixins/paramsMixins'
  18. import linkageMixins from 'data-room-ui/js/mixins/linkageMixins'
  19. export default {
  20. name: 'MapCharts',
  21. mixins: [paramsMixins, commonMixins, linkageMixins],
  22. props: {
  23. id: {
  24. type: String,
  25. default: ''
  26. },
  27. config: {
  28. type: Object,
  29. default: () => ({})
  30. }
  31. },
  32. data () {
  33. return {
  34. charts: null,
  35. hasData: false,
  36. level:''
  37. }
  38. },
  39. computed: {
  40. Data () {
  41. return JSON.parse(JSON.stringify(this.config))
  42. }
  43. },
  44. watch: {
  45. Data: {
  46. handler (newVal, oldVal) {
  47. if (newVal.w !== oldVal.w || newVal.h !== oldVal.h) {
  48. this.$nextTick(() => {
  49. this.charts.resize()
  50. })
  51. }
  52. },
  53. deep: true
  54. }
  55. },
  56. mounted () {
  57. this.chartInit()
  58. },
  59. beforeDestroy () {
  60. this.charts?.clear()
  61. },
  62. methods: {
  63. chartInit () {
  64. const config = this.config
  65. // key和code相等,说明是一进来刷新,调用list接口
  66. if (this.config.code === this.config.key || this.isPreview) {
  67. // 改变数据
  68. this.changeDataByCode(config).then((res) => {
  69. // 改变样式
  70. // config = this.changeStyle(res)
  71. this.newChart(config)
  72. }).catch(() => {})
  73. } else {
  74. // 否则说明是更新,这里的更新只指更新数据(改变样式时是直接调取changeStyle方法),因为更新数据会改变key,调用chart接口
  75. this.changeData(config).then((res) => {
  76. // 初始化图表
  77. this.newChart(res)
  78. })
  79. }
  80. },
  81. dataFormatting (config, data) {
  82. config.option = {
  83. ...config.option,
  84. data: data?.data
  85. }
  86. return config
  87. },
  88. async newChart (config) {
  89. this.charts = echarts.init(
  90. document.getElementById(`chart${this.config.code}`)
  91. )
  92. this.level=config.customize.level
  93. const lines_coord = []
  94. let fromCoord=[]
  95. let coord=[]
  96. const mapUrl =config.customize.level==='world'?`${window.BS_CONFIG?.httpConfigs?.baseURL}/static/worldMap/world.json`:`${window.BS_CONFIG?.httpConfigs?.baseURL}/static/chinaMap/${config.customize.level}/${config.customize.dataMap}`
  97. this.$dataRoomAxios.get(decodeURI(mapUrl), {}, true).then(res=>{
  98. this.config.option.data.forEach(val => {
  99. lines_coord.push({value:val.value,msg:{...val}, coords:[[val.lat1,val.lng1],[val.lat2,val.lng2]]})
  100. if(val.type==='move_in'){
  101. coord.push({name:val.from,value:[val.lat1,val.lng1,val.value],msg:{...val}})
  102. fromCoord.push({name:val.to,value:[val.lat2,val.lng2,val.value],msg:{...val}})
  103. }
  104. if(val.type==='move_out'){
  105. coord.push({name:val.to,value:[val.lat2,val.lng2,val.value],msg:{...val}})
  106. fromCoord.push({name:val.from,value:[val.lat1,val.lng1,val.value],msg:{...val}})
  107. }
  108. })
  109. echarts.registerMap(config.customize.scope, res)
  110. const option = {
  111. nameMap:config.customize.level=='world'?nameMap:'',
  112. graphic: [
  113. ],
  114. geo: {
  115. map: config.customize.scope,
  116. zlevel: 10,
  117. show:true,
  118. layoutCenter: ['50%', '50%'],
  119. roam: true,
  120. layoutSize: "100%",
  121. zoom: 1,
  122. label: {
  123. // 通常状态下的样式
  124. normal: {
  125. show: config.customize.mapName,
  126. textStyle: {
  127. color: '#fff'
  128. }
  129. },
  130. // 鼠标放上去的样式
  131. emphasis: {
  132. textStyle: {
  133. color: '#fff'
  134. }
  135. }
  136. },
  137. // 地图区域的样式设置
  138. itemStyle: {
  139. normal: {
  140. borderColor: config.customize.mapLineColor,
  141. borderWidth: 1,
  142. areaColor: config.customize.areaColor,
  143. shadowColor: 'fffff',
  144. shadowOffsetX: -2,
  145. shadowOffsetY: 2,
  146. shadowBlur: 10
  147. },
  148. // 鼠标放上去高亮的样式
  149. emphasis: {
  150. areaColor: '#389BB7',
  151. borderWidth: 0
  152. }
  153. }
  154. },
  155. tooltip: {
  156. backgroundColor: config.customize.tooltipBackgroundColor,
  157. borderColor: config.customize.borderColor,
  158. show: true,
  159. textStyle: {
  160. color: config.customize.fontColor,
  161. },
  162. },
  163. series: [
  164. {
  165. type:'effectScatter',
  166. coordinateSystem: 'geo',
  167. zlevel: 15,
  168. symbolSize:8,
  169. rippleEffect: {
  170. period: 4, brushType: 'stroke', scale: 4
  171. },
  172. tooltip: {
  173. trigger: 'item',
  174. formatter(params) {
  175. const a= eval(config.customize.scatterFormatter)
  176. return a
  177. },
  178. },
  179. itemStyle:{
  180. color:config.customize.scatterColor,
  181. opacity:1
  182. },
  183. data:coord
  184. },
  185. {
  186. type:'effectScatter',
  187. coordinateSystem: 'geo',
  188. zlevel: 15,
  189. symbolSize:12,
  190. tooltip: {
  191. trigger: 'item',
  192. formatter(params) {
  193. const a= eval(config.customize.scatterFormatter)
  194. return a
  195. },
  196. },
  197. rippleEffect: {
  198. period: 6, brushType: 'stroke', scale: 8
  199. },
  200. itemStyle:{
  201. color:config.customize.scatterCenterColor,
  202. opacity:1
  203. },
  204. data:fromCoord
  205. },
  206. {
  207. type:'lines',
  208. coordinateSystem:'geo',
  209. zlevel: 15,
  210. tooltip: {
  211. trigger: 'item',
  212. formatter(params) {
  213. const a= eval(config.customize.lineFormatter)
  214. return a
  215. },
  216. },
  217. effect: {
  218. show: true, period: 5, trailLength: 0, symbol: config.customize.symbol, color:config.customize.symbolColor,symbolSize: config.customize.symbolSize,
  219. },
  220. lineStyle: {
  221. normal: {color: function(value){
  222. return '#ffffff'
  223. },width: 2, opacity: 0.6, curveness: 0.2 }
  224. },
  225. data:lines_coord
  226. }
  227. ]
  228. }
  229. if (config.customize.visual) {
  230. option.visualMap = {
  231. show: false,
  232. min: config.customize.range[0],
  233. max: config.customize.range[1],
  234. seriesIndex: [0,2],
  235. inRange: {
  236. color: config.customize.rangeColor
  237. }
  238. }
  239. }
  240. if(config.customize.down){
  241. // config?.customize?.graphic?.forEach((item,index)=>{
  242. option.graphic.push({
  243. type: "text",
  244. left: `250px`,
  245. top: "5%",
  246. style: {
  247. text: '中国',
  248. font: `bolder ${config.customize.fontSize}px "Microsoft YaHei", sans-serif`,
  249. fill: config.customize.fontGraphicColor,
  250. },
  251. onclick:async()=>{
  252. this.level='country'
  253. const index = option.graphic.findIndex(i => i.style.text === '中国');
  254. // 点击元素之后的所有元素全部删除
  255. option.graphic.splice(index + 1);
  256. const mapUrl =`${window.BS_CONFIG?.httpConfigs?.baseURL}/static/chinaMap/country/中华人民共和国.json`
  257. const map = await this.$dataRoomAxios.get(decodeURI(mapUrl), {}, true)
  258. option.geo.map = '中华人民共和国'
  259. this.changeData({...config,customize:{...config.customize,level:'country',scope:'中国'}})
  260. echarts.registerMap('中华人民共和国', map);
  261. this.charts.setOption(option, true);
  262. }
  263. },)
  264. // })
  265. }
  266. this.charts.setOption(option)
  267. this.charts.on('click', async(params)=> {
  268. const index = option.graphic.findIndex(i => i.style.text === params.name);
  269. if(params.name=='' || index !== -1) return
  270. if(config.customize.down===false||this.level==='province') return
  271. const idx = option.graphic.length + 1;
  272. option.graphic.push({
  273. type: "text",
  274. left: `${idx * 250}px`,
  275. top: "5%",
  276. style: {
  277. text: params.name,
  278. font: `bolder ${config.customize.fontSize}px "Microsoft YaHei", sans-serif`,
  279. fill: config.customize.fontGraphicColor,
  280. },
  281. onclick: async() => {
  282. const mapUrl =`${window.BS_CONFIG?.httpConfigs?.baseURL}/static/chinaMap/${params.name=='中华人民共和国'?'country':'province'}/${params.name}.json`
  283. const map = await this.$dataRoomAxios.get(decodeURI(mapUrl), {}, true)
  284. // 利用函数的作用域,可以直接拿上面的name来用
  285. const index = option.graphic.findIndex(i => i.style.text === params.name);
  286. // 点击元素之后的所有元素全部删除
  287. option.graphic.splice(index + 1);
  288. // 很多操作重复了,你可以将公共部分抽离出来
  289. option.geo.map = params.name;
  290. this.changeData({...config,customize:{...config.customize,level:'province',scope:params.name}})
  291. echarts.registerMap(params.name, map);
  292. this.charts.setOption(option, true);
  293. },
  294. });
  295. this.level='province'
  296. const mapUrl =`${window.BS_CONFIG?.httpConfigs?.baseURL}/static/chinaMap/province/${params.name}.json`
  297. const map = await this.$dataRoomAxios.get(decodeURI(mapUrl), {}, true)
  298. this.changeData({...config,customize:{...config.customize,level:'province',scope:params.name}})
  299. option.geo.map = params.name
  300. echarts.registerMap(params.name, map);
  301. this.charts.setOption(option, true);
  302. });
  303. })
  304. }
  305. }
  306. }
  307. </script>
  308. <style lang="scss" scoped>
  309. @import '../../assets/style/echartStyle';
  310. .light-theme {
  311. background-color: #ffffff;
  312. color: #000000;
  313. }
  314. .auto-theme {
  315. background-color: rgba(0, 0, 0, 0);
  316. }
  317. </style>