components_ncp_china_vue.html 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. <!--********************************************************************
  2. * Copyright© 2000 - 2021 SuperMap Software Co.Ltd. All rights reserved.
  3. *********************************************************************-->
  4. <!DOCTYPE html>
  5. <html>
  6. <head>
  7. <meta charset="UTF-8" />
  8. <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport" />
  9. <title></title>
  10. </head>
  11. <body style="margin: 0; overflow: hidden; background: #fff; width: 100%; height: 100%; position: absolute; top: 0;">
  12. <div id="main">
  13. <sm-web-map :map-options="mapOptions" @load="mapLoaded" @click="mapClicked"></sm-web-map>
  14. <div id="group">
  15. <sm-radio-group class="radio-group" v-model="type" default-value="china-riskLevel" size="large">
  16. <sm-radio-button value="china-riskLevel" data-i18n="resources.text_ncp_riskLevel"></sm-radio-button>
  17. <sm-radio-button
  18. value="china-incrementConfirmed"
  19. data-i18n="resources.text_ncp_incrementConfirmed"
  20. ></sm-radio-button>
  21. <sm-radio-button
  22. value="china-nowConfirmed"
  23. data-i18n="resources.text_ncp_nowConfirmed"
  24. ></sm-radio-button>
  25. <sm-radio-button value="china-incidence" data-i18n="resources.text_ncp_incidence"></sm-radio-button>
  26. </sm-radio-group>
  27. <br />
  28. <sm-indicator :title="title" unit="" mode="horizontal" :num="num" font-size="44px" font-weight="400">
  29. </sm-indicator>
  30. <sm-text
  31. :title="time"
  32. text-color="rgba(255, 255, 255, 0.6)"
  33. :font-style='{ fontSize: "18px", fontWeight: "400" ,display: "block"}'
  34. >
  35. </sm-text>
  36. </div>
  37. <sm-image
  38. repeat="noRepeat"
  39. src="../img/online-qr.png"
  40. style="position: absolute; bottom: 32px; right: 16px; z-index: 1000; height: 88px; width: 88px;"
  41. ></sm-image>
  42. </div>
  43. <script type="text/javascript" include="vue" src="../js/include-web.js"></script>
  44. <script
  45. include="iclient-mapboxgl-vue,mapbox-gl-enhance"
  46. src="../../dist/mapboxgl/include-mapboxgl.js"
  47. ></script>
  48. <script src="../data/ncp/ProvinceData1M.js"></script>
  49. <script src="../data/ncp/province_center_data.js"></script>
  50. <style>
  51. #main {
  52. margin: 0 auto;
  53. width: 100%;
  54. height: 100%;
  55. }
  56. #group {
  57. position: absolute;
  58. left: 10px;
  59. top: 10px;
  60. z-index: 1000;
  61. }
  62. .sm-component-radio-button-wrapper {
  63. color: #fff;
  64. background: #333333;
  65. padding: 0px 10px;
  66. }
  67. .mapboxgl-popup-content {
  68. border: solid 1px #464646;
  69. background-color: #464646;
  70. border-radius: 7px;
  71. padding: 16px;
  72. z-index: 3;
  73. font-size: 20px;
  74. text-align: center;
  75. color: #ffffff;
  76. line-height: 30px;
  77. }
  78. .mapboxgl-popup-tip {
  79. display: none;
  80. }
  81. .sm-component-radio-button-wrapper-checked {
  82. color: #0081e2 !important;
  83. border-color: #0081e2 !important;
  84. box-shadow: -1px 0 0 0 #0081e2 !important;
  85. background: #333333 !important;
  86. }
  87. .sm-component-radio-button-wrapper:hover {
  88. color: #0081e2;
  89. }
  90. @media screen and (max-width: 768px) {
  91. .sm-component-count-to__numItem {
  92. font-size: 32px !important;
  93. }
  94. .sm-component-indicator__title {
  95. font-size: 20px !important;
  96. }
  97. .sm-component-indicator__num {
  98. font-size: 32px !important;
  99. }
  100. .sm-component-text {
  101. font-size: 16px !important;
  102. }
  103. #group {
  104. margin-top: 28px;
  105. }
  106. .sm-component-radio-group-large .sm-component-radio-button-wrapper {
  107. height: 32px;
  108. line-height: 30px;
  109. font-size: 14px;
  110. padding: 0 10px;
  111. }
  112. }
  113. </style>
  114. <script>
  115. var styles = {
  116. 'china-riskLevel': {
  117. tooltip: function (properties) {
  118. if (properties.daysNoConfirmedAdd >= 3) {
  119. return resources.text_ncp_riskLevel_tooltip
  120. .replace('{name}', properties['省份'])
  121. .replace('{daysNoConfirmedAdd}', properties.daysNoConfirmedAdd);
  122. }
  123. return resources.text_ncp_riskLevel_tooltip1
  124. .replace('{name}', properties['省份'])
  125. .replace('{daysMaxConfirmedAdd}', properties.daysMaxConfirmedAdd)
  126. .replace('{confirmedAdd}', properties.confirmedAdd);
  127. },
  128. title: resources.text_ncp_riskLevel_title,
  129. 'fill-color': [
  130. 'case',
  131. ['>=', ['get', 'daysMaxConfirmedAdd'], 10],
  132. '#FC9A6B',
  133. ['>=', ['get', 'daysMaxConfirmedAdd'], 1],
  134. '#FDCD8C',
  135. ['>=', ['get', 'daysNoConfirmedAdd'], 14],
  136. '#53AB5E',
  137. ['>=', ['get', 'daysNoConfirmedAdd'], 7],
  138. '#ADDD8E',
  139. ['>=', ['get', 'daysNoConfirmedAdd'], 3],
  140. '#D6FDB9',
  141. '#F4F4F4'
  142. ],
  143. 'text-field': [
  144. 'concat',
  145. ['get', '省份'],
  146. ['case', ['>', ['get', 'daysNoConfirmedAdd'], 0], ['get', 'daysNoConfirmedAdd'], '']
  147. ],
  148. 'line-color': '#5F5F5F'
  149. },
  150. 'china-incrementConfirmed': {
  151. tooltip: function (properties) {
  152. if (isNaN(properties['confirmedAdd'])) {
  153. return resources.text_ncp_nodata_tooltip.replace('{name}', properties['省份']);
  154. }
  155. return resources.text_ncp_incrementConfirmed_tooltip
  156. .replace('{name}', properties['省份'])
  157. .replace('{confirmedAdd}', properties['confirmedAdd']);
  158. },
  159. title: resources.text_ncp_incrementConfirmed_title,
  160. 'fill-color': [
  161. 'case',
  162. ['has', 'confirmedAdd'],
  163. [
  164. 'case',
  165. ['>=', ['get', 'confirmedAdd'], 200],
  166. '#d7301f',
  167. ['>=', ['get', 'confirmedAdd'], 100],
  168. '#ef6548',
  169. ['>=', ['get', 'confirmedAdd'], 50],
  170. '#fc8d59',
  171. ['>=', ['get', 'confirmedAdd'], 10],
  172. '#fdbb84',
  173. ['>=', ['get', 'confirmedAdd'], 1],
  174. '#fdd49e',
  175. '#F4F4F4'
  176. ],
  177. '#D9D9D9'
  178. ],
  179. 'text-field': [
  180. 'concat',
  181. ['get', '省份'],
  182. ['case', ['>', ['get', 'confirmedAdd'], 0], ['concat', '+', ['get', 'confirmedAdd']], '']
  183. ],
  184. 'line-color': '#83838D'
  185. },
  186. 'china-nowConfirmed': {
  187. tooltip: function (properties) {
  188. if (isNaN(properties['nowConfirmed'])) {
  189. return resources.text_ncp_nodata_tooltip.replace('{name}', properties['省份']);
  190. }
  191. return resources.text_ncp_nowConfirmed_tooltip
  192. .replace('{name}', properties['省份'])
  193. .replace('{nowConfirmed}', properties['nowConfirmed']);
  194. },
  195. title: resources.text_ncp_nowConfirmed_title,
  196. 'fill-color': [
  197. 'case',
  198. ['has', 'nowConfirmed'],
  199. [
  200. 'case',
  201. ['>=', ['get', 'nowConfirmed'], 200],
  202. '#d7301f',
  203. ['>=', ['get', 'nowConfirmed'], 100],
  204. '#ef6548',
  205. ['>=', ['get', 'nowConfirmed'], 50],
  206. '#fc8d59',
  207. ['>=', ['get', 'nowConfirmed'], 10],
  208. '#fdbb84',
  209. ['>=', ['get', 'nowConfirmed'], 1],
  210. '#fdd49e',
  211. '#F4F4F4'
  212. ],
  213. '#D9D9D9'
  214. ],
  215. 'text-field': ['get', '省份'],
  216. 'line-color': '#83838D'
  217. },
  218. 'china-incidence': {
  219. tooltip: function (properties) {
  220. return resources.text_ncp_incidence_tooltip
  221. .replace('{name}', properties['省份'])
  222. .replace('{incidence}', properties['incidence'])
  223. .replace('{confirmed}', properties['confirmed'])
  224. .replace('{population}', parseInt(properties['population'] / 10000));
  225. },
  226. title: resources.text_ncp_incidence_title,
  227. 'fill-color': [
  228. 'case',
  229. ['>=', ['get', 'incidence'], 5],
  230. '#6a51a3',
  231. ['>=', ['get', 'incidence'], 1.5],
  232. '#7f7dba',
  233. ['>=', ['get', 'incidence'], 1],
  234. '#9e9ac8',
  235. ['>=', ['get', 'incidence'], 0.5],
  236. '#dadaeb',
  237. ['>=', ['get', 'incidence'], 0],
  238. '#efedf5',
  239. '#F4F4F4'
  240. ],
  241. 'text-field': ['get', '省份'],
  242. 'line-color': '#83838D'
  243. }
  244. };
  245. new Vue({
  246. el: '#main',
  247. data() {
  248. var attribution =
  249. "<a href='https://www.mapbox.com/about/maps/' target='_blank'>© Mapbox </a>" +
  250. " with <span>© <a href='https://iclient.supermap.io' target='_blank'>SuperMap iClient</a> | </span>" +
  251. " Map Data <span>© <a href='https://www.supermapol.com/' target='_blank'>SuperMap Online</a></span> ";
  252. return {
  253. type: 'china-riskLevel',
  254. time: '04/01 24:00',
  255. nums: {
  256. 'china-incrementConfirmed': 0,
  257. 'china-nowConfirmed': 0,
  258. 'china-incidence': 0,
  259. 'china-confirmed': 0
  260. },
  261. mapOptions: {
  262. container: 'map', // container id
  263. style: {
  264. version: 8,
  265. glyphs: 'https://ncov.supermapol.com/statichtml/font/{fontstack}/{range}.pbf',
  266. sources: {
  267. 'raster-tiles': {
  268. attribution: attribution,
  269. type: 'raster',
  270. tiles: [
  271. 'https://maptiles.supermapol.com/iserver/services/map-China/rest/maps/China_Dark_Nolable'
  272. ],
  273. transparent: false,
  274. rasterSource: 'iserver',
  275. tileSize: 256
  276. }
  277. },
  278. layers: [
  279. {
  280. id: 'simple-tiles',
  281. type: 'raster',
  282. source: 'raster-tiles',
  283. minzoom: 0,
  284. maxzoom: 22
  285. }
  286. ]
  287. },
  288. bounds: [
  289. [72.10274031198492, 2.481417743284723],
  290. [137.0563536922412, 54.36513803178008]
  291. ],
  292. center: [105.9002304535943, 31.9592716277851],
  293. minZoom: 1.5,
  294. maxZoom: 6,
  295. zoom: 3.55
  296. }
  297. };
  298. },
  299. computed: {
  300. num() {
  301. return this.nums[this.type] || '';
  302. },
  303. title() {
  304. return styles[this.type].title;
  305. }
  306. },
  307. watch: {
  308. type(val) {
  309. if (this.popup) {
  310. this.popup.remove();
  311. }
  312. this.map.setPaintProperty('china', 'fill-color', styles[val]['fill-color']);
  313. this.map.setPaintProperty('china-strokeLine', 'line-color', styles[val]['line-color']);
  314. this.map.setLayoutProperty('china-label', 'text-field', styles[val]['text-field']);
  315. }
  316. },
  317. created() {
  318. SuperMap.Components.setTheme({
  319. textColor: 'rgba(255, 255, 255, 0.85)',
  320. background: 'rgba(0, 0, 0, 0)',
  321. colorGroup: ['rgb(225, 2, 0)']
  322. });
  323. $.get(
  324. 'https://ncpviz.oss-cn-beijing.aliyuncs.com/ncpviz/ui.json?time=' + new Date().getTime(),
  325. function (response) {
  326. document.title = getTitle(response);
  327. }
  328. );
  329. },
  330. methods: {
  331. mapLoaded(e) {
  332. this.map = e.map;
  333. $.get(
  334. 'https://ncpviz.oss-cn-beijing.aliyuncs.com/ncpviz/ncp.json?time=' + new Date().getTime(),
  335. function (response) {
  336. // this.time = resources.text_ncp_time.replace('{time}', response.time);
  337. var latestProvinceData = this.getLatestProvinceData(response);
  338. this.map.addSource('china', {
  339. type: 'geojson',
  340. data: ProvinceData
  341. });
  342. this.map.addLayer({
  343. id: 'china',
  344. type: 'fill',
  345. source: 'china',
  346. layout: {},
  347. paint: {
  348. 'fill-color': styles[this.type]['fill-color']
  349. }
  350. });
  351. this.map.addLayer({
  352. id: 'china-strokeLine',
  353. type: 'line',
  354. source: 'china',
  355. layout: {},
  356. paint: {
  357. 'line-width': 0.5,
  358. 'line-color': styles[this.type]['line-color'],
  359. 'line-opacity': 1
  360. }
  361. });
  362. this.map.addSource('china-label', {
  363. type: 'geojson',
  364. data: ProvincesCenterData
  365. });
  366. this.map.addLayer({
  367. id: 'china-label',
  368. type: 'symbol',
  369. source: 'china-label',
  370. layout: {
  371. 'text-field': styles[this.type]['text-field'],
  372. 'text-font': ['Microsoft YaHei Regular'],
  373. 'text-size': 14,
  374. 'text-allow-overlap': {
  375. stops: [
  376. [2.5, false],
  377. [3, true]
  378. ]
  379. },
  380. 'text-letter-spacing': 0
  381. },
  382. paint: {
  383. 'text-color': 'white',
  384. 'text-opacity': 1,
  385. 'text-halo-color': '#696868',
  386. 'text-halo-width': 1.5
  387. }
  388. });
  389. this.map.addSource('line', {
  390. type: 'geojson',
  391. data: {
  392. type: 'FeatureCollection',
  393. features: [
  394. {
  395. type: 'Feature',
  396. geometry: {
  397. type: 'LineString',
  398. coordinates: [
  399. [127.53, 50.22],
  400. [97.5, 24.06]
  401. ]
  402. }
  403. }
  404. ]
  405. }
  406. });
  407. this.map.addLayer({
  408. id: 'line',
  409. type: 'line',
  410. source: 'line',
  411. layout: {
  412. 'line-cap': 'round'
  413. },
  414. paint: {
  415. 'line-color': '#919191',
  416. 'line-opacity': 1,
  417. 'line-width': 2,
  418. 'line-dasharray': [2, 2]
  419. }
  420. });
  421. }.bind(this)
  422. );
  423. },
  424. mapClicked(e) {
  425. var bbox = [
  426. [e.mapboxEvent.point.x - 5, e.mapboxEvent.point.y - 5],
  427. [e.mapboxEvent.point.x + 5, e.mapboxEvent.point.y + 5]
  428. ];
  429. var features = this.map.queryRenderedFeatures(bbox);
  430. if (features[0] && features[0].properties['省份']) {
  431. this.popup = new mapboxgl.Popup({ closeButton: false, maxWidth: 'none' })
  432. .setLngLat(e.mapboxEvent.lngLat)
  433. .setHTML(styles[this.type].tooltip(features[0].properties))
  434. .addTo(this.map);
  435. }
  436. },
  437. getLatestProvinceData(response) {
  438. var unit = 100000; //单位为10万
  439. var dataByName = {};
  440. ProvincesCenterData.features.forEach((provinceData) => {
  441. dataByName[provinceData.properties['省份']] = provinceData;
  442. });
  443. var dataExcludeNational = response.data.slice(1);
  444. var someDataOutOfDate = false;
  445. var latestProvinceData = [];
  446. var provinceLabelData = [];
  447. var provinceName = [];
  448. var daysNoConfirmedAdd = [];
  449. dataExcludeNational.forEach((data) => {
  450. if (data.provinces[1].provinceData && data.provinces[1].provinceData.properties) {
  451. var name = data.provinces[1].provinceData.provinceName;
  452. provinceName.push(name);
  453. daysNoConfirmedAdd.push(data.provinces[1].provinceData.properties.daysNoConfirmedAdd);
  454. // 计算连续三日最高的新增确诊数
  455. if (data.provinces[1].provinceData.properties.confirmedAdd != null) {
  456. var latest3DaysConfiredInrement = data.provinces
  457. .slice(1, 4)
  458. .map((e) => e.provinceData.properties.confirmedAdd);
  459. data.provinces[1].provinceData.properties.daysMaxConfirmedAdd = Math.max(
  460. latest3DaysConfiredInrement[0],
  461. latest3DaysConfiredInrement[1],
  462. latest3DaysConfiredInrement[2]
  463. );
  464. } else {
  465. delete data.provinces[1].provinceData.properties.daysNoConfirmedAdd;
  466. }
  467. var confirmed = data.provinces[1].provinceData.properties.confirmed;
  468. var confirmedAbsent = false;
  469. if (confirmed == null) {
  470. confirmed = data.provinces[1].provinceData.properties.confirmed;
  471. confirmedAbsent = true;
  472. }
  473. var population = dataByName[name].properties.population;
  474. var incidence = (confirmed / population) * unit;
  475. incidence = Number(incidence.toFixed(2));
  476. if (!confirmedAbsent) {
  477. data.provinces[1].provinceData.properties.incidence = incidence;
  478. }
  479. data.provinces[1].provinceData.properties.population = population;
  480. // provinceIncidence.push(incidence);
  481. var toPush = Object.assign(data.provinces[1].provinceData);
  482. // latestProvinceData.push(toPush);
  483. var province = ProvinceData.features.find(function (item) {
  484. return item.properties.Name === name || item.properties.Name.indexOf(name) === 0;
  485. });
  486. var provinceLabel = ProvincesCenterData.features.find(function (item) {
  487. return (
  488. item.properties['省份'] === name || item.properties['省份'].indexOf(name) === 0
  489. );
  490. });
  491. if (provinceLabel && province) {
  492. provinceLabel.properties = Object.assign(
  493. province.properties,
  494. provinceLabel.properties,
  495. toPush.properties,
  496. { 省份: getProvinceName(name) }
  497. );
  498. province.properties = Object.assign(
  499. province.properties,
  500. provinceLabel.properties,
  501. toPush.properties,
  502. { 省份: getProvinceName(name) }
  503. );
  504. }
  505. }
  506. });
  507. var chinaData = response.data[0].provinces[0].provinceData.properties;
  508. if (chinaData) {
  509. this.nums['china-nowConfirmed'] = chinaData['nowConfirmed'];
  510. this.nums['confirmed'] = chinaData['confirmed'];
  511. this.nums['china-incrementConfirmed'] = chinaData['confirmedAdd'];
  512. this.nums['china-incidence'] = ((chinaData['confirmed'] / 1428003306) * unit).toFixed(2);
  513. }
  514. return latestProvinceData;
  515. }
  516. }
  517. });
  518. function getProvinceName(name) {
  519. if (utils.getLanguage() === 'en-US') {
  520. return ProvincesNameEn[name];
  521. }
  522. return name;
  523. }
  524. function getTitle(response) {
  525. var titles = response[utils.getLanguage()];
  526. if (titles) {
  527. if (titles.firstPriorityTitle) {
  528. return titles.firstPriorityTitle;
  529. }
  530. if (titles.title && titles.title.indexOf('{') < 0) {
  531. return titles.title;
  532. }
  533. }
  534. return resources.text_ncp_china;
  535. }
  536. </script>
  537. </body>
  538. </html>