工作中遇到一个比较复杂的功能,其中用到渐变色,于是研究了一下,发现虽然 JS API 不直接支持渐变色,但是也可以自定义创建渐变色,通过 Mesh 自定义顶点、索引来实现。
这里简单介绍一下原理,并且提供在线渐变色示例。
本文包括 核心代码、完整代码以及在线示例。
核心代码
介绍一下原理:首先通过 canvas 创建渐变色,可以选择两个颜色或者多个颜色。
根据想要创建的几何体,构建顶点和索引数据,简单图形的话,根据经验即可,如果是复杂几何体,
可以通过一些工具来获取,然后通过 Mesh 创建几何体对象即可,最终添加到地图中。
// 创建渐变色
function createLinearGradient() {
const canvas = document.createElement("canvas");
const width = 32 * 32;
const height = 32 * 32;
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d");
ctx.globalAlpha = globalAlpha;
// Create the linear gradient with which to fill the canvas
const gradient = ctx.createLinearGradient(0, 0, width, 0);
// 这里创建三个渐变色,可随意调整
gradient.addColorStop(0, "#0000ff");
gradient.addColorStop(0.5, "#ff0000");
gradient.addColorStop(1, "#ffffff");
// Fill the canvas with the gradient pattern
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, width, height);
return canvas;
}
const uv = 1;
// 材质
const material = {
colorTexture: {
data: createLinearGradient(),
wrap: 'clamp'
},
};
// 创建 box
const mesh = new Mesh({
// 顶点属性
vertexAttributes: {
position: cameraPositionGeographic,
uv: [
0, 0,
uv, 0,
uv, 0,
uv, 0,
uv, 0,
]
},
// 三角面材质纹理
components: [
{
faces: [0, 2, 1],
material
},
{
faces: [0, 2, 3],
material
},
{
faces: [0, 3, 4],
material
},
{
faces: [0, 4, 1],
material
},
{
faces: [1, 2, 4],
material: {
color: "transparent"
}
},
{
faces: [2, 3, 4],
material: {
color: "transparent"
}
}],
spatialReference,
})
完整代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
<title>ArcGIS JS API mesh 自定义几何渐变色示例</title>
<style>
html, body, #viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<!-- 引入ArcGIS JS API样式和脚本 -->
<link rel="stylesheet" href="https://js.arcgis.com/4.28/esri/themes/light/main.css">
<script src="https://js.arcgis.com/4.28/"></script>
<script>
require([
"esri/Map",
"esri/views/SceneView",
"esri/WebScene",
"esri/geometry/Mesh",
"esri/geometry/Point",
"esri/geometry/SpatialReference",
"esri/Graphic",
], function (Map, SceneView, WebScene, Mesh, Point, SpatialReference, Graphic,
) {
const view = new SceneView({
container: "viewDiv",
map: new Map({
basemap: "hybrid",
}),
});
const spatialReference = SpatialReference.WebMercator;
// 视椎体顶点
const cameraPositionGeographic = [12121597.211481025, 4060392.3041098495, 673.0166350845248, 12121688.817691227, 4060067.135944337, 825.3678379664198, 12121265.251479909, 4060329.6045611626, 825.3678379654884, 12121245.121950569, 4060297.137362419, 571.5452030794695, 12121668.70426917, 4060034.659804911, 571.5452030794695]
// 透明度
const globalAlpha = 0.7;
// 创建渐变色
function createLinearGradient() {
const canvas = document.createElement("canvas");
const width = 32 * 32;
const height = 32 * 32;
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d");
ctx.globalAlpha = globalAlpha;
// Create the linear gradient with which to fill the canvas
const gradient = ctx.createLinearGradient(0, 0, width, 0);
// 这里创建三个渐变色,可随意调整
gradient.addColorStop(0, "#0000ff");
gradient.addColorStop(0.5, "#ff0000");
gradient.addColorStop(1, "#ffffff");
// Fill the canvas with the gradient pattern
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, width, height);
return canvas;
}
const uv = 1;
// 材质
const material = {
colorTexture: {
data: createLinearGradient(),
wrap: 'clamp'
},
};
// 创建 box
const mesh = new Mesh({
// 顶点属性
vertexAttributes: {
position: cameraPositionGeographic,
uv: [
0, 0,
uv, 0,
uv, 0,
uv, 0,
uv, 0,
]
},
// 三角面材质纹理
components: [
{
faces: [0, 2, 1],
material
},
{
faces: [0, 2, 3],
material
},
{
faces: [0, 3, 4],
material
},
{
faces: [0, 4, 1],
material
},
{
faces: [1, 2, 4],
material: {
color: "transparent"
}
},
{
faces: [2, 3, 4],
material: {
color: "transparent"
}
}],
spatialReference,
})
const conusGraphic = new Graphic({
// 缩放至矩阵范围
geometry: mesh,
symbol: {
type: "mesh-3d",
symbolLayers: [
{
type: "fill",
},
],
},
});
// 将圆柱体添加到视图
view.graphics.add(conusGraphic);
// 当视图加载完成后执行
view.when(() => {
// 将视图缩放到圆柱体范围
view.goTo({
target: mesh,
tilt: 90,
heading: 150
}, {duration: 1500});
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>
在线示例
ArcGIS Maps SDK for JavaScript 在线示例:创建渐变色材质的自定义几何体