目录
一、openlayers
通过css滤镜的方式改变地图颜色。
const layerObj = new TileLayer({
className: 'baseLayerClass', //重点代码!!!
zIndex: zIndex,
source: new WMTS({
url: 'https://t{0-7}.tianditu.gov.cn/' + serviceName + '_c/wmts?tk=' + tk,
crossOrigin: 'anonymous',
tileGrid: new WMTSTileGrid({
origin: getTopLeft(projectionExtent),
resolutions: resolutions,
matrixIds: ids
}),
format: 'tiles',
layer: serviceName,
matrixSet: 'c',
style: ''
})
});
css样式中配置
//地图配色
.baseLayerClass {
filter: grayscale(76%) sepia(55%) invert(100%) saturate(236%);
}
二、cesium
天地图加载完之后调用
addTiandituLayerFilter()
如果要切换主题的话,要把之前的着色器代码保存一下,方便恢复
// 在外部保存原始着色器代码的引用
let originalFragShaderSources = ref([]);
// 添加颜色滤镜 主题
function addTiandituLayerFilter() {
if(sideTheme.value === 'theme-dark') {
const filterParams = {
bInvertColor: true, // 启用颜色反转
bFilterColor: true, // 启用颜色过滤
filterColor: '#0044aa' // 过滤颜色值
}
tiandituLayer.brightness = 0.6 // 亮度降低
tiandituLayer.contrast = 1.8 // 对比度增强
tiandituLayer.gamma = 0.3 // 伽马值调整
tiandituLayer.hue = 1 // 色相保持
tiandituLayer.saturation = 0 // 饱和度归零
filterLayer(filterParams)
} else {
// 亮色主题:恢复原始着色器
if(originalFragShaderSources.value.length > 0) {
viewer.scene.globe._surfaceShaderSet.baseFragmentShaderSource.sources = originalFragShaderSources.value
}
}
}
function filterLayer(options) {
const {bInvertColor, bFilterColor, filterColor } = options
const color = new Cesium.Color.fromCssColorString(filterColor);
// 提取RGB分量并转换为0-255整数
const filterRGB = [
Math.round(color.red * 255),
Math.round(color.green * 255),
Math.round(color.blue * 255)
]
let fragShader = viewer.scene.globe._surfaceShaderSet.baseFragmentShaderSource.sources
originalFragShaderSources.value = JSON.parse(JSON.stringify(fragShader))
for (let i = 0; i < fragShader.length; i++) {
// 定位要修改的代码位置(饱和度计算后)
const strS = 'color = czm_saturation(color, textureSaturation);\n#endif\n'
let strT = 'color = czm_saturation(color, textureSaturation);\n#endif\n'
if (bInvertColor) {
strT += `
color.r = 1.0 - color.r;
color.g = 1.0 - color.g;
color.b = 1.0 - color.b;
`
}
if (bFilterColor) {
strT += `
color.r = color.r * ${filterRGB[0]}.0/255.0;
color.g = color.g * ${filterRGB[1]}.0/255.0;
color.b = color.b * ${filterRGB[2]}.0/255.0;
`
}
fragShader[i] = fragShader[i].replace(strS, strT)
}
}
三、openlayers天地图调色demo
以下代码可以直接复制到html文件中运行,通过滑块调整获取 filter: grayscale(76%) sepia(55%) invert(100%) saturate(236%);几个参数的值,调整好以后,直接复制到代码中使用。
<!DOCTYPE html>
<html>
<head>
<title>天地图滤镜控制</title>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/css/ol.css">
<style>
.map {
width: 100%;
height: 90vh;
}
.controls {
position: absolute;
top: 10px;
left: 50px;
background: rgba(255, 255, 255, 0.8);
padding: 10px;
border-radius: 5px;
z-index: 1000;
}
.control-group {
margin: 5px 0;
}
label {
display: inline-block;
width: 120px;
}
/* ' hue-rotate(180deg) saturate(1600%) brightness(180%) contrast(90%)'; */
</style>
</head>
<body>
<div id="map" class="map"></div>
<div class="controls">
<div class="control-group">
<label>Grayscale: <span id="grayscaleValue">100</span>%</label>
<input type="range" id="grayscale" min="0" max="100" value="100">
</div>
<div class="control-group">
<label>Sepia: <span id="sepiaValue">51</span>%</label>
<input type="range" id="sepia" min="0" max="100" value="51">
</div>
<div class="control-group">
<label>Invert: <span id="invertValue">100</span>%</label>
<input type="range" id="invert" min="0" max="100" value="100">
</div>
<div class="control-group">
<label>Saturate: <span id="saturateValue">350</span>%</label>
<input type="range" id="saturate" min="0" max="500" value="350">
</div>
</div>
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/build/ol.js"></script>
<script>
const tk = '你的天地图token';
// 创建投影和分辨率配置
const projection = ol.proj.get('EPSG:4326');
const projectionExtent = projection.getExtent();
const size = ol.extent.getWidth(projectionExtent) / 256;
const resolutions = new Array(20);
const matrixIds = new Array(20);
// 渌口区王家洲村坐标(使用高德地图获取的坐标)
const targetLonLat = [113.138728, 27.694423]; // WGS84坐标
const targetCoordinate = ol.proj.fromLonLat(targetLonLat);
for (let z = 0; z < 20; ++z) {
resolutions[z] = size / Math.pow(2, z);
matrixIds[z] = z;
}
// 创建天地图图层
const layer = new ol.layer.Tile({
className: 'base-layer',
source: new ol.source.WMTS({
url: `https://t5.tianditu.gov.cn/vec_c/wmts?tk=${tk}`,
layer: 'vec',
matrixSet: 'c',
format: 'tiles',
projection: projection,
tileGrid: new ol.tilegrid.WMTS({
origin: ol.extent.getTopLeft(projectionExtent),
resolutions: resolutions,
matrixIds: matrixIds
}),
style: 'default',
wrapX: true,
crossOrigin: 'anonymous'
})
});
const layer_B = new ol.layer.Tile({
className: 'base-layer',
source: new ol.source.WMTS({
url: `https://t5.tianditu.gov.cn/cva_c/wmts?tk=${tk}`,
layer: 'cva',
matrixSet: 'c',
format: 'tiles',
projection: projection,
tileGrid: new ol.tilegrid.WMTS({
origin: ol.extent.getTopLeft(projectionExtent),
resolutions: resolutions,
matrixIds: matrixIds
}),
style: 'default',
wrapX: true,
crossOrigin: 'anonymous'
})
});
// 创建地图实例
const map = new ol.Map({
target: 'map',
layers: [layer,layer_B],
view: new ol.View({
center: targetCoordinate, // 初始定位到目标位置
zoom: 14 // 调整到合适的缩放级别
})
});
// 获取滤镜控制元素
const grayscale = document.getElementById('grayscale');
const sepia = document.getElementById('sepia');
const invert = document.getElementById('invert');
const saturate = document.getElementById('saturate');
// 初始化滤镜值
let currentFilters = {
grayscale: 100,
sepia: 51,
invert: 100,
saturate: 350,
};
// 更新滤镜显示
function updateDisplay() {
document.getElementById('grayscaleValue').textContent = currentFilters.grayscale;
document.getElementById('sepiaValue').textContent = currentFilters.sepia;
document.getElementById('invertValue').textContent = currentFilters.invert;
document.getElementById('saturateValue').textContent = currentFilters.saturate;
}
// 应用滤镜到地图
function applyFilters() {
const filterStr =
`grayscale(${currentFilters.grayscale}%) ` +
`sepia(${currentFilters.sepia}%) ` +
`invert(${currentFilters.invert}%) ` +
`saturate(${currentFilters.saturate}%)`;
console.log('filterStr',filterStr);
const layerElement = document.querySelector('.base-layer');
if (layerElement) {
layerElement.style.filter = filterStr;
}
}
// 事件监听
grayscale.addEventListener('input', (e) => {
currentFilters.grayscale = e.target.value;
updateDisplay();
applyFilters();
});
sepia.addEventListener('input', (e) => {
currentFilters.sepia = e.target.value;
updateDisplay();
applyFilters();
});
invert.addEventListener('input', (e) => {
currentFilters.invert = e.target.value;
updateDisplay();
applyFilters();
});
saturate.addEventListener('input', (e) => {
currentFilters.saturate = e.target.value;
updateDisplay();
applyFilters();
});
// 初始化显示
updateDisplay();
applyFilters();
</script>
</body>
</html>
注意:
1、这个里面需要替换为自己的token
2、天地图和ol的引用使用的都是在线地址,如果加载不出来,需要替换
3、有跨域问题,可以直接用浏览器的非安全模式打开