Introdução ao Desenvolvimento de Mapas Baidu (5): Exemplo de Animação de Linha Voadora

Adquira o hábito de escrever juntos! Este é o 5º dia da minha participação no "Nuggets Daily New Plan · April Update Challenge", clique para ver os detalhes do evento .

Explique outra aplicação comum - animação de linha voadora, usada principalmente para mostrar o fluxo de dados

lbsyun.baidu.com/solutions/m…

1. Desenhe uma única linha voadora

A curva aqui pode ser desenhada com a ajuda do gerador de curvas do Baidu: 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. Adicione mais linhas

// 准备数据源

        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. exemplo mapv transplante mapvgl - gráfico de linha de convergência de pontos

Na verdade, mapv (o antecessor do mapvgl) tem muitos bons casos de diagramas de linhas voadoras para referência, mas o oficial não é mais mantido, mas ainda podemos aprendê-lo, por exemplo aqui: mapv.baidu.com/examples/#b…

Após clicar no código-fonte, você pode ver o código-fonte de sua implementação, mas deve-se notar que o caminho do script precisa ser alterado para um caminho absoluto. O exemplo padrão é um caminho relativo:

imagem.png

O caso acima é a versão antiga do mapv, na verdade, não é recomendado aprender, e o código não será explicado em detalhes.

mapv é baseado em renderização de tela, ele congelará ao mover o ângulo de visão, mapvgl é implementado com base em webgl, não haverá problemas acima

Mas podemos transplantá-lo para o mapvgl como um todo. Na verdade, o conteúdo desta imagem ainda é relativamente grande. Na verdade, é composto de pontos móveis e linhas estáticas.

Implementar uma camada de linha estática

Isso envolve principalmente o transplante de um algoritmo de convergência. Primeiro, implementamos uma linha de convergência multiponto em Pequim e, em seguida, verificamos se existe uma camada que implementa uma linha estática. Aqui ela pode ser implementada com base em LineLayer: lbsyun.baidu.com /soluções/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>
复制代码

Implementar camada de ponto móvel

Deve-se notar aqui que a trajetória da camada de ponto móvel é na verdade a mesma da linha estática, ou seja, os dados por trás dela são os mesmos. A camada não é encontrada no site oficial, mas na demo demo encontramos um mapa de trajetória, que contém muitos pontos em movimento: mapv .baidu.com/gl/examples…

Sua parte traseira é realmente baseada em LinePointLayer, mas a documentação oficial não possui essas informações de camada, podemos apenas nos referir ao método de demonstração para conseguir:

// 绘制数据源 

        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);



        }
复制代码

conseguir mais pontos

Aqui, alguns destinos de agregação de pontos aleatórios ainda são gerados com base em números aleatórios:

// 准备数据源

        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;

        }
复制代码

Implementação do algoritmo de vinculação de borda

Esse algoritmo pode ajudar a reduzir a confusão do gráfico e servir como uma função de agregação de bordas. Por exemplo, uma determinada linha de posição está muito próxima e pode ajudá-lo a convergir para atingir a meta blog.csdn.net/gdp12315_gu… :

Nós não implementamos a vinculação de borda no momento, e o efeito não é tão bom quanto o exemplo acima. Vamos dar uma olhada no método da ferramenta mapv para vinculação de borda.

        // 准备数据源

        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);



        }
复制代码

mais o efeito de convergência

// 初始化linelayer实现静态线

            const lineLayer = new mapvgl.LineLayer({

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

                blend: 'lighter' 

            });
复制代码

A aplicação prática do algoritmo de ligação de borda é frequentemente usada.

Acho que você gosta

Origin juejin.im/post/7084820895709003807
Recomendado
Clasificación