factoryindex4.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. <template>
  2. <view class="page">
  3. <!-- 1. 顶部标题 -->
  4. <view class="header">
  5. <text class="title">{{title}}</text>
  6. <!-- 新增地图按钮 -->
  7. <image
  8. class="map-btn"
  9. src="/static/img/tab.png"
  10. mode="aspectFit"
  11. @tap="goMap"
  12. />
  13. </view>
  14. <!-- 2. 轮播图 -->
  15. <swiper
  16. class="swiper"
  17. circular
  18. :indicator-dots="true"
  19. :autoplay="true"
  20. :interval="3000"
  21. :duration="800"
  22. >
  23. <swiper-item v-for="(item, index) in picture" :key="index">
  24. <image :src="item" class="swiper-item" mode="aspectFill" />
  25. </swiper-item>
  26. </swiper>
  27. <!-- 3. 地图 -->
  28. <view class="map-box">
  29. <view @touchend="onTouchEnd" class="map-wrap">
  30. <canvas canvas-id="ydChart" id="ydChart" class="map-canvas" />
  31. </view>
  32. </view>
  33. </view>
  34. </template>
  35. <script>
  36. import * as echarts from 'echarts'
  37. import loginService from "@/api/auth/loginService";
  38. export default {
  39. data() {
  40. return {
  41. chart: null,
  42. title:'盐都区闲置厂房分布图',
  43. /* 轮播图示例,换成你的真实图片即可 */
  44. picture:["https://ydwqfw.com.cn/yd_qycpfbH5/bg1.jpg",
  45. "https://ydwqfw.com.cn/yd_qycpfbH5/bg2.jpg",
  46. "https://ydwqfw.com.cn/yd_qycpfbH5/bg3.jpg",
  47. "https://ydwqfw.com.cn/yd_qycpfbH5/bg4.jpg"],
  48. parkList2: [],
  49. buildingMap: new Map() // 新增
  50. }
  51. },
  52. async onReady() {
  53. const json = await this.loadGeoJSON()
  54. echarts.registerMap('yanduqu', json)
  55. let canvasNode
  56. // #ifdef H5
  57. canvasNode = document.getElementById('ydChart')
  58. // #endif
  59. // #ifndef H5
  60. canvasNode = await new Promise(resolve => {
  61. uni.createSelectorQuery()
  62. .in(this)
  63. .select('#ydChart')
  64. .node(res => resolve(res.node))
  65. .exec()
  66. })
  67. // #endif
  68. this.chart = echarts.init(canvasNode, null, {
  69. width : uni.getSystemInfoSync().windowWidth,
  70. height: uni.getSystemInfoSync().windowHeight * 0.6 // 地图占屏幕 50%
  71. })
  72. this.getList()
  73. },
  74. methods: {
  75. getList() {
  76. loginService.getParkList().then(({
  77. data
  78. }) => {
  79. let alls = 0
  80. data.forEach(item => { alls += item.building_cnt })
  81. for(var i = 0; i < data.length; i++){
  82. alls=alls+data[i].building_cnt;
  83. if(data[i].label.indexOf("高新区") != -1){
  84. data[i].label='盐龙'
  85. }
  86. // if(data[i].label.indexOf("大冈") != -1){
  87. // data[i].label='大冈镇'
  88. // }else if(data[i].label.indexOf("大纵湖") != -1){
  89. // data[i].label='大纵湖镇'
  90. // }else if(data[i].label.indexOf("学富") != -1){
  91. // data[i].label='学富镇'
  92. // }else if(data[i].label.indexOf("尚庄") != -1){
  93. // data[i].label='尚庄镇'
  94. // }else if(data[i].label.indexOf("张庄") != -1){
  95. // data[i].label='张庄镇'
  96. // }else if(data[i].label.indexOf("楼王") != -1){
  97. // data[i].label='楼王镇'
  98. // }else if(data[i].label.indexOf("潘黄") != -1){
  99. // data[i].label='潘黄街道'
  100. // }else if(data[i].label.indexOf("盐渎") != -1){
  101. // data[i].label='盐渎街道'
  102. // }else if(data[i].label.indexOf("秦南") != -1){
  103. // data[i].label='秦南镇'
  104. // }else if(data[i].label.indexOf("郭猛") != -1){
  105. // data[i].label='郭猛镇'
  106. // }else if(data[i].label.indexOf("高新区") != -1){
  107. // data[i].label='盐龙街道'
  108. // }else if(data[i].label.indexOf("龙冈") != -1){
  109. // data[i].label='龙冈镇'
  110. // }
  111. }
  112. this.allcount = alls
  113. this.parkList2 = data
  114. /* 构造 name -> building_cnt 映射表 */
  115. this.buildingMap = new Map(data.map(item => [item.label, item.building_cnt]))
  116. /* 插入“全部”汇总行 */
  117. this.parkList2.unshift({ total_area: 0, total_idle_area: 0, building_cnt: alls, label: '全部' })
  118. this.renderMap()
  119. }).catch(e => {
  120. })
  121. },
  122. loadGeoJSON() {
  123. return new Promise((resolve, reject) => {
  124. uni.request({
  125. url: './static/yandu.json',
  126. method: 'GET',
  127. success: res => resolve(res.data),
  128. fail: reject
  129. })
  130. })
  131. },
  132. goList(parkName) {
  133. // 真正跳转
  134. uni.navigateTo({
  135. url: `/pages/factoryBuildings/factoryBuildingsList?parkid=${parkName}`
  136. })
  137. },
  138. goMap() {
  139. uni.navigateTo({
  140. url: `/pages/index/factoryindex` // 换成你的地图页面路径
  141. })
  142. },
  143. onTouchEnd(e) {
  144. const touch = e.changedTouches[0]
  145. uni.createSelectorQuery()
  146. .in(this)
  147. .select('.map-wrap')
  148. .boundingClientRect(rect => {
  149. const dpr = uni.getSystemInfoSync().pixelRatio // 关键1:拿到 dpr
  150. const xCss = touch.clientX - rect.left // CSS 像素
  151. const yCss = touch.clientY - rect.top
  152. const xCanvas = xCss ; // 关键2:转成 canvas 物理像素
  153. const yCanvas = yCss ;
  154. // 用物理像素判断
  155. const inGeo = this.chart.containPixel('geo', [xCanvas, yCanvas])
  156. if (inGeo) {
  157. // 拿到逻辑坐标(供 emit 用)
  158. const [lng, lat] = this.chart.convertFromPixel('geo', [xCanvas, yCanvas])
  159. // 直接 emit 一个 click 事件,把 name 传出去
  160. // 先用 chart.getOption().series[0].data 里匹配,这里简化:用 convert 回来的坐标反查
  161. const geoModel = this.chart.getModel().getComponent('geo', 0)
  162. const region = geoModel.coordinateSystem.getRegionByCoord([lng, lat])
  163. const name = region ? region.name : ''
  164. if (region) {
  165. this.goList(name)
  166. }
  167. }
  168. })
  169. .exec()
  170. },
  171. renderMap() {
  172. const mapData = []
  173. /* 如果你知道所有镇名,可以写死;否则把 geoJSON 里的名字读出来即可 */
  174. const townNames = ['台创园', '大冈镇', '大纵湖镇', '学富镇', '尚庄镇', '张庄街道', '楼王镇','潘黄街道','盐渎街道', '秦南镇', '郭猛镇', '盐龙街道', '龙冈镇']
  175. townNames.forEach(name => {
  176. mapData.push({
  177. name,
  178. value: this.buildingMap.get(name) || 0 // 没有就按 0 处理
  179. })
  180. })
  181. const option = {
  182. geo: [{
  183. map: 'yanduqu',
  184. roam: true,
  185. aspectScale: 1.2,
  186. zoom: 1.3,
  187. itemStyle: {
  188. normal: {
  189. areaColor: {
  190. type: 'linear-gradient',
  191. x: 0,
  192. y: 400,
  193. x2: 0,
  194. y2: 0,
  195. colorStops: [{
  196. offset: 0,
  197. color: 'rgba(37,108,190,0.8)' // 0% 处的颜色
  198. }, {
  199. offset: 1,
  200. color: 'rgba(15,169,195,0.8)' // 50% 处的颜色
  201. }],
  202. global: true // 缺省为 false
  203. },
  204. borderColor: '#4ecee6',
  205. borderWidth: 1
  206. },
  207. emphasis: {
  208. areaColor: {
  209. type: 'linear-gradient',
  210. x: 0,
  211. y: 300,
  212. x2: 0,
  213. y2: 0,
  214. colorStops: [{
  215. offset: 0,
  216. color: 'rgba(37,108,190,1)' // 0% 处的颜色
  217. }, {
  218. offset: 1,
  219. color: 'rgba(15,169,195,1)' // 50% 处的颜色
  220. }],
  221. global: false // 缺省为 false
  222. },
  223. }
  224. },
  225. emphasis: {
  226. itemStyle: { areaColor: '#ffca28' }
  227. },
  228. // 关键:打开标签
  229. label: {
  230. show: true, // 默认显示名称
  231. color: '#fff', // 文字颜色
  232. fontSize: 12, // 字号
  233. fontWeight: 'bold',
  234. /* 关键:让标签显示两行 */
  235. formatter: params => {
  236. const cnt = this.buildingMap.get(params.name) || 0
  237. return `${params.name} ${cnt} 处`
  238. //return `${params.name}`
  239. }
  240. }
  241. }],
  242. series: [{ type: 'map', geoIndex: 0, data: mapData },]
  243. }
  244. this.chart.setOption(option)
  245. this.chart.on('click', params => {
  246. uni.navigateTo({
  247. url: `/pages/factoryBuildings/factoryBuildingsList?parkid=${params.name}`
  248. })
  249. })
  250. }
  251. }
  252. }
  253. </script>
  254. <style scoped>
  255. .page {
  256. display: flex;
  257. flex-direction: column;
  258. height: 100vh;
  259. background: #f5f5f5;
  260. }
  261. /* 顶部标题 */
  262. .header {
  263. position: relative; /* 让子元素绝对定位参照它 */
  264. padding: 20rpx 0;
  265. text-align: center;
  266. background: #fff;
  267. }
  268. .title {
  269. font-size: 36rpx;
  270. font-weight: bold;
  271. color: #333;
  272. }
  273. /* 右上角地图按钮 */
  274. .map-btn {
  275. position: absolute;
  276. right: 30rpx;
  277. top: 50%;
  278. transform: translateY(-50%);
  279. width: 48rpx;
  280. height: 48rpx;
  281. }
  282. /* 轮播图 */
  283. .swiper {
  284. width: 100%;
  285. height: 300rpx;
  286. }
  287. .swiper-item {
  288. width: 100%;
  289. height: 100%;
  290. }
  291. /* 地图容器 */
  292. .map-box {
  293. flex: 1;
  294. width: 100%;
  295. /* background: #003366; */ /* 任意你想要的深色 */
  296. }
  297. .map-canvas {
  298. width: 100%;
  299. height: 100%;
  300. }
  301. </style>