Map-l7.jsx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. import { onMount } from "solid-js";
  2. import { Scene, PointLayer, PolygonLayer, LineLayer, Marker } from '@antv/l7';
  3. import { Mapbox } from '@antv/l7-maps';
  4. // import { GaodeMap } from '@antv/l7-maps';
  5. // import DataSet from '@antv/data-set';
  6. import json from "../../../assets/file/100000_full.json"
  7. import utils from "../../../utils/index"
  8. // import config from "../../../base/config"
  9. import { getMapfull } from "../../../api/bigScreen"
  10. import "../../../assets/style/CommonBigScreenHome.css"
  11. let total = 0
  12. function Map(prop) {
  13. let anchorLayer = undefined,
  14. textLayer = undefined,
  15. $canvas = undefined,
  16. scene = undefined,
  17. source = [],
  18. li = [],
  19. cli = [
  20. '#87CEFA',
  21. '#00BFFF',
  22. '#7FFFAA',
  23. '#00FF7F',
  24. '#32CD32',
  25. '#F0E68C',
  26. '#FFD700',
  27. '#FF7F50',
  28. '#FF6347',
  29. '#FF0000'
  30. ];
  31. // TODO: 高德地图
  32. /***
  33. * 高德天气,暂时不用只能在https下可以
  34. */
  35. // function getWatcher(local) {
  36. // getGeography({
  37. // radius: 1,
  38. // key: config.webToke,
  39. // location: [local.lng, local.lat].join()
  40. // }).then(res => {
  41. // let adcode = res.regeocode.addressComponent.adcode.split("");
  42. // getWeather({
  43. // key: config.webToke,
  44. // // city: adcode[0] + adcode[1] + adcode[2] + adcode[3] + "00"
  45. // city: 610100
  46. // }).then(r => prop.setfun(r))
  47. // })
  48. // }
  49. function TrendChart() {
  50. scene = new Scene({
  51. id: $canvas,
  52. logoVisible: false,
  53. // map: new GaodeMap({
  54. // style: 'blank',
  55. // pitch: 50,
  56. // center: [108.2, 35],
  57. // zoom: 2,
  58. // maxZoom: 7,
  59. // minZoom: 7,
  60. // token: config.gaodeToken
  61. // })
  62. map: new Mapbox({
  63. pitch: 60,
  64. center: [108.2, 35.6],
  65. style: 'blank',
  66. zoom: 5.6,
  67. minZoom: 5.4,
  68. })
  69. });
  70. scene.setMapStatus({ dragEnable: false });
  71. scene.on('loaded', () => {
  72. // 获取地理/天气信息
  73. // AMap.convertFrom([prop.Geography.longitude, prop.Geography.latitude], 'gps', function (status, result) {
  74. // if (result.info !== 'ok') return
  75. // console.log(result)
  76. // const local = result.locations[0] || { Q: -190, R: -190, lat: -190, lng: -1906 }
  77. // scene.setCenter([local.lng, local.lat])
  78. // getWatcher(local)
  79. // });
  80. getMapfull().then(data => {
  81. li = data && data.features && data.features.length ? data.features : [];
  82. for (let i = 0; i < li.length; i++) {
  83. const v = li[i].properties || { center: [] };
  84. const size = prop.li.find(item => item.area === v.name).usrcount
  85. total += size;
  86. const Data = {
  87. name: v.name,
  88. lng: v.center[0],
  89. lat: v.center[1],
  90. size // 自定义数据
  91. };
  92. source.push(Data);
  93. }
  94. const layer = new PointLayer()
  95. .source(source, {
  96. parser: {
  97. type: 'json',
  98. x: 'lng',
  99. y: 'lat'
  100. }
  101. })
  102. .shape('circle')
  103. .color('backgoundColor')
  104. .size(42);
  105. // 上层线条
  106. const lineUp = new LineLayer({ zIndex: 2, blend: "normal" })
  107. .source(data)
  108. .shape('line')
  109. .color('rgb(0,255,255)')
  110. .size(0.5)
  111. .style({
  112. raisingHeight: 150000,
  113. opacity: 0.8,
  114. })
  115. .animate({
  116. interval: 1, // 间隔
  117. duration: 1, // 持续时间,延时
  118. trailLength: 3 // 流线长度
  119. });
  120. // 围栏
  121. const bottomLayer = new LineLayer({ zIndex: 0, blend: "normal" })
  122. .source(json)
  123. .shape('wall')
  124. .color('rgb(255,255,255)')
  125. .size(10)
  126. .style({
  127. heightfixed: true,
  128. opacity: 1,
  129. sourceColor: '#0DCCFF',
  130. });
  131. // 高度
  132. const gd = new PolygonLayer({ zIndex: 1, blend: "normal" })
  133. .source(data)
  134. .size(150000)
  135. .shape('extrude')
  136. .color("#3194fb")
  137. // .color("name", cli)
  138. .style({
  139. heightfixed: true,
  140. pickLight: true,
  141. raisingHeight: 0,
  142. opacity: 0.8,
  143. });
  144. // 水波
  145. const waveLayer = new PointLayer({ zIndex: 2, blend: 'normal' })
  146. .source(source,
  147. {
  148. parser: {
  149. type: 'json',
  150. x: 'lng',
  151. y: 'lat'
  152. }
  153. }
  154. )
  155. .shape('circle')
  156. .color("name", cli)
  157. .size('size', v => {
  158. // let p = v / source[0].size;
  159. // p < 0.3 ? p = (p + 0.2).toFixed(2) - 0 : '';
  160. let p = (v / total * 100).toFixed(2) - 0;
  161. if (p < 30) return p + 30;
  162. return p
  163. })
  164. .animate(true)
  165. .style({
  166. raisingHeight: 0,
  167. });
  168. // 柱子
  169. // const barLayer = new PointLayer({ zIndex: 2, depth: false })
  170. // .source(
  171. // source,
  172. // {
  173. // parser: {
  174. // type: 'json',
  175. // x: 'lng',
  176. // y: 'lat'
  177. // }
  178. // }
  179. // )
  180. // .shape('cylinder')
  181. // .color("name", cli)
  182. // .size('size', v => {
  183. // let p = v / source[0].size;
  184. // p < 0.3 ? p = (p + 0.2).toFixed(2) - 0 : '';
  185. // return [5, 5, p * 100]
  186. // })
  187. // .animate(true)
  188. // .style({
  189. // raisingHeight: 1,
  190. // opacityLinear: {
  191. // enable: true, // true - false
  192. // dir: 'up' // up - down
  193. // },
  194. // lightEnable: false
  195. // });
  196. scene.addLayer(gd);
  197. scene.addLayer(bottomLayer);
  198. scene.addLayer(layer);
  199. scene.addLayer(lineUp);
  200. scene.addLayer(waveLayer);
  201. // scene.addLayer(barLayer);
  202. timeout()
  203. })
  204. });
  205. }
  206. function timeout() {
  207. // scene.setCenter([source[index].lng, source[index].lat])
  208. for (let index = 0; index < source.length; index++) {
  209. console.log(source[index])
  210. // anchorLayer && scene.removeAllMakers();
  211. // textLayer && scene.removeLayer(textLayer);
  212. var el = document.createElement('div'), son = document.createElement('div');
  213. el.className = 'tooltip';
  214. son.className = "tooltipSon";
  215. son.innerHTML = `<div>${source[index].name}</div>${utils.formatNumber(source[index].size, 2)}`;
  216. el.appendChild(son);
  217. // toolpit
  218. anchorLayer = new Marker({
  219. element: el
  220. }).setLnglat([source[index].lng, source[index].lat]);
  221. const text = [], province = [];
  222. for (let i = 0; i < source.length; i++) {
  223. if (index === i) {
  224. li[i].value = 10000 * Math.random();
  225. li[i] && province.push(li[i]);
  226. continue
  227. }
  228. const v = source[i];
  229. text.push(v);
  230. }
  231. // 文字
  232. textLayer = new PointLayer({ zIndex: 1, blend: "normal" })
  233. .source(text, {
  234. parser: {
  235. type: 'json',
  236. x: 'lng',
  237. y: 'lat'
  238. }
  239. })
  240. .shape('name', 'text')
  241. .size(14)
  242. .style({
  243. textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left
  244. spacing: 2, // 字符间距
  245. padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
  246. stroke: '#FFFFFF', // 描边颜色
  247. strokeWidth: 0.2, // 描边宽度
  248. raisingHeight: 1,
  249. textAllowOverlap: true
  250. });
  251. scene.addLayer(textLayer);
  252. scene.addMarker(anchorLayer);
  253. }
  254. }
  255. onMount(() => {
  256. TrendChart()
  257. })
  258. const openBigData = () => {
  259. window.open("http://djweb.smcic.net/centerRelay/center.html?" + Date.now())
  260. }
  261. return (
  262. <div class="livRang map" style={{
  263. width: `${prop.width}px`
  264. }}>
  265. <div class="head">
  266. {prop.title}
  267. <div onClick={openBigData} class="btn">大数据平台登录入口</div>
  268. </div>
  269. <div ref={$canvas} style={{
  270. width: `${prop.width}px`,
  271. height: `${prop.height}px`,
  272. position: 'relative'
  273. }}></div>
  274. </div>
  275. );
  276. }
  277. export default Map;