一、效果图
二、实现思路
使用着色器,通过纹理坐标和其他参数计算出材质的颜色和透明度。通过给定的颜色、漫反射强度和透明度,计算出最终的反射颜色和透明度,并且根据给定的中心点位置和当前像素的纹理坐标,计算出距离中心的距离用来做透明度的参考值,然后计算得到的颜色加载到对应的材质上。
三、完整代码
<template>
<div>
<button @click="handlePolygon()">渐变面</button>
<CesiumViewer />
</div>
</template>
<script setup>
import { ref, onMounted } from "vue";
import CesiumViewer from "./components/cesiumViewer.vue";
let viewer;
onMounted(() => {
viewer = window.cesiumViewer;
});
const updateResolutionScale = (viewer) => {
//判断是否支持图像渲染像素化处理
if (Cesium.FeatureDetection.supportsImageRenderingPixelated()) {
viewer.resolutionScale = window.devicePixelRatio;
}
};
const PolyGradientMaterial = `uniform vec4 color;
uniform float diffusePower;
uniform float alphaPower;
uniform float globalAlpha;
uniform vec2 center;
czm_material czm_getMaterial(czm_materialInput materialInput) {
czm_material material = czm_getDefaultMaterial(materialInput);
float time = czm_frameNumber/600.;
float per = fract(time);
vec2 st = materialInput.st;
float alpha = distance(st, center);
material.alpha = color.a * alpha * alphaPower * globalAlpha;
material.diffuse = color.rgb * diffusePower;
return material;
}`;
let index = 0;
const arrColor = [
"rgb(18,76,154)",
"rgb(15,176,255)",
"#40C4E4",
"#42B2BE",
"rgb(51,176,204)",
"#8CB7E5",
"rgb(0,244,188)",
"#139FF0",
];
const getColor = () => {
return arrColor[++index % arrColor.length];
};
let totalLabel = 0;
const addPolygon = (positions, color, name) => {
const polygonOptions = {
extrudedHeight: 1000,
polygonHierarchy: new Cesium.PolygonHierarchy(positions),
};
const geometry = new Cesium.PolygonGeometry(polygonOptions);
const geometryInstance = new Cesium.GeometryInstance({
geometry: geometry,
id: "chinaocean",
});
const material = new Cesium.Material({
fabric: {
source: PolyGradientMaterial,
uniforms: {
color: Cesium.Color.fromCssColorString(color),
diffusePower: 1.8,
alphaPower: 1.2,
center: new Cesium["Cartesian2"](0.5, 0.5),
globalAlpha: 0x1,
},
},
translucent: true,
});
const primitive = new Cesium.Primitive({
releaseGeometryInstances: false,
asynchronous: false,
geometryInstances: [geometryInstance],
appearance: new Cesium.EllipsoidSurfaceAppearance({
material: material,
}),
});
// const removeListener = viewer.scene.postRender.addEventListener(() => {
// if (!primitive.ready) {
// return;
// }
// totalLabel += 1;
// const position = primitive._boundingSpheres[0].center;
// viewer.entities.add({
// position,
// label: {
// text: name,
// font: "32px 楷体",
// fillColor: Cesium.Color.WHITE,
// outlineColor: Cesium.Color.BLACK,
// style: Cesium.LabelStyle.FILL_AND_OUTLINE,
// outlineWidth: 2,
// disableDepthTestDistance: 1000000000,
// scale: 0.5,
// pixelOffset: new Cesium.Cartesian2(0, -10),
// backgroundColor: new Cesium.Color.fromCssColorString(
// "rgba(0, 0, 0, 0.7)"
// ),
// backgroundPadding: new Cesium.Cartesian2(10, 10),
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
// },
// });
// removeListener();
// });
viewer.scene.primitives.add(primitive);
};
const handlePolygon = () => {
updateResolutionScale(viewer);
viewer.scene.skyBox.show = false;
var mapOptions = {
scene: {
center: {
lat: 30.037072,
lng: 91.091762,
alt: 1600000.0,
heading: 160000.0,
// 视角
heading: 355,
pitch: -88,
},
},
};
viewer.camera.flyTo({
orientation: {
heading: Cesium.Math.toRadians(mapOptions.scene.center.heading),
pitch: Cesium.Math.toRadians(mapOptions.scene.center.pitch),
},
destination: Cesium.Cartesian3.fromDegrees(
mapOptions.scene.center.lng,
mapOptions.scene.center.lat,
mapOptions.scene.center.alt
),
duration: 0,
});
Cesium.GeoJsonDataSource.load(
"https://geo.datav.aliyun.com/areas_v3/bound/540100.json"
).then((dataSource) => {
const entities = dataSource.entities.values;
// 遍历所有实体
entities.forEach((entity, index) => {
if (entity.polygon) {
const positions = entity.polygon.hierarchy._value.positions;
addPolygon(positions, getColor(index), entity.name);
}
});
});
};
</script>
<style scoped></style>
*注:<CesiumViewer/>