// AQI来源:https://aqicn.org
|
|
import * as mars3d from "mars3d"
|
|
export let map // mars3d.Map三维地图对象
|
export let graphicLayer // 矢量图层对象
|
|
let imgData = null
|
let lastExtent = null
|
let bWorking = false
|
let currentData
|
|
let startTimestamp, endTimestamp
|
let timeout = 1000
|
let worker
|
|
// 需要覆盖config.json中地图属性参数(当前示例框架中自动处理合并)
|
export const mapOptions = {
|
scene: {
|
center: { lat: 25.251743, lng: 107.045599, alt: 553192, heading: 0, pitch: -51 }
|
}
|
}
|
|
/**
|
* 初始化地图业务,生命周期钩子函数(必须)
|
* 框架在地图初始化完成后自动调用该函数
|
* @param {mars3d.Map} mapInstance 地图对象
|
* @returns {void} 无
|
*/
|
export function onMounted(mapInstance) {
|
map = mapInstance // 记录map
|
|
imgData = getImageData()
|
|
// 创建Graphic图层
|
graphicLayer = new mars3d.layer.GraphicLayer()
|
map.addLayer(graphicLayer)
|
|
// 在layer上绑定Popup单击弹窗
|
graphicLayer.bindPopup(function (event, callback) {
|
const item = event.graphic.attr
|
if (!item) {
|
return false
|
}
|
return mars3d.Util.getTemplateHtml({
|
title: "AQI",
|
template: [
|
{ field: "city", name: "城市" },
|
{ field: "utime", name: "时间" },
|
{ field: "aqi", name: "AQI" },
|
{ field: "level", name: "质量" },
|
{ field: "influence", name: "影响" },
|
{ field: "suggestion", name: "建议" }
|
],
|
attr: item
|
})
|
})
|
|
map.on(mars3d.EventType.cameraChanged, onMap_cameraChanged)
|
onMap_cameraChanged()
|
}
|
|
/**
|
* 释放当前地图业务的生命周期函数
|
* @returns {void} 无
|
*/
|
export function onUnmounted() {
|
map = null
|
}
|
|
function onMap_cameraChanged() {
|
endTimestamp = new Date().getTime()
|
if (bWorking === false) {
|
const extent = map.getExtent()
|
const bbox = extent.ymin + "," + extent.xmin + "," + extent.ymax + "," + extent.xmax
|
if (bbox !== lastExtent) {
|
startWorker(bbox)
|
lastExtent = bbox
|
}
|
} else if (endTimestamp - startTimestamp > timeout) {
|
bWorking = false
|
timeout += 1000
|
worker.terminate() // 终止 web worker
|
}
|
}
|
|
function startWorker(strBounds) {
|
startTimestamp = endTimestamp = new Date().getTime()
|
worker = new Worker(window.currentPath + `aqiWorker.js`) // currentPath为当前目录,内置在示例框架中
|
|
// 主线程调用worker.postMessage()方法,向 Worker 发消息。
|
worker.postMessage({
|
bounds: strBounds
|
})
|
bWorking = true
|
|
worker.onmessage = function (event) {
|
// Worker返回的结果。
|
currentData = event.data.entityTable
|
const currTime = event.data.currTime
|
if (currentData.length !== 0 && currTime > startTimestamp) {
|
createGraphics(currentData)
|
}
|
|
bWorking = false
|
worker.terminate() // 终止 web worker
|
}
|
}
|
|
function createGraphics(currentData) {
|
graphicLayer.clear()
|
console.log("加载数据", currentData)
|
|
for (let i = currentData.length - 1; i >= 0; i--) {
|
const item = currentData[i]
|
|
const primitive = new mars3d.graphic.BillboardPrimitive({
|
id: item.x,
|
name: item.city,
|
position: [item.lon, item.lat],
|
style: {
|
image: mars3d.Util.getCircleImage(item.aqi, {
|
color: getColor(item.aqi),
|
radius: 25
|
}),
|
scale: 1,
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
verticalOrigin: Cesium.VerticalOrigin.CENTER,
|
scaleByDistance: new Cesium.NearFarScalar(10000, 1.0, 900000, 0.3)
|
},
|
attr: item
|
})
|
graphicLayer.addGraphic(primitive)
|
}
|
}
|
|
// 获取色带
|
function getImageData() {
|
const nWidth = 500
|
const canvas = document.createElement("canvas")
|
canvas.width = nWidth
|
canvas.height = nWidth
|
const ctx = canvas.getContext("2d")
|
ctx.beginPath()
|
/* 指定渐变区域 */
|
const grad = ctx.createLinearGradient(0, 0, nWidth, 0)
|
/* 指定几个颜色 */
|
grad.addColorStop(0.05, "rgb(0, 228, 0)") // green
|
grad.addColorStop(0.15, "rgb(256, 256, 0)") // yellow
|
grad.addColorStop(0.25, "rgb(256, 126, 0)") // orange
|
grad.addColorStop(0.35, "rgb(256, 0, 0)") // red
|
grad.addColorStop(0.5, "rgb(153, 0, 76)") // purple
|
grad.addColorStop(0.8, "rgb(126, 0, 35)") // maroon
|
/* 将这个渐变设置为fillStyle */
|
ctx.fillStyle = grad
|
/* 绘制矩形 */
|
ctx.rect(0, 0, nWidth, nWidth)
|
ctx.fill()
|
return ctx.getImageData(0, 0, nWidth, 1).data
|
}
|
|
function getColor(aqi) {
|
if (aqi > 500) {
|
return "rgba(126,0,35,0.8)"
|
} else {
|
return `rgba(${imgData[aqi * 4]},${imgData[aqi * 4 + 1]},${imgData[aqi * 4 + 2]},0.8)`
|
}
|
}
|