如何在 Mapbox GL JS 动画中对 LineString 段进行不同的着色
How to color LineString segments differently in Mapbox GL JS animations
我正在制作一个动画,根据我获得的一些历史 GPS 项圈数据显示狼的行踪。
该代码基于此 Mapbox 示例:
https://docs.mapbox.com/mapbox-gl-js/example/live-update-feature/
我想根据是白天还是夜晚给线段上色,蓝色代表夜晚,红色代表白天。像这样:
在时间段1,狼向东北偏东移动;现在是晚上,所以线段是蓝色的。在时间段 2,狼向东北移动;现在是白天,所以线段是红色的。在时间段 3,狼再次向东北偏东方向移动;现在是晚上,所以线段又是蓝色的。
但我似乎无法使用不同的颜色。我有一些 toy/example 数据:
{ "type": "FeatureCollection", "features": [ { "type": "Feature", "geometry": {
"type": "LineString", "coordinates" : [[-112.191833, 57.073668],
[-112.181833, 57.083668],
[-112.181833, 57.073668],
[-112.201833, 57.075668]]} } ],
"properties": {"daytime" : [0, 1, 1, 0] }}
有4个时间段,中间两个是白天(设置为1)。
这是我的代码。 (您需要粘贴您的 mapbox 键才能工作):
mapboxgl.accessToken = 'INSERT YOUR MAPBOX KEY HERE';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/satellite-v9',
zoom: 0
});
map.on('load', function() {
// We use D3 to fetch the JSON here to parse and use it separately
// from GL JS's use in the added source. You can use any request method
// that you want.
d3.json(
"https://raw.githubusercontent.com/pete-rodrigue/wolves_of_alberta/data_store/wolves_geojson_example.geojson?token=ACEMB42EH5NKZSF24MHPQSS6JFTMU",
function(err, data) {
if (err) throw err;
// save full coordinate list for later
var coordinates = data.features[0].geometry.coordinates;
// save 1's and 0's for later
var daynight = data.properties.daytime
// start by showing just the first coordinate
data.features[0].geometry.coordinates = [coordinates[0]];
// THIS NEXT LINE IS ONE PART OF MY FAILED APPROACH:
data.properties.daytime = ['blue']; // set initial color value to blue
// add it to the map
map.addSource('trace', { type: 'geojson', data: data });
map.addLayer({
'id': 'trace',
'type': 'line',
'source': 'trace',
'paint': {
// THIS WILL WORK FINE
'line-color': 'orange',
// 'line-color': ['to-string', ['get', 'daytime']], // DOES NOT WORK
'line-width': 8
},
layout: {'line-cap': 'round', 'line-join': 'round'}
});
// setup the viewport
map.jumpTo({ 'center': coordinates[0], 'zoom': 13 });
map.setPitch(30);
// on a regular basis, add more coords from the saved list to update map
var i = 0;
var timer = window.setInterval(function() {
if (i < coordinates.length) {
data.features[0].geometry.coordinates.push(
coordinates[i]
);
// if it's daytime, append blue; if it's nighttime, append red
if (daynight[i] == 0) {
data.properties.daytime.push(['blue']);
} else {data.properties.daytime.push(['red']);}
map.getSource('trace').setData(data);
map.panTo(coordinates[i]);
i++;
} else {
window.clearInterval(timer);
}
}, 150);
}
);
});
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
<head>
<meta charset="utf-8" />
<title>Wolves GPS collar example data</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://api.mapbox.com/mapbox-gl-js/v1.7.0/mapbox-gl.js"></script>
<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v1.7.0/mapbox-gl.css" rel="stylesheet" />
<link rel="stylesheet" href="main_css.css">
</head>
<body>
<div id="map"></div>
<script type="text/javascript" src='main_js.js'></script>
</body>
也在这里:
https://codepen.io/pete-rodrigue/pen/XWbJOpK
我已经注释掉了不起作用的部分并留下了注释。
基本上,我正在尝试这样做:
'line-color': ['to-string', ['get', 'daytime']]
在 map.addLayer()
的 paint
部分,其中 daytime
属性 是表示 'blue' 或 'red' 的字符串数组,随着动画的进行,我将新元素推入其中——这是代码的这一部分:
if (daynight[i] == 0) {
data.properties.daytime.push(['blue']); // if it's daytime, append blue
} else {
data.properties.daytime.push(['red']); // if it's nighttime, append red
}
我敢肯定这行不通的原因很明显。但我是新手,无法理解它。
任何基础知识的帮助和解释将不胜感激。
当您指定:
'line-color': ['to-string', ['get', 'daytime']]
在带有 Map#addLayer
的 'trace'
图层中,地图渲染器被告知使用 '[0, 1, 1, 0]'
(在您提供的示例数据的情况下)作为线条的颜色在 ID 为 'trace'
的 source
中。它不会等待您设置计时器,即使它设置了,您也可能 运行 遇到一些 JavaScript 的异步性问题。正如在 Mapbox 的 style specification, 'line-color'
expects a color
中以 HTML 样式的十六进制值、RGB、RGBA、HSL 或 HSLA 形式指出的那样,因此您可能 运行 会出错,因为字符串化数组是 none 这些形式。
相反,我建议将每个时间段分解成它自己的 LineString
,其中 'line-color'
由其在原始颜色数组中的相应值指定,并添加这些 LineString
作为单独的图层添加到地图。然后,您可以通过设置一些间隔来创建动画效果,以指定添加图层和动画的顺序,如 live update feature example.
中所做的那样
我正在制作一个动画,根据我获得的一些历史 GPS 项圈数据显示狼的行踪。 该代码基于此 Mapbox 示例: https://docs.mapbox.com/mapbox-gl-js/example/live-update-feature/
我想根据是白天还是夜晚给线段上色,蓝色代表夜晚,红色代表白天。像这样:
在时间段1,狼向东北偏东移动;现在是晚上,所以线段是蓝色的。在时间段 2,狼向东北移动;现在是白天,所以线段是红色的。在时间段 3,狼再次向东北偏东方向移动;现在是晚上,所以线段又是蓝色的。
但我似乎无法使用不同的颜色。我有一些 toy/example 数据:
{ "type": "FeatureCollection", "features": [ { "type": "Feature", "geometry": {
"type": "LineString", "coordinates" : [[-112.191833, 57.073668],
[-112.181833, 57.083668],
[-112.181833, 57.073668],
[-112.201833, 57.075668]]} } ],
"properties": {"daytime" : [0, 1, 1, 0] }}
有4个时间段,中间两个是白天(设置为1)。
这是我的代码。 (您需要粘贴您的 mapbox 键才能工作):
mapboxgl.accessToken = 'INSERT YOUR MAPBOX KEY HERE';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/satellite-v9',
zoom: 0
});
map.on('load', function() {
// We use D3 to fetch the JSON here to parse and use it separately
// from GL JS's use in the added source. You can use any request method
// that you want.
d3.json(
"https://raw.githubusercontent.com/pete-rodrigue/wolves_of_alberta/data_store/wolves_geojson_example.geojson?token=ACEMB42EH5NKZSF24MHPQSS6JFTMU",
function(err, data) {
if (err) throw err;
// save full coordinate list for later
var coordinates = data.features[0].geometry.coordinates;
// save 1's and 0's for later
var daynight = data.properties.daytime
// start by showing just the first coordinate
data.features[0].geometry.coordinates = [coordinates[0]];
// THIS NEXT LINE IS ONE PART OF MY FAILED APPROACH:
data.properties.daytime = ['blue']; // set initial color value to blue
// add it to the map
map.addSource('trace', { type: 'geojson', data: data });
map.addLayer({
'id': 'trace',
'type': 'line',
'source': 'trace',
'paint': {
// THIS WILL WORK FINE
'line-color': 'orange',
// 'line-color': ['to-string', ['get', 'daytime']], // DOES NOT WORK
'line-width': 8
},
layout: {'line-cap': 'round', 'line-join': 'round'}
});
// setup the viewport
map.jumpTo({ 'center': coordinates[0], 'zoom': 13 });
map.setPitch(30);
// on a regular basis, add more coords from the saved list to update map
var i = 0;
var timer = window.setInterval(function() {
if (i < coordinates.length) {
data.features[0].geometry.coordinates.push(
coordinates[i]
);
// if it's daytime, append blue; if it's nighttime, append red
if (daynight[i] == 0) {
data.properties.daytime.push(['blue']);
} else {data.properties.daytime.push(['red']);}
map.getSource('trace').setData(data);
map.panTo(coordinates[i]);
i++;
} else {
window.clearInterval(timer);
}
}, 150);
}
);
});
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
<head>
<meta charset="utf-8" />
<title>Wolves GPS collar example data</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://api.mapbox.com/mapbox-gl-js/v1.7.0/mapbox-gl.js"></script>
<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v1.7.0/mapbox-gl.css" rel="stylesheet" />
<link rel="stylesheet" href="main_css.css">
</head>
<body>
<div id="map"></div>
<script type="text/javascript" src='main_js.js'></script>
</body>
也在这里: https://codepen.io/pete-rodrigue/pen/XWbJOpK
我已经注释掉了不起作用的部分并留下了注释。
基本上,我正在尝试这样做:
'line-color': ['to-string', ['get', 'daytime']]
在 map.addLayer()
的 paint
部分,其中 daytime
属性 是表示 'blue' 或 'red' 的字符串数组,随着动画的进行,我将新元素推入其中——这是代码的这一部分:
if (daynight[i] == 0) {
data.properties.daytime.push(['blue']); // if it's daytime, append blue
} else {
data.properties.daytime.push(['red']); // if it's nighttime, append red
}
我敢肯定这行不通的原因很明显。但我是新手,无法理解它。
任何基础知识的帮助和解释将不胜感激。
当您指定:
'line-color': ['to-string', ['get', 'daytime']]
在带有 Map#addLayer
的 'trace'
图层中,地图渲染器被告知使用 '[0, 1, 1, 0]'
(在您提供的示例数据的情况下)作为线条的颜色在 ID 为 'trace'
的 source
中。它不会等待您设置计时器,即使它设置了,您也可能 运行 遇到一些 JavaScript 的异步性问题。正如在 Mapbox 的 style specification, 'line-color'
expects a color
中以 HTML 样式的十六进制值、RGB、RGBA、HSL 或 HSLA 形式指出的那样,因此您可能 运行 会出错,因为字符串化数组是 none 这些形式。
相反,我建议将每个时间段分解成它自己的 LineString
,其中 'line-color'
由其在原始颜色数组中的相应值指定,并添加这些 LineString
作为单独的图层添加到地图。然后,您可以通过设置一些间隔来创建动画效果,以指定添加图层和动画的顺序,如 live update feature example.