Introduction to Baidu Map Development (5): Example of Flying Line Animation

Get into the habit of writing together! This is the 5th day of my participation in the "Nuggets Daily New Plan · April Update Challenge", click to view the details of the event .

Explain another common application - flying line animation, mainly used to show the flow of data

lbsyun.baidu.com/solutions/m…

1. Draw a single flying line

The curve here can be drawn with the help of Baidu's curve generator: lbsyun.baidu.com/solutions/m…

<body>

    <div id="map_container"></div>

    <script>

        const map = initBMap();

        const data = initData();

        setData(data, map);



        // 初始化百度地图

        function initBMap() {

            // 引入的common库所作的处理

            // mapv提供了api,根据名称获取坐标

            const cityCenter = mapv.utilCityCenter.getCenterByCityName('上海');

            const map = initMap({

                center: [cityCenter.lng, cityCenter.lat],

                zoom: 6,

                style: purpleStyle,

                tilt: 30

            })

            return map;



        }





        // 准备数据源

        function initData() {

            let data = [];

            // 生成贝塞尔曲线坐标集 - 关键要素

            // 1. 实例化贝塞尔曲线对象

            const curve = new mapvgl.BezierCurve();

            // 2. 设置起始和终点坐标

            const start = mapv.utilCityCenter.getCenterByCityName('上海');

            const end = mapv.utilCityCenter.getCenterByCityName('北京');

            curve.setOptions({

                start:[start.lng, start.lat],

                end:[end.lng, end.lat]

            });

            // 3. 生成贝塞尔曲线坐标集

            const curveData = curve.getPoints();

            data.push({

                geometry:{

                    type: 'LineString',

                    coordinates: curveData

                }

            })

            return data;

        }





        // 绘制数据源 

        function setData(data, map) {

           const view = new mapvgl.View({map});

           // 初始化飞线对象并添加到图层中

            const flyLine = new mapvgl.FlyLineLayer({

                // 更多配置项可以看文档

                color: 'red',

                textureColor: 'blue',

                textureWidth: 20,

                textureLength: 80,

                style: 'chaos',

                step: 0.5

            });

            view.addLayer(flyLine);

            flyLine.setData(data);



        }

    </script>

</body>
复制代码

// 绘制数据源 

        function setData(data, map) {

           const view = new mapvgl.View({map});

           // 初始化飞线对象并添加到图层中

            const flyLine = new mapvgl.FlyLineLayer({

                // 更多配置项可以看文档

                color: 'rgba(33,242,214,0.3)',

                textureColor: '#ff0000',

                textureWidth: 20,

                textureLength: 10,

                style: 'chaos',

                step: 0.3

            });

            view.addLayer(flyLine);

            flyLine.setData(data);



        }
复制代码

2. Add more lines

// 准备数据源

        function initData() {

            let data = [];

            const cities = [

                '北京', '天津', '上海', '重庆', '石家庄', '太原', '呼和浩特', '哈尔滨',

                '长春', '沈阳', '济南', '南京', '合肥', '杭州', '南昌', '福州', '郑州',

                '武汉', '长沙', '广州', '南宁', '西安', '银川', '兰州', '西宁', '乌鲁木齐',

                '成都', '贵阳', '昆明', '拉萨', '海口'

            ];

            let randomCount = 100;

            // 生成贝塞尔曲线坐标集 - 关键要素

            // 1. 实例化贝塞尔曲线对象

            const curve = new mapvgl.BezierCurve();

            while (randomCount--) {

                // 2. 设置起始和终点坐标

                const start = mapv.utilCityCenter.getCenterByCityName(cities[parseInt(Math.random() * cities.length)]);

                const end = mapv.utilCityCenter.getCenterByCityName(cities[parseInt(Math.random() * cities.length)]);

                curve.setOptions({

                    start: [start.lng, start.lat],

                    end: [end.lng, end.lat]

                });

                // 3. 生成贝塞尔曲线坐标集

                const curveData = curve.getPoints();

                data.push({

                    geometry: {

                        type: 'LineString',

                        coordinates: curveData

                    }

                })

            }



            return data;

        }
复制代码

3. mapv example transplant mapvgl - point convergence line graph

In fact, mapv (the predecessor of mapvgl) has many good flying line diagram cases for reference, but the official is no longer maintained, but we can still learn it, for example here: mapv.baidu.com/examples/#b…

After clicking on the source code, you can see the source code of his implementation, but it should be noted that the script path needs to be changed to an absolute path. The default example is a relative path:

image.png

The above case is the old mapv version, in fact, it is not recommended to learn, and the code will not be explained in detail.

mapv is based on canvas rendering, it will freeze when moving the viewing angle, mapvgl is implemented based on webgl, there will be no above problems

But we can transplant it into mapvgl as a whole. In fact, the content of this picture is still relatively large. It is actually composed of moving points and static lines.

Implement a static line layer

This mainly involves the transplantation of a convergence algorithm. Let's first implement a multi-point convergence line in Beijing, and then see if there is a layer that implements static lines, which can be implemented based on LineLayer: lbsyun.baidu.com/solutions/m…

<body>

    <div id="map_container"></div>

    <script>

        const map = initBMap();

        const data = initData();

        setData(data, map);



        // 初始化百度地图

        function initBMap() {

            // 引入的common库所作的处理

            // mapv提供了api,根据名称获取坐标

            const cityCenter = mapv.utilCityCenter.getCenterByCityName('北京');

            const map = initMap({

                center: [cityCenter.lng, cityCenter.lat],

                zoom: 5,

                style: purpleStyle,

                tilt: 0

            })

            return map;



        }





        // 准备数据源

        function initData() {

            let data = [];

            const cities = [

                '北京', '天津', '上海'

            ];

            let randomCount = 100;

            const targetCity = mapv.utilCityCenter.getCenterByCityName('北京');

            const curve = new mapvgl.BezierCurve();

            for (let i = 1; i < cities.length; i++) {

                const startCity = mapv.utilCityCenter.getCenterByCityName(cities[i]);

                curve.setOptions({

                    start: [startCity.lng, startCity.lat],

                    end: [targetCity.lng, targetCity.lat]

                })

                const curveData = curve.getPoints();

                data.push({

                    geometry: {

                        type: 'LineString',

                        coordinates: curveData

                    }

                });



            }





            return data;

        }





        // 绘制数据源 

        function setData(data, map) {

            const view = new mapvgl.View({ map });

            // 初始化linelayer实现静态线

            const lineLayer = new mapvgl.LineLayer({

                color: 'rgba(55,50,250,0.3)'

            });

            view.addLayer(lineLayer);

            lineLayer.setData(data);



        }







    </script>

</body>
复制代码

Implement moving point layer

It should be noted here that the trajectory of the moving point layer is actually the same as the static line, that is to say, the data behind it is the same. The layer is not found on the official website, but in the demo demo we found a trajectory map, which contains many moving points: mapv .baidu.com/gl/examples…

His backside is actually based on LinePointLayer, but the official documentation does not have this Layer information, we can only refer to the demo method to achieve:

// 绘制数据源 

        function setData(data, map) {

            const view = new mapvgl.View({ map });

            // 初始化linelayer实现静态线

            const lineLayer = new mapvgl.LineLayer({

                color: 'rgba(55,50,250,0.3)'

            });

            const linePointLayer = new mapvgl.LinePointLayer({

                size: 8, // 点大小

                speed: 12, // 点运动速度

                color: 'rgba(255, 255, 0, 0.6)',

                animationType: mapvgl.LinePointLayer.ANIMATION_TYPE_SMOOTH, // 点动画类型

                shapeType: mapvgl.LinePointLayer.SHAPE_TYPE_CIRCLE, //点形状

                blend: 'lighter' // 交会时处理

            });

            view.addLayer(lineLayer);

            view.addLayer(linePointLayer)

            lineLayer.setData(data);

            linePointLayer.setData(data);



        }
复制代码

achieve more points

Here, some random point aggregation targets are still generated based on random numbers:

// 准备数据源

        function initData() {

            let data = [];

            const cities = [

                '北京', '天津', '上海', '重庆', '石家庄', '太原', '呼和浩特', '哈尔滨',

                '长春', '沈阳', '济南', '南京', '合肥', '杭州', '南昌', '福州', '郑州',

                '武汉', '长沙', '广州', '南宁', '西安', '银川', '兰州', '西宁', '乌鲁木齐',

                '成都', '贵阳', '昆明', '拉萨', '海口'

            ];

            let randomCount = 500;

            const targetCity = mapv.utilCityCenter.getCenterByCityName('北京');

            const curve = new mapvgl.BezierCurve();

            for (let i = 0; i < randomCount; i++) {

                const startCity = mapv.utilCityCenter.getCenterByCityName(cities[parseInt(Math.random() * cities.length)]);

                curve.setOptions({

                    start: [startCity.lng - 5 + 10 * Math.random(), startCity.lat - 5 + 10 * Math.random()],

                    end: [targetCity.lng, targetCity.lat]

                })

                const curveData = curve.getPoints();

                data.push({

                    geometry: {

                        type: 'LineString',

                        coordinates: curveData

                    }

                });



            }





            return data;

        }
复制代码

Edge Binding Algorithm Implementation

This algorithm can help reduce the clutter of the graph and serve as an edge aggregation function. For example, a certain position line is very close, and it can help you converge to reach the goal blog.csdn.net/gdp12315_gu… :

We have not implemented edge binding at present, and the effect is not as good as the above example. Let's take a look at the tool method of mapv for edge binding.

        // 准备数据源

        function initData() {

            let data = [];

            const cities = [

                '北京', '天津', '上海', '重庆', '石家庄', '太原', '呼和浩特', '哈尔滨',

                '长春', '沈阳', '济南', '南京', '合肥', '杭州', '南昌', '福州', '郑州',

                '武汉', '长沙', '广州', '南宁', '西安', '银川', '兰州', '西宁', '乌鲁木齐',

                '成都', '贵阳', '昆明', '拉萨', '海口'

            ];

            const targetCity = mapv.utilCityCenter.getCenterByCityName('北京');

            let nodeData = [{

                x: targetCity.lng,

                y: targetCity.lat

            }]; // 点

            let edgeData = [{

                source: 0, // 0表示的是nodeData的第0号元素

                target: 0 // 0 - 0号元素的线

            }]; // 边,表示点点关系

            // 我们需要生成一系列node和edge数据





            let randomCount = 500;

            const curve = new mapvgl.BezierCurve();

            for (let i = 0; i < randomCount; i++) {

                const startCity = mapv.utilCityCenter.getCenterByCityName(cities[parseInt(Math.random() * cities.length)]);

                nodeData.push({

                    x: startCity.lng + 5 - Math.random() * 10,

                    y: startCity.lat + 5 - Math.random() * 10

                });

                edgeData.push({

                    source: i + 1, // source为上面新push的node

                    target: 0

                })

            }

            // 基于百度边绑定API获取需要的数据

            const bundling = mapv.utilForceEdgeBundling().nodes(nodeData).edges(edgeData);

            const results = bundling(); // 获取所有线沿途的点数据 - 一个二维数组

            for (let i = 0; i < results.length; i++) {

                const line = results[i];

                const coordinates = [];

                for (let j = 0; j < line.length; j++) {

                    coordinates.push([line[j].x, line[j].y])



                }

                data.push({

                    geometry: {

                        type: 'LineString',

                        coordinates

                    }

                });



            }

            return data;

        }





        // 绘制数据源 

        function setData(data, map) {

            const view = new mapvgl.View({ map });

            // 初始化linelayer实现静态线

            const lineLayer = new mapvgl.LineLayer({

                color: 'rgba(55,50,250,0.5)'

            });

            const linePointLayer = new mapvgl.LinePointLayer({

                size: 5, // 点大小

                speed: 12, // 点运动速度

                color: 'rgba(255, 255, 0, 0.6)',

                animationType: mapvgl.LinePointLayer.ANIMATION_TYPE_SMOOTH, // 点动画类型

                shapeType: mapvgl.LinePointLayer.SHAPE_TYPE_CIRCLE, //点形状

                blend: 'lighter' // 交会时处理

            });

            view.addLayer(lineLayer);

            view.addLayer(linePointLayer)

            lineLayer.setData(data);

            linePointLayer.setData(data);



        }
复制代码

plus the convergence effect

// 初始化linelayer实现静态线

            const lineLayer = new mapvgl.LineLayer({

                color: 'rgba(55,50,250,0.5)',

                blend: 'lighter' 

            });
复制代码

The practical application of the edge binding algorithm is often used.

Guess you like

Origin juejin.im/post/7084820895709003807