JSAPIThree 数据源系统学习笔记:让数据在地图上可视化
<blockquote><p>作为一个刚开始学习 mapvthree 的小白,今天要学习数据源系统了!听说这个系统可以把各种格式的数据加载到地图上,还能让数据可视化!想想就实用!</p>
</blockquote>
<h2 id="第一次听说数据源系统">第一次听说数据源系统</h2>
<p>今天在文档里看到了"数据源"这个词,一开始我还以为是数据库,结果查了一下才知道,原来这是用来存储和加载地理数据的系统!</p>
<p>文档说数据源系统可以:</p>
<ul>
<li>存储带坐标信息的数据</li>
<li>支持多种数据格式(GeoJSON、JSON、CSV)</li>
<li>与可视化组件配合使用</li>
<li>动态添加、删除、修改数据</li>
</ul>
<p><strong>我的理解</strong>:简单说就是"数据仓库",把地理数据存起来,然后给可视化组件用!</p>
<h2 id="第一步理解数据源的基本概念">第一步:理解数据源的基本概念</h2>
<p>作为一个初学者,我习惯先理解基本概念。文档说 <code>DataSource</code> 是数据源类,用于存储一组带坐标信息的数据。</p>
<p><strong>我的发现</strong>:数据源通常与可视化组件配合使用:</p>
<pre><code class="language-js">// 创建可视化组件
const point = engine.add(new mapvthree.SimplePoint());
// 创建数据源
const dataSource = new mapvthree.DataSource();
// 将数据源赋值给可视化组件
point.dataSource = dataSource;
</code></pre>
<p><strong>我的理解</strong>:数据源存储数据,可视化组件负责渲染,两者配合才能显示数据!</p>
<h3 id="dataitem数据的最小单元">DataItem:数据的最小单元</h3>
<p>文档说 <code>DataItem</code> 是数据的最小单元,用于存储单条数据的信息。</p>
<pre><code class="language-js">// 创建一个点数据
const dataItem = new mapvthree.DataItem();
// 添加到数据源
dataSource.add(dataItem);
</code></pre>
<p><strong>我的理解</strong>:</p>
<ul>
<li><code>DataItem</code> 是单条数据</li>
<li><code>DataSource</code> 是数据集合</li>
<li>一个数据源可以包含多个 <code>DataItem</code></li>
</ul>
<h2 id="第二步使用-geojson-数据源">第二步:使用 GeoJSON 数据源</h2>
<p>看到基本概念后,我想:怎么加载实际的数据?</p>
<p>文档说可以用 <code>GeoJSONDataSource</code> 来加载 GeoJSON 格式的数据!</p>
<pre><code class="language-js">import * as mapvthree from '@baidumap/mapv-three';
const container = document.getElementById('container');
const engine = new mapvthree.Engine(container, {
map: {
center: ,
range: 2000,
},
});
// 创建点图层
const point = engine.add(new mapvthree.SimplePoint({
size: 15,
}));
// 从 URL 加载 GeoJSON 数据
const dataSource = await mapvthree.GeoJSONDataSource.fromURL('data/geojson/points.geojson');
point.dataSource = dataSource;
</code></pre>
<p><strong>我的发现</strong>:<code>fromURL</code> 是异步方法,需要用 <code>await</code> 等待数据加载完成!</p>
<p><strong>我的理解</strong>:</p>
<ul>
<li><code>fromURL</code>:从 URL 加载数据</li>
<li><code>fromGeoJSON</code>:直接传入 GeoJSON 对象</li>
</ul>
<p><strong>我的尝试</strong>:</p>
<pre><code class="language-js">// 方式 1:从 URL 加载
const dataSource1 = await mapvthree.GeoJSONDataSource.fromURL('data/geojson/points.geojson');
// 方式 2:直接传入 GeoJSON 对象
const geojson = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: ,
},
properties: {},
},
],
};
const dataSource2 = mapvthree.GeoJSONDataSource.fromGeoJSON(geojson);
</code></pre>
<p><strong>我的发现</strong>:两种方式都可以,根据数据来源选择合适的方式!</p>
<h2 id="第三步使用-json-数据源">第三步:使用 JSON 数据源</h2>
<p>看到 GeoJSON 后,我想:如果数据是 JSON 格式怎么办?</p>
<p>文档说可以用 <code>JSONDataSource</code> 来加载 JSON 格式的数据!</p>
<pre><code class="language-js">// 从 URL 加载 JSON 数据
const dataSource = await mapvthree.JSONDataSource.fromURL('data/json/points.json');
point.dataSource = dataSource;
</code></pre>
<p><strong>我的理解</strong>:JSON 数据源需要满足特定格式:</p>
<ol>
<li>有坐标字段(默认是 <code>coordinates</code>,可通过 <code>coordinatesKey</code> 指定)</li>
<li>坐标数据满足 WKT 格式要求</li>
</ol>
<p><strong>我的尝试</strong>:</p>
<pre><code class="language-js">// JSON 数据格式示例
const jsonData = [{
coordinates: 'POINT(116.404 39.915)',
name: '北京',
}, {
coordinates: 'POINT(121.473 31.230)',
name: '上海',
}];
const dataSource = mapvthree.JSONDataSource.fromJSON(jsonData);
point.dataSource = dataSource;
</code></pre>
<p><strong>我的发现</strong>:JSON 数据源支持 WKT 格式的坐标!</p>
<h3 id="自定义坐标解析">自定义坐标解析</h3>
<p>如果坐标不是 WKT 格式,可以自定义解析函数:</p>
<pre><code class="language-js">const dataSource = mapvthree.JSONDataSource.fromJSON([{
position: ,
color: 0xff0000,
}, {
position: '121.473, 31.230',
color: 0x00ff00,
}], {
coordinatesKey: 'position', // 指定坐标字段
parseCoordinates: function({position}) {
// 自定义解析函数
if (Array.isArray(position)) {
return position;
} else {
return position.split(',').map(v => parseFloat(v));
}
},
});
</code></pre>
<p><strong>我的发现</strong>:可以自定义解析函数,处理各种格式的坐标数据!</p>
<h2 id="第四步使用-csv-数据源">第四步:使用 CSV 数据源</h2>
<p>看到 JSON 后,我想:如果数据是 CSV 格式怎么办?</p>
<p>文档说可以用 <code>CSVDataSource</code> 来加载 CSV 格式的数据!</p>
<pre><code class="language-js">// 从 URL 加载 CSV 数据
const dataSource = await mapvthree.CSVDataSource.fromURL('data/csv/points.csv');
point.dataSource = dataSource;
</code></pre>
<p><strong>我的理解</strong>:CSV 数据源也需要满足特定格式:</p>
<ol>
<li>有坐标列(默认是 <code>coordinates</code>,可通过 <code>coordinatesKey</code> 指定)</li>
<li>坐标数据满足 WKT 格式要求</li>
</ol>
<p><strong>我的发现</strong>:CSV 数据源和 JSON 数据源的格式要求类似,都支持 WKT 格式!</p>
<h2 id="第五步定义数据属性">第五步:定义数据属性</h2>
<p>看到可以加载数据后,我想:能不能根据数据的不同属性显示不同的样式?</p>
<p>文档说可以用 <code>defineAttribute</code> 来定义数据属性!</p>
<pre><code class="language-js">// 加载数据
const dataSource = await mapvthree.GeoJSONDataSource.fromURL('data/geojson/points.geojson');
// 定义颜色属性
dataSource.defineAttribute('color', 'color');
// 定义大小属性
dataSource.defineAttribute('size', 'size');
</code></pre>
<p><strong>我的理解</strong>:<code>defineAttribute</code> 可以将数据中的字段映射到可视化属性!</p>
<p><strong>我的尝试</strong>:</p>
<pre><code class="language-js">// 创建支持颜色和大小的点图层
const point = engine.add(new mapvthree.SimplePoint({
vertexColors: true, // 开启颜色属性
vertexSizes: true,// 开启大小属性
}));
// 加载数据并定义属性
const dataSource = await mapvthree.GeoJSONDataSource.fromURL('data/geojson/points.geojson');
dataSource.defineAttribute('color', 'color');
dataSource.defineAttribute('size', 'size');
point.dataSource = dataSource;
</code></pre>
<p><strong>我的发现</strong>:需要在可视化组件中开启对应的属性标志(如 <code>vertexColors</code>),才能使用数据属性!</p>
<h3 id="使用回调函数定义属性">使用回调函数定义属性</h3>
<p>文档说可以用回调函数来动态计算属性值:</p>
<pre><code class="language-js">// 使用回调函数定义颜色
dataSource.defineAttribute('color', properties => {
// 根据数据动态计算颜色
return properties.count > 100 ? 0xff0000 : 0x00ff00;
});
// 使用回调函数定义大小
dataSource.defineAttribute('size', properties => {
return properties.count * 2;
});
</code></pre>
<p><strong>我的发现</strong>:回调函数可以灵活地根据数据计算属性值!</p>
<h2 id="第六步动态修改数据">第六步:动态修改数据</h2>
<p>看到可以加载数据后,我想:能不能动态添加、删除、修改数据?</p>
<p>文档说数据源提供了 <code>add</code>、<code>remove</code>、<code>setData</code> 等方法来修改数据!</p>
<pre><code class="language-js">// 添加数据
const newItem = new mapvthree.DataItem();
dataSource.add(newItem);
// 删除数据
dataSource.remove(itemId);
// 更新整个数据源
dataSource.setData(newGeoJSONData);
// 修改单个数据的属性
dataSource.setAttributeValues(itemId, {
color: 0xff0000,
size: 20,
});
// 修改单个数据的坐标
dataSource.setCoordinates(itemId, );
</code></pre>
<p><strong>我的发现</strong>:可以动态地添加、删除、修改数据,非常灵活!</p>
<p><strong>我的尝试</strong>:</p>
<pre><code class="language-js">// 点击地图添加点
engine.map.addEventListener('click', e => {
if (!e.target) {
const newItem = new mapvthree.DataItem(e.point);
dataSource.add(newItem);
}
});
// 点击点删除
point.addEventListener('rightclick', e => {
dataSource.remove(e.entity.value.id);
});
// 点击点修改颜色
point.addEventListener('click', e => {
dataSource.setAttributeValues(e.entity.value.id, {
color: 0xffffff * Math.random(),
});
});
</code></pre>
<p><strong>我的发现</strong>:结合事件系统,可以实现交互式的数据编辑!</p>
<h2 id="第七步创建自定义数据源">第七步:创建自定义数据源</h2>
<p>看到可以加载各种格式的数据后,我想:能不能手动创建数据源?</p>
<p>文档说可以直接使用 <code>DataSource</code> 构造函数创建数据源!</p>
<pre><code class="language-js">// 创建数据源
const dataSource = new mapvthree.DataSource({
attributes: {
color: p => p.color || 0xffff00,
size: p => p.size || 10,
},
});
// 创建数据项
const item1 = new mapvthree.DataItem(, {
color: 0xff0000,
size: 20,
});
const item2 = new mapvthree.DataItem(, {
color: 0x00ff00,
size: 15,
});
// 添加数据项
dataSource.add(item1);
dataSource.add(item2);
// 绑定到可视化组件
point.dataSource = dataSource;
</code></pre>
<p><strong>我的发现</strong>:可以手动创建数据源和数据项,适合动态生成数据的场景!</p>
<h3 id="创建不同类型的几何数据">创建不同类型的几何数据</h3>
<p>文档说 <code>DataItem</code> 可以表示不同类型的几何图形:</p>
<pre><code class="language-js">// 点数据
const pointItem = new mapvthree.DataItem();
// 线数据
const lineItem = new mapvthree.DataItem({
geometry: {
type: 'LineString',
coordinates: [, ],
},
});
// 面数据
const polygonItem = new mapvthree.DataItem({
geometry: {
type: 'Polygon',
coordinates: [[, , , , ]],
},
});
</code></pre>
<p><strong>我的发现</strong>:可以创建点、线、面等不同类型的几何数据!</p>
<h2 id="第八步设置数据投影">第八步:设置数据投影</h2>
<p>看到可以创建数据后,我想:如果数据的坐标系统不同怎么办?</p>
<p>文档说可以通过 <code>crs</code> 属性来设置数据的投影信息!</p>
<pre><code class="language-js">// 创建使用投影坐标的数据项
const item = new mapvthree.DataItem({
geometry: {
type: 'Point',
coordinates: , // 投影坐标
},
}, {
crs: 'EPSG:3857', // 指定投影
});
</code></pre>
<p><strong>我的理解</strong>:引擎会自动将数据从源投影转换到目标投影!</p>
<p><strong>我的发现</strong>:这样就能处理不同坐标系统的数据了!</p>
<h2 id="第九步完整示例">第九步:完整示例</h2>
<p>我想写一个完整的示例,把学到的都用上:</p>
<pre><code class="language-js">import * as mapvthree from '@baidumap/mapv-three';
const container = document.getElementById('container');
const engine = new mapvthree.Engine(container, {
map: {
center: ,
range: 2000,
},
rendering: {
enableAnimationLoop: true,
},
});
// 创建支持颜色和大小的点图层
const point = engine.add(new mapvthree.SimplePoint({
size: 15,
vertexColors: true,
vertexSizes: true,
}));
// 从 URL 加载 GeoJSON 数据
const dataSource = await mapvthree.GeoJSONDataSource.fromURL('data/geojson/points.geojson');
// 定义属性
dataSource.defineAttribute('color', properties => {
return properties.count > 100 ? 0xff0000 : 0x00ff00;
});
dataSource.defineAttribute('size', properties => {
return properties.count * 2;
});
// 绑定数据源
point.dataSource = dataSource;
// 点击地图添加点
engine.map.addEventListener('click', e => {
if (!e.target) {
const newItem = new mapvthree.DataItem(e.point, {
count: Math.random() * 200,
});
dataSource.add(newItem);
}
});
// 点击点修改颜色
point.addEventListener('click', e => {
dataSource.setAttributeValues(e.entity.value.id, {
count: Math.random() * 200,
});
});
</code></pre>
<p><strong>我的感受</strong>:写一个完整的示例,把学到的都用上,感觉很有成就感!</p>
<h2 id="第十步踩过的坑">第十步:踩过的坑</h2>
<p>作为一个初学者,我踩了不少坑,记录下来避免再犯:</p>
<h3 id="坑-1数据源不显示">坑 1:数据源不显示</h3>
<p><strong>原因</strong>:数据源加载是异步的,在数据加载完成前就绑定了。</p>
<p><strong>解决</strong>:确保使用 <code>await</code> 等待数据加载完成后再绑定。</p>
<h3 id="坑-2属性不生效">坑 2:属性不生效</h3>
<p><strong>原因</strong>:没有在可视化组件中开启对应的属性标志。</p>
<p><strong>解决</strong>:需要在组件中开启对应的属性标志,如 <code>vertexColors</code>、<code>vertexSizes</code>。</p>
<h3 id="坑-3坐标格式错误">坑 3:坐标格式错误</h3>
<p><strong>原因</strong>:坐标格式不符合要求,或者坐标字段名不对。</p>
<p><strong>解决</strong>:</p>
<ol>
<li>确保坐标格式正确(WKT 格式或数组格式)</li>
<li>使用 <code>coordinatesKey</code> 指定坐标字段名</li>
</ol>
<h3 id="坑-4jsoncsv-数据解析失败">坑 4:JSON/CSV 数据解析失败</h3>
<p><strong>原因</strong>:坐标数据不是 WKT 格式,且没有自定义解析函数。</p>
<p><strong>解决</strong>:使用 <code>parseCoordinates</code> 自定义解析函数。</p>
<h3 id="坑-5数据更新不生效">坑 5:数据更新不生效</h3>
<p><strong>原因</strong>:使用了错误的方法更新数据。</p>
<p><strong>解决</strong>:</p>
<ul>
<li>更新整个数据源:使用 <code>setData</code></li>
<li>添加/删除数据:使用 <code>add</code>/<code>remove</code></li>
<li>修改属性:使用 <code>setAttributeValues</code></li>
<li>修改坐标:使用 <code>setCoordinates</code></li>
</ul>
<h2 id="我的学习总结">我的学习总结</h2>
<p>经过这一天的学习,我掌握了:</p>
<ol>
<li><strong>数据源的作用</strong>:存储带坐标信息的数据,与可视化组件配合使用</li>
<li><strong>DataItem</strong>:数据的最小单元,可以表示点、线、面等几何图形</li>
<li><strong>GeoJSON 数据源</strong>:最常用的数据格式,支持 <code>fromURL</code> 和 <code>fromGeoJSON</code></li>
<li><strong>JSON 数据源</strong>:支持 WKT 格式坐标,可以自定义解析函数</li>
<li><strong>CSV 数据源</strong>:支持 WKT 格式坐标,格式要求与 JSON 类似</li>
<li><strong>定义属性</strong>:通过 <code>defineAttribute</code> 将数据字段映射到可视化属性</li>
<li><strong>动态修改</strong>:通过 <code>add</code>、<code>remove</code>、<code>setData</code> 等方法动态修改数据</li>
<li><strong>数据投影</strong>:通过 <code>crs</code> 属性设置数据投影,引擎自动转换</li>
</ol>
<p><strong>我的感受</strong>:数据源系统真的很强大!虽然功能很多,但是用起来其实不难。关键是要理解数据源和可视化组件的关系,然后根据数据格式选择合适的加载方式!</p>
<p><strong>下一步计划</strong>:</p>
<ol>
<li>学习更多数据源的配置选项</li>
<li>尝试处理复杂的数据格式</li>
<li>做一个完整的数据可视化项目</li>
</ol>
<hr>
<blockquote>
<p>学习笔记就到这里啦!作为一个初学者,我觉得数据源系统虽然功能很多,但是用起来其实不难。关键是要理解数据源和可视化组件的关系,然后根据数据格式选择合适的加载方式!希望我的笔记能帮到其他初学者!大家一起加油!</p>
</blockquote><br><br>
来源:https://www.cnblogs.com/map-3d-vis/p/19296100
頁:
[1]