components_ncp_world_vue.html 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  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
  14. style="background: #081f30;"
  15. :map-options="mapOptions"
  16. @load="mapLoaded"
  17. @click="mapClicked"
  18. ></sm-web-map>
  19. <div id="group">
  20. <sm-radio-group class="radio-group" v-model="type" default-value="world-confirmedIncrement" size="large">
  21. <sm-radio-button
  22. value="world-confirmedIncrement"
  23. data-i18n="resources.text_ncp_incrementConfirmed"
  24. ></sm-radio-button>
  25. <sm-radio-button value="world-confirmed" data-i18n="resources.text_ncp_confirmed"></sm-radio-button>
  26. <sm-radio-button value="world-incidence" data-i18n="resources.text_ncp_incidence"></sm-radio-button>
  27. </sm-radio-group>
  28. <br />
  29. <sm-indicator :title="title" unit="" mode="horizontal" :num="num" font-size="44px" font-weight="400">
  30. </sm-indicator>
  31. <sm-text
  32. :title="time"
  33. text-color="rgba(255, 255, 255, 0.6)"
  34. :font-style='{ fontSize: "18px", fontWeight: "400" ,display: "block"}'
  35. >
  36. </sm-text>
  37. </div>
  38. <sm-image
  39. repeat="noRepeat"
  40. src="../img/online-qr.png"
  41. style="position: absolute; bottom: 32px;right: 16px;z-index: 1000;height: 88px;width: 88px;"
  42. ></sm-image>
  43. </div>
  44. <script type="text/javascript" include="vue" src="../js/include-web.js"></script>
  45. <script
  46. include="iclient-mapboxgl-vue,mapbox-gl-enhance"
  47. src="../../dist/mapboxgl/include-mapboxgl.js"
  48. ></script>
  49. <script src="../data/ncp/Country_Region.js"></script>
  50. <script src="../data/ncp/Country_Center.js"></script>
  51. <script src="../data/ncp/CountriesPopulation.js"></script>
  52. <style>
  53. #main {
  54. margin: 0 auto;
  55. width: 100%;
  56. height: 100%;
  57. }
  58. #group {
  59. position: absolute;
  60. left: 10px;
  61. top: 10px;
  62. z-index: 1000;
  63. }
  64. .sm-component-radio-button-wrapper {
  65. color: #fff;
  66. background: #333333;
  67. }
  68. .sm-component-radio-button-wrapper-checked {
  69. color: #0081e2 !important;
  70. border-color: #0081e2 !important;
  71. box-shadow: -1px 0 0 0 #0081e2 !important;
  72. background: #333333 !important;
  73. }
  74. .mapboxgl-popup-content {
  75. border: solid 1px #464646;
  76. background-color: #464646;
  77. border-radius: 7px;
  78. padding: 16px;
  79. z-index: 3;
  80. font-size: 20px;
  81. text-align: center;
  82. color: #ffffff;
  83. line-height: 30px;
  84. }
  85. .mapboxgl-popup-tip {
  86. display: none;
  87. }
  88. @media screen and (max-width: 768px) {
  89. .sm-component-count-to__numItem {
  90. font-size: 32px !important;
  91. }
  92. .sm-component-indicator__title {
  93. font-size: 20px !important;
  94. }
  95. .sm-component-indicator__num {
  96. font-size: 32px !important;
  97. }
  98. .sm-component-text {
  99. font-size: 16px !important;
  100. }
  101. .sm-component-radio-group-large .sm-component-radio-button-wrapper {
  102. height: 32px;
  103. line-height: 30px;
  104. font-size: 14px;
  105. padding: 0 10px;
  106. }
  107. }
  108. </style>
  109. <script>
  110. var styles = {
  111. 'world-confirmedIncrement': {
  112. tooltip: function(properties) {
  113. return resources.text_ncp_incrementConfirmed_tooltip
  114. .replace('{name}', properties['areaName'])
  115. .replace('{confirmedAdd}', properties['confirmedIncrement']);
  116. },
  117. title: resources.text_ncpworld_incrementConfirmed_title,
  118. 'fill-color': '#002F4E',
  119. 'text-field': ['case', ['>', ['get', 'confirmedIncrement'], 0], ['get', 'confirmedIncrement'], ''],
  120. 'line-color': '#0C4B68',
  121. 'circle-visibility': 'visible',
  122. 'label-visibility': 'none'
  123. },
  124. 'world-confirmed': {
  125. tooltip: function(properties) {
  126. return resources.text_ncp_confirmed_tooltip
  127. .replace('{name}', properties['areaName'])
  128. .replace('{confirmed}', properties['confirmed']);
  129. },
  130. title: resources.text_ncpworld_confirmed_title,
  131. 'fill-color': [
  132. 'case',
  133. ['has', 'confirmed'],
  134. [
  135. 'case',
  136. ['>=', ['get', 'confirmed'], 1000000],
  137. '#580000',
  138. ['>=', ['get', 'confirmed'], 100000],
  139. '#900000',
  140. ['>=', ['get', 'confirmed'], 10000],
  141. '#ef6548',
  142. ['>=', ['get', 'confirmed'], 1000],
  143. '#fc8d59',
  144. ['>=', ['get', 'confirmed'], 100],
  145. '#fdbb84',
  146. ['>=', ['get', 'confirmed'], 10],
  147. '#fdd49e',
  148. ['>=', ['get', 'confirmed'], 1],
  149. '#fee8c8',
  150. '#F4F4F4'
  151. ],
  152. '#F4F4F4'
  153. ],
  154. 'text-field': [
  155. 'concat',
  156. ['get', 'areaName'],
  157. ' ',
  158. ['case', ['>', ['get', 'confirmed'], 0], ['get', 'confirmed'], '']
  159. ],
  160. 'line-color': '#83838D',
  161. 'circle-visibility': 'none',
  162. 'label-visibility': 'visible'
  163. },
  164. 'world-incidence': {
  165. tooltip: function(properties) {
  166. return resources.text_ncp_incidence_tooltip
  167. .replace('{name}', properties['areaName'])
  168. .replace('{incidence}', properties['worldIncidence'])
  169. .replace('{confirmed}', properties['confirmed'])
  170. .replace('{population}', parseInt(properties['population'] / 10000));
  171. },
  172. title: resources.text_ncpworld_incidence_title,
  173. 'fill-color': [
  174. 'case',
  175. ['has', 'worldIncidence'],
  176. [
  177. 'case',
  178. ['>=', ['get', 'worldIncidence'], 20],
  179. '#47366D',
  180. ['>=', ['get', 'worldIncidence'], 10],
  181. '#6a51a3',
  182. ['>=', ['get', 'worldIncidence'], 5],
  183. '#7f7dba',
  184. ['>=', ['get', 'worldIncidence'], 1],
  185. '#9e9ac8',
  186. ['>=', ['get', 'worldIncidence'], 0.1],
  187. '#dadaeb',
  188. '#efedf5'
  189. ],
  190. '#F4F4F4'
  191. ],
  192. 'text-field': ['get', 'areaName'],
  193. 'line-color': '#83838D',
  194. 'circle-visibility': 'none',
  195. 'label-visibility': 'visible'
  196. }
  197. };
  198. new Vue({
  199. el: '#main',
  200. data() {
  201. var attribution =
  202. "<a href='https://www.mapbox.com/about/maps/' target='_blank'>© Mapbox </a>" +
  203. " with <span>© <a href='https://iclient.supermap.io' target='_blank'>SuperMap iClient</a> | </span>" +
  204. " Map Data <span>© <a href='https://www.supermapol.com/' target='_blank'>SuperMap Online</a></span> ";
  205. return {
  206. type: 'world-confirmedIncrement',
  207. nums: { 'world-confirmedIncrement': 0, 'world-confirmed': 0, 'world-incidence': 0 },
  208. chinaConfirmed: 0,
  209. chinaConfirmedIncrement: 0,
  210. time: '',
  211. // mapOptions是sm-map组件的props
  212. mapOptions: {
  213. container: 'map', // container id
  214. style: {
  215. version: 8,
  216. glyphs: 'https://ncov.supermapol.com/statichtml/font/{fontstack}/{range}.pbf',
  217. sources: {
  218. 'raster-tiles': {
  219. attribution: attribution,
  220. type: 'raster',
  221. tiles: [
  222. 'https://maptiles.supermapol.com/iserver/services/map-China-2/rest/maps/China_DarkBlue_Nolable'
  223. ],
  224. prjCoordSys: { epsgCode: 4326 },
  225. rasterSource: 'iserver',
  226. tileSize: 256
  227. }
  228. },
  229. layers: [
  230. {
  231. id: 'simple-tiles',
  232. type: 'raster',
  233. source: 'raster-tiles',
  234. minzoom: 0,
  235. maxzoom: 22
  236. }
  237. ]
  238. },
  239. center: [101.58, 33.11],
  240. maxZoom: 5,
  241. zoom: 2,
  242. crs: 'EPSG:4326'
  243. }
  244. };
  245. },
  246. created() {
  247. SuperMap.Components.setTheme({
  248. textColor: 'rgba(255, 255, 255, 0.85)',
  249. background: 'rgba(0, 0, 0,0)',
  250. colorGroup: ['rgb(225, 2, 0)']
  251. });
  252. $.get('https://ncpviz.oss-cn-beijing.aliyuncs.com/ncpviz/ui.json?time=' + new Date().getTime(), function(response) {
  253. document.title = getTitle(response);
  254. });
  255. },
  256. computed: {
  257. num() {
  258. if (this.type === 'world-incidence') {
  259. return this.nums['world-incidence'];
  260. }
  261. if (this.type === 'world-confirmedIncrement') {
  262. return this.nums['world-confirmedIncrement'] - this.chinaConfirmedIncrement;
  263. }
  264. if (this.type === 'world-confirmed') {
  265. return this.nums['world-confirmed'] - this.chinaConfirmed;
  266. }
  267. return '';
  268. },
  269. title() {
  270. return styles[this.type].title;
  271. }
  272. },
  273. watch: {
  274. type(val) {
  275. if (this.popup) {
  276. this.popup.remove();
  277. }
  278. this.map.setPaintProperty('china', 'fill-color', styles[val]['fill-color']);
  279. this.map.setPaintProperty('world-strokeLine', 'line-color', styles[val]['line-color']);
  280. this.map.setLayoutProperty('world-label', 'text-field', styles[val]['text-field']);
  281. this.map.setLayoutProperty('world-clusters', 'visibility', styles[val]['circle-visibility']);
  282. this.map.setLayoutProperty(
  283. 'world-label-clusters',
  284. 'visibility',
  285. styles[val]['circle-visibility']
  286. );
  287. this.map.setLayoutProperty(
  288. 'world-label-area-clusters',
  289. 'visibility',
  290. styles[val]['circle-visibility']
  291. );
  292. this.map.setLayoutProperty('world-serious', 'visibility', styles[val]['circle-visibility']);
  293. this.map.setLayoutProperty(
  294. 'world-label-area-serious',
  295. 'visibility',
  296. styles[val]['circle-visibility']
  297. );
  298. this.map.setLayoutProperty(
  299. 'world-label-serious',
  300. 'visibility',
  301. styles[val]['circle-visibility']
  302. );
  303. this.map.setLayoutProperty('world-label', 'visibility', styles[val]['label-visibility']);
  304. }
  305. },
  306. methods: {
  307. mapLoaded(e) {
  308. this.map = e.map;
  309. $.get(
  310. 'https://ncpviz.oss-cn-beijing.aliyuncs.com/ncpviz/worldNcp.json?time=' +
  311. new Date().getTime(),
  312. function(response) {
  313. this.time = resources.text_ncp_time.replace('{time}', response.time);
  314. var latestProvinceData = this.getLatestWorldData(response);
  315. this.map.addSource('china', {
  316. type: 'geojson',
  317. data: CountryData
  318. });
  319. this.map.addLayer({
  320. id: 'china',
  321. type: 'fill',
  322. source: 'china',
  323. layout: {},
  324. paint: {
  325. 'fill-color': styles[this.type]['fill-color']
  326. }
  327. });
  328. this.map.addLayer({
  329. id: 'world-strokeLine',
  330. type: 'line',
  331. source: 'china',
  332. layout: {},
  333. paint: {
  334. 'line-width': 0.5,
  335. 'line-color': styles[this.type]['line-color'],
  336. 'line-opacity': 1
  337. }
  338. });
  339. this.map.addSource('world-label-clusters', {
  340. type: 'geojson',
  341. data: CountryCenterData,
  342. cluster: true,
  343. clusterRadius: 10
  344. });
  345. this.map.addSource('world-label', {
  346. type: 'geojson',
  347. data: CountryCenterData
  348. });
  349. this.map.addLayer({
  350. id: 'world-clusters',
  351. type: 'circle',
  352. source: 'world-label-clusters',
  353. filter: [
  354. 'all',
  355. ['<', ['get', 'confirmedIncrement'], 1000],
  356. ['>', ['get', 'confirmedIncrement'], 0]
  357. ],
  358. layout: {
  359. visibility: styles[this.type]['circle-visibility']
  360. },
  361. paint: {
  362. 'circle-color': [
  363. 'case',
  364. ['>=', ['get', 'confirmedIncrement'], 1000],
  365. '#F35735',
  366. ['>=', ['get', 'confirmedIncrement'], 100],
  367. '#F39146',
  368. ['>=', ['get', 'confirmedIncrement'], 50],
  369. '#F9B657',
  370. ['>=', ['get', 'confirmedIncrement'], 10],
  371. '#E2B06A',
  372. '#ADB37E'
  373. ],
  374. 'circle-radius': [
  375. 'case',
  376. ['>=', ['get', 'confirmedIncrement'], 1000],
  377. 18,
  378. ['>=', ['get', 'confirmedIncrement'], 100],
  379. 15,
  380. ['>=', ['get', 'confirmedIncrement'], 50],
  381. 12,
  382. ['>=', ['get', 'confirmedIncrement'], 10],
  383. 10,
  384. 7
  385. ],
  386. 'circle-stroke-width': 1,
  387. 'circle-stroke-color': '#fff',
  388. 'circle-stroke-opacity': 0.8
  389. }
  390. });
  391. this.map.addLayer({
  392. id: 'world-label-area-clusters',
  393. type: 'symbol',
  394. source: 'world-label-clusters',
  395. filter: [
  396. 'all',
  397. ['<', ['get', 'confirmedIncrement'], 1000],
  398. ['>', ['get', 'confirmedIncrement'], 0]
  399. ],
  400. layout: {
  401. visibility: styles[this.type]['circle-visibility'],
  402. 'text-field': '{areaName}',
  403. 'text-font': ['Microsoft YaHei Regular'],
  404. 'text-size': 12,
  405. 'text-letter-spacing': 0,
  406. 'text-offset': [0, -2]
  407. },
  408. paint: {
  409. 'text-color': 'white',
  410. 'text-opacity': 1,
  411. 'text-halo-color': '#696868',
  412. 'text-halo-width': 1.5
  413. }
  414. });
  415. this.map.addLayer({
  416. id: 'world-label-clusters',
  417. type: 'symbol',
  418. source: 'world-label-clusters',
  419. filter: [
  420. 'all',
  421. ['<', ['get', 'confirmedIncrement'], 1000],
  422. ['>', ['get', 'confirmedIncrement'], 0]
  423. ],
  424. layout: {
  425. visibility: styles[this.type]['circle-visibility'],
  426. 'text-field': styles[this.type]['text-field'],
  427. 'text-font': ['Microsoft YaHei Regular'],
  428. 'text-size': 12,
  429. 'text-letter-spacing': 0
  430. },
  431. paint: {
  432. 'text-color': '#000',
  433. 'text-opacity': 1
  434. }
  435. });
  436. this.map.addLayer({
  437. id: 'world-serious',
  438. type: 'circle',
  439. source: 'world-label',
  440. filter: ['>=', ['get', 'confirmedIncrement'], 1000],
  441. layout: {
  442. visibility: styles[this.type]['circle-visibility']
  443. },
  444. paint: {
  445. 'circle-color': '#F35735',
  446. 'circle-radius': 18,
  447. 'circle-stroke-width': 1,
  448. 'circle-stroke-color': '#fff',
  449. 'circle-stroke-opacity': 0.8
  450. }
  451. });
  452. this.map.addLayer({
  453. id: 'world-label-area-serious',
  454. type: 'symbol',
  455. source: 'world-label',
  456. filter: ['>=', ['get', 'confirmedIncrement'], 1000],
  457. layout: {
  458. visibility: styles[this.type]['circle-visibility'],
  459. 'text-field': '{areaName}',
  460. 'text-font': ['Microsoft YaHei Regular'],
  461. 'text-size': 12,
  462. 'text-allow-overlap': false,
  463. 'text-ignore-placement': false,
  464. 'text-letter-spacing': 0,
  465. 'text-offset': [0, -2],
  466. 'symbol-sort-key': 9
  467. },
  468. paint: {
  469. 'text-color': 'white',
  470. 'text-opacity': 1,
  471. 'text-halo-color': '#696868',
  472. 'text-halo-width': 1.5
  473. }
  474. });
  475. this.map.addLayer({
  476. id: 'world-label-serious',
  477. type: 'symbol',
  478. source: 'world-label',
  479. filter: ['>=', ['get', 'confirmedIncrement'], 1000],
  480. layout: {
  481. visibility: styles[this.type]['circle-visibility'],
  482. 'text-field': styles[this.type]['text-field'],
  483. 'text-font': ['Microsoft YaHei Regular'],
  484. 'text-size': 12,
  485. 'text-letter-spacing': 0,
  486. 'symbol-sort-key': 10
  487. },
  488. paint: {
  489. 'text-color': '#000',
  490. 'text-opacity': 1
  491. }
  492. });
  493. this.map.addLayer({
  494. id: 'world-label',
  495. type: 'symbol',
  496. source: 'world-label',
  497. layout: {
  498. visibility: styles[this.type]['label-visibility'],
  499. 'text-field': styles[this.type]['text-field'],
  500. 'text-font': ['Microsoft YaHei Regular'],
  501. 'text-size': 12,
  502. 'text-allow-overlap': false,
  503. 'text-letter-spacing': 0
  504. },
  505. paint: {
  506. 'text-color': 'white',
  507. 'text-opacity': 1,
  508. 'text-halo-color': '#696868',
  509. 'text-halo-width': 1.5
  510. }
  511. });
  512. }.bind(this)
  513. );
  514. },
  515. mapClicked(e) {
  516. var bbox = [
  517. [e.mapboxEvent.point.x - 5, e.mapboxEvent.point.y - 5],
  518. [e.mapboxEvent.point.x + 5, e.mapboxEvent.point.y + 5]
  519. ];
  520. var features = this.map.queryRenderedFeatures(bbox);
  521. if (features[0] && features[0].properties.areaName) {
  522. this.popup = new mapboxgl.Popup({ closeButton: false, maxWidth: 'none' })
  523. .setLngLat(e.mapboxEvent.lngLat)
  524. .setHTML(styles[this.type].tooltip(features[0].properties))
  525. .addTo(this.map);
  526. }
  527. },
  528. getLatestWorldData(result) {
  529. var countrys = [];
  530. var confirmeds = [];
  531. worldTime = result.time;
  532. worldDataUpdateTime = result.updateTime;
  533. // 最新当天的数据
  534. todayWorldData = result.data.worldHistory[0].historyList[0];
  535. var unit = 100000; //单位为10万
  536. result.data.worldList.forEach(data => {
  537. // 砖石号游轮不计算发病率
  538. // 计算各国报告发病率
  539. var confirmed = data.confirmed;
  540. var name = data.areaName;
  541. if (name === '日本本土') {
  542. name = data.areaName = '日本';
  543. }
  544. var countryName = CountriesNameEn[name];
  545. if (CountriesPopulation[countryName]) {
  546. data.population = CountriesPopulation[countryName] * 1000; //联合国数以千计
  547. }
  548. // 大于等于10万 才计算发病率
  549. if (data.population >= 100000) {
  550. var incidence = (confirmed / data.population) * unit;
  551. incidence = Number(incidence.toFixed(2));
  552. // 地图使用
  553. data.worldIncidence = incidence;
  554. }
  555. if (!isNaN(data.confirmedIncrement)) {
  556. this.nums['world-confirmedIncrement'] += parseInt(data.confirmedIncrement);
  557. if (name === '中国') {
  558. this.chinaConfirmedIncrement = data.confirmedIncrement;
  559. }
  560. }
  561. if (!isNaN(data.confirmed)) {
  562. this.nums['world-confirmed'] += parseInt(data.confirmed);
  563. if (name === '中国') {
  564. this.chinaConfirmed = data.confirmed;
  565. }
  566. }
  567. if (!isNaN(data.worldIncidence)) {
  568. this.nums['world-incidence'] = (
  569. (this.nums['world-confirmed'] / 7751396374) *
  570. unit
  571. ).toFixed(2);
  572. }
  573. var country = CountryData.features.find(function(item) {
  574. return (
  575. item.properties.Country === name ||
  576. (name === '中国' && item.properties.Country === '中华人民共和国')
  577. );
  578. });
  579. var countryLabel = CountryCenterData.features.find(function(item) {
  580. return (
  581. item.properties.Country === name ||
  582. (name === '中国' && item.properties.Country === '中华人民共和国')
  583. );
  584. });
  585. if (country && countryLabel) {
  586. country.properties = Object.assign(country.properties, countryLabel.properties, data, {
  587. areaName: getareaName(name)
  588. });
  589. countryLabel.properties = Object.assign(
  590. country.properties,
  591. countryLabel.properties,
  592. data,
  593. { areaName: getareaName(name) }
  594. );
  595. }
  596. });
  597. CountryCenterData.features = CountryCenterData.features.sort(function(val1, val2) {
  598. return (val2.properties.confirmed || 0) - (val1.properties.confirmed || 0);
  599. });
  600. }
  601. }
  602. });
  603. function getareaName(name) {
  604. if (utils.getLanguage() === 'en-US') {
  605. return CountriesNameEn[name];
  606. }
  607. return name;
  608. }
  609. function getTitle(response) {
  610. var titles = response[utils.getLanguage()];
  611. if (titles) {
  612. if (titles.firstPriorityTitle) {
  613. return titles.firstPriorityTitle;
  614. }
  615. if (titles.title && titles.title.indexOf('{') < 0) {
  616. return titles.title;
  617. }
  618. }
  619. return resources.text_ncp_world;
  620. }
  621. </script>
  622. </body>
  623. </html>