Commit eefd4ca3 by lyc

11

parent 35b01f4a
......@@ -6,8 +6,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue</title>
<script src="../Build/CesiumUnminified/Cesium.js"></script>
<!-- <script src="/node_modules/cesium-heatmap/CesiumHeatmap.js"></script> -->
</head>
......
......@@ -10,12 +10,16 @@
},
"dependencies": {
"cesium": "1.99",
"cesium-heatmap": "^0.0.4",
"element-plus": "^2.7.7",
"heatmap.js": "^2.0.5",
"vite-plugin-cesium": "^1.2.22",
"vue": "^3.4.29"
},
"devDependencies": {
"@types/heatmap.js": "^2.0.41",
"@vitejs/plugin-vue": "^5.0.5",
"sass": "^1.77.8",
"vite": "^5.3.1"
}
}
......@@ -20,7 +20,7 @@ import jiguang from './components/jiguang.vue'
import shiqushiti from './components/shiqushiti.vue'
import kuosanquan from './components/kuosanyuan.vue'
import relitu from './components/relitu.vue'
// import test from './components/test.vue'
//封装
import point from './encapsulation/point.vue'
......@@ -51,16 +51,17 @@ export default {
<!-- <draw/> -->
<!-- <camera/> -->
<!-- <dail/> -->
<!-- <raotaiyang/> -->
<raotaiyang/>
<!-- <qq/> -->
<!-- <xyz/> -->
<!-- <setl/> -->
<!-- <shiye/> -->
<!-- <lineq/> -->
<jiguang/>
<!-- <jiguang/> -->
<!-- <shiqushiti/> -->
<!-- <kuosanquan/> -->
<!-- <relitu/> -->
<!-- <test/> -->
<!-- <point/> -->
<!-- <polygonq/> -->
......
<template>
<div id="cesiumContainer" class="all"></div>
<div id="cesiumContainer" class="all">
<div id="heatMap" v-show="false"></div>
</div>
</template>
<script setup>
import { onMounted } from 'vue'
import * as Cesium from 'cesium'
onMounted(() => {
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyYTI3MDQxMS1hYzgxLTRlYTQtODExZS00YzdmYjM0YTg3OTAiLCJpZCI6MjI0NzQzLCJpYXQiOjE3MTkzOTcxMDF9._VD-W1rEy7jSUtPmcVytEYbZIZ00_IeHCZm59Kua5aE'
const viewer = new Cesium.Viewer("cesiumContainer", {
})
var gravityData = [
{
position: Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706), // 示例坐标
value: 100.0 // 示例重力异常值
},
// ... 更多点
];
var pointPrimitive = viewer.scene.primitives.add(Cesium.Primitive.createPoints({
attributes: new Cesium.BoundingSphereGeometryAttributes({
position: new Cesium.PositionPropertyCollection(gravityData)
}),
color: Cesium.Color.fromRandom(),
size: 10
}));
// 更新画面的渲染并添加图层
viewer.scene.requestRender();
// let bounds = {
// west: 103,
// east: 104,
// south: 30,
// north: 31
// };
// let heatMap = CesiumHeatmap.create(
// viewer,
// bounds,
// {
// minOpacity: 0.16,
// maxOpacity: 0.85,
// gradient: {
// "0.05": "rgb(0,0,255)",
// "0.25": "rgb(0 255 127)",
// "0.45": "rgb(0,255,0)",
// "0.65": "rgb(255 255 0)",
// "0.85": "rgb(255 165 0)",
// "1.00": "rgb(255,0,0)"
// },
// radius: 150,
// blur: 0.7,
// }
// );
// let minValue = 0;
// let maxValue = 100;
// let data = [];
// for (let i = 0; i < 100; i++) {
// data.push({
// x: 103 + Math.random(),
// y: 30 + Math.random(),
// value: Math.floor(Math.random() * 100) //[0,100]
// });
// }
// heatMap.setWGS84Data(minValue, maxValue, data);
// viewer.camera.setView({
// destination: Cesium.Rectangle.fromDegrees(bounds.west, bounds.south, bounds.east, bounds.north)
// });
// let list = [];
// for (let i = 0; i < 100; i++) {
// list.push({
// "lnglat": [
// 117.28 + Math.random() * (Math.random() > 0.5 ? 1 : -1),
// 31.923 + Math.random() * (Math.random() > 0.5 ? 1 : -1)
// ],
// "value": 100 * Math.random()
// })
// }
// new Heatmap(viewer, {
// list: list
// })
})
</script>
<style></style>
<style>
.canvas-main {
position: absolute;
margin: 10px;
padding: 10px;
z-index: 10;
background: rgba(255, 255, 0, 0.329);
}
</style>
<template>
<div id="cesiumContainer">
<div class="canvas-main">
<el-button size="mini" @click="startDraw" :disabled="bool">开始绘制</el-button>
<el-button size="mini" @click="autoUpdate" :disabled="!bool">自动更新</el-button>
</div>
</div>
</template>
<script>
import { ref } from 'vue';
import * as Cesium from 'cesium';
// const mapData = ref([]);
// const bool = ref(false);
// const viewer = ref(undefined);
// const key =
// 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyYTI3MDQxMS1hYzgxLTRlYTQtODExZS00YzdmYjM0YTg3OTAiLCJpZCI6MjI0NzQzLCJpYXQiOjE3MTkzOTcxMDF9._VD-W1rEy7jSUtPmcVytEYbZIZ00_IeHCZm59Kua5aE';
// Cesium.Ion.defaultAccessToken = key;
// const initViewer = () => {
// const options = {
// imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
// url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
// }),
// terrainProvider: Cesium.createWorldTerrain(),
// geocoder: true,
// homeButton: true,
// sceneModePicker: true,
// baseLayerPicker: true,
// navigationHelpButton: true,
// animation: true,
// timeline: true,
// fullscreenButton: true,
// vrButton: true,
// selectionIndicator: true,
// infoBox: true,
// };
// viewer.value = new Cesium.Viewer("cesiumContainer", options);
// viewer.value._cesiumWidget._creditContainer.style.display = "none"; // 隐藏版权
// };
// onMounted(initViewer);
// const startDra=()=> {
// const option = {
// min: 0,
// max: 100,
// size: 20,
// };
// window.heatmapObj = new HeatmapIntensity(viewer, option);
// const box = {
// west: 110,
// south: 40.5,
// east: 110.5,
// north: 41,
// };
// window.heatmapObj.createHeatmap(box, this.mapData);
// this.bool = true;
// };
// const autoUpdate=()=> {
// setInterval(() => {
// let data = [];
// for (let i = 0; i < 100; i++) {
// let obj = {};
// obj.x = this.randomNum(110, 110.5, 5);
// obj.y = this.randomNum(40.5, 41, 5);
// obj.value = this.randomNum(0, 100, 2);
// data.push(obj);
// }
// window.heatmapObj.setData(data);
// }, 1000);
// };
// const initData=()=> {
// this.mapData = [];
// for (let i = 0; i < 100; i++) {
// let obj = {};
// obj.x = this.randomNum(110, 110.5, 5);
// obj.y = this.randomNum(40.5, 41, 5);
// obj.value = this.randomNum(0, 100, 2);
// this.mapData.push(obj);
// }
// this.mapData.forEach((element) => {
// viewer.entities.add({
// position: Cesium.Cartesian3.fromDegrees(
// Number(element.x),
// Number(element.y)
// ),
// point: {
// pixelSize: 5,
// heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
// },
// });
// });
// viewer.flyTo(viewer.entities);
// };
// const randomNum =(maxNum, minNum, decimalNum)=> {
// // 获取指定范围内的随机数, decimalNum指小数保留多少位
// let max = 0,
// min = 0;
// minNum <= maxNum
// ? ((min = minNum), (max = maxNum))
// : ((min = maxNum), (max = minNum));
// let result = undefined;
// switch (arguments.length) {
// case 1:
// result = Math.floor(Math.random() * (max + 1));
// break;
// case 2:
// result = Math.floor(Math.random() * (max - min + 1) + min);
// break;
// case 3:
// result = (Math.random() * (max - min) + min).toFixed(decimalNum);
// break;
// default:
// result = Math.random();
// break;
// }
// return result;
// },
</script>
<style lang="scss" scoped>
#cesiumContainer {
width: 100%;
height: 100%;
position: relative;
background: rgba(255, 0, 0, 0.322);
.canvas-main {
position: absolute;
margin: 10px;
padding: 10px;
z-index: 10;
background: rgba(255, 255, 0, 0.329);
}
}
</style>
\ No newline at end of file
/*
* Cesium 热力图主类
* @Author: Wang jianLei
* @Date: 2022-10-20 15:12:27
* @Last Modified by: Wang JianLei
* @Last Modified time: 2022-10-23 22:53:01
*/
import { Intensity, Canvas } from "./Intensity";
const Cesium = window.Cesium;
class HeatmapIntensity {
constructor(viewer, option = {}) {
if (!viewer) throw new Error("no viewer object!");
this._viewer = viewer;
this._min = option.min || 0; //最小值
this._max = option.max || 100; //最大值
this._size = option.size || 20; //光圈大小,像素值
this._result = undefined; //热力图结果
this._canvas = undefined; //离屏canvas
}
get min() {
return this._min;
}
set min(val) {
this._min = val;
this.updateHeatmap(this._result.canvasData);
}
get max() {
return this._max;
}
set max(val) {
this._max = val;
this.updateHeatmap(this._result.canvasData);
}
get size() {
return this._size;
}
set size(val) {
this._size = val;
this.updateHeatmap(this._result.canvasData);
}
get result() {
return this._result;
}
/**
* 创建热力图对象
* @param {*} box 范围对象,经纬度值-{west,south,east,north}
* @param {*} data 待绘制热力图的数据-[{x1,y1,value1},{x2,y2,value2},...]
* @returns 热力图结果对象
*/
createHeatmap(box, data) {
const mercator_WestSouth = this.WGS84ToWebMercator(box.west, box.south, 0); //左下位置(墨卡托)
const mercator_EastNorth = this.WGS84ToWebMercator(box.east, box.north, 0); //右上位置(墨卡托)
const diffDegrees_X = mercator_EastNorth.x - mercator_WestSouth.x;
const diffDegrees_Y = mercator_EastNorth.y - mercator_WestSouth.y;
const diffMax = Math.max(diffDegrees_X, diffDegrees_Y);
let multiple = diffMax / 300; //适当扩大倍数,以便绘制canvas
const width = Math.ceil(diffDegrees_X / multiple);
const height = Math.ceil(diffDegrees_Y / multiple);
this.mercator_WestSouth = mercator_WestSouth;
this.mercator_EastNorth = mercator_EastNorth;
this.diffDegrees_X = diffDegrees_X;
this.diffDegrees_Y = diffDegrees_Y;
let canvasData = [];
data.forEach((element) => {
const curMercator = this.WGS84ToWebMercator(
Number(element.x),
Number(element.y),
0
);
const per_X = (curMercator.x - mercator_WestSouth.x) / diffDegrees_X;
const currentPix_X = Math.ceil(per_X * width);
const per_Y = (curMercator.y - mercator_WestSouth.y) / diffDegrees_Y;
const currentPix_Y = Math.ceil(per_Y * height);
const currentValue = Number(element.value);
canvasData.push({
x: currentPix_X,
y: height - currentPix_Y - 1,
value: currentValue,
});
});
let canvas = new Canvas(width, height);
let context = canvas.getContext("2d");
context.clearRect(0, 0, canvas.width, canvas.height);
let circle = this.createCircle(this._size);
let circleHalfWidth = circle.width / 2;
let circleHalfHeight = circle.height / 2;
// 按透明度分类
let dataOrderByAlpha = {};
canvasData.forEach((item) => {
let alpha =
item.value < this._min
? 0
: Math.min(1, item.value / this._max).toFixed(2);
dataOrderByAlpha[alpha] = dataOrderByAlpha[alpha] || [];
dataOrderByAlpha[alpha].push(item);
});
// 绘制不同透明度的圆形
for (let i in dataOrderByAlpha) {
if (isNaN(i)) continue;
let _data = dataOrderByAlpha[i];
context.beginPath();
context.globalAlpha = i;
_data.forEach((item) => {
context.drawImage(
circle,
item.x - circleHalfWidth,
item.y - circleHalfHeight
);
});
}
// 圆形着色
let intensity = new Intensity();
let colored = context.getImageData(
0,
0,
context.canvas.width,
context.canvas.height
);
const options = { min: 0, max: this._max, size: this._size };
this.colorize(options, colored.data, intensity.getImageData());
context.clearRect(0, 0, context.canvas.width, context.canvas.height);
context.putImageData(colored, 0, 0);
let entity = this._viewer.entities.add({
name: "rectangle",
rectangle: {
coordinates: Cesium.Rectangle.fromDegrees(
box.west,
box.south,
box.east,
box.north
),
material: new Cesium.ImageMaterialProperty({
image: canvas,
transparent: true,
}),
// heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
},
});
this._canvas = canvas;
this._result = { box, data, canvasData, entity };
return this._result;
}
/**
* 更新热力图数据
* @param {*} data 待绘制热力图的数据-[{x1,y1,value1},{x2,y2,value2},...]
*/
setData(data) {
if (!this._result) {
return;
}
let canvasData = [];
const height = this._canvas.height;
const width = this._canvas.width;
data.forEach((element) => {
const curMercator = this.WGS84ToWebMercator(
Number(element.x),
Number(element.y),
0
);
const per_X =
(curMercator.x - this.mercator_WestSouth.x) / this.diffDegrees_X;
const currentPix_X = Math.ceil(per_X * width);
const per_Y =
(curMercator.y - this.mercator_WestSouth.y) / this.diffDegrees_Y;
const currentPix_Y = Math.ceil(per_Y * height);
const currentValue = Number(element.value);
canvasData.push({
x: currentPix_X,
y: height - currentPix_Y - 1,
value: currentValue,
});
});
this._result.data = data;
this._result.canvasData = canvasData;
this.updateHeatmap(canvasData);
}
/**
* 更新热力图
* @param {*} data 参考canvasData
* @returns 热力图结果对象
*/
updateHeatmap(data) {
let canvas = this._canvas;
let context = canvas.getContext("2d");
context.clearRect(0, 0, canvas.width, canvas.height);
let circle = this.createCircle(this._size);
let circleHalfWidth = circle.width / 2;
let circleHalfHeight = circle.height / 2;
// 按透明度分类
let dataOrderByAlpha = {};
data.forEach((item) => {
let alpha =
item.value < this._min
? 0
: Math.min(1, item.value / this._max).toFixed(2);
dataOrderByAlpha[alpha] = dataOrderByAlpha[alpha] || [];
dataOrderByAlpha[alpha].push(item);
});
// 绘制不同透明度的圆形
for (let i in dataOrderByAlpha) {
if (isNaN(i)) continue;
let _data = dataOrderByAlpha[i];
context.beginPath();
context.globalAlpha = i;
_data.forEach((item) => {
context.drawImage(
circle,
item.x - circleHalfWidth,
item.y - circleHalfHeight
);
});
}
// 圆形着色
let intensity = new Intensity();
let colored = context.getImageData(
0,
0,
context.canvas.width,
context.canvas.height
);
const options = { min: 0, max: this._max, size: this._size };
this.colorize(options, colored.data, intensity.getImageData());
context.clearRect(0, 0, context.canvas.width, context.canvas.height);
context.putImageData(colored, 0, 0);
this._result.entity.rectangle.material = new Cesium.ImageMaterialProperty({
image: canvas,
transparent: true,
});
return this._result;
}
createCircle(size) {
let shadowBlur = size / 2;
let r2 = size + shadowBlur;
let offsetDistance = 10000;
let circle = new Canvas(r2 * 2, r2 * 2);
let context = circle.getContext("2d");
context.shadowBlur = shadowBlur;
context.shadowColor = "black";
context.shadowOffsetX = context.shadowOffsetY = offsetDistance;
context.beginPath();
context.arc(
r2 - offsetDistance,
r2 - offsetDistance,
size,
0,
Math.PI * 2,
true
);
context.closePath();
context.fill();
return circle;
}
colorize(options, pixels, gradient) {
let max = options.max;
let min = options.min;
let diff = max - min;
let range = options.range || null;
let jMin = 0;
let jMax = 1024;
if (range && range.length === 2) {
jMin = ((range[0] - min) / diff) * 1024;
}
if (range && range.length === 2) {
jMax = ((range[1] - min) / diff) * 1024;
}
let maxOpacity = options.maxOpacity || 0.8;
for (let i = 3, len = pixels.length, j; i < len; i += 4) {
j = pixels[i] * 4; // get gradient color from opacity value
if (pixels[i] / 256 > maxOpacity) {
pixels[i] = 256 * maxOpacity;
}
if (j && j >= jMin && j <= jMax) {
pixels[i - 3] = gradient[j];
pixels[i - 2] = gradient[j + 1];
pixels[i - 1] = gradient[j + 2];
} else {
pixels[i] = 0;
}
}
}
WGS84ToWebMercator(lng, lat, height) {
let mercator = {};
let x = (lng * 20037508.34) / 180;
let y = Math.log(Math.tan(((90 + lat) * Math.PI) / 360)) / (Math.PI / 180);
y = (y * 20037508.34) / 180;
mercator.x = x;
mercator.y = y;
mercator.z = height;
return mercator;
}
clearAll() {
this._result && this._viewer.entities.remove(this._result.entity);
this._result = undefined;
}
}
export default HeatmapIntensity;
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment