unipp实现map地图轨迹,轨迹长度,标点,连线功能

效果图

 一、pages.json文件中加入

{
            "path" : "pages/map/mapd",
            "style" : 
            {
                "navigationBarTitleText" : "地图",
                "app-plus": {
                    "subNVues":[
                        {  
                            "id": "mapsubd1", // 唯一标识  
                            "path": "pages/map/subnvued/mapsubd1", // 页面路径  
                            /*"type": "popup",  这里不需要*/  
                            "style": {  
                                "position": "fixed",
                                "top": "100px",
                                "right": "20px",
                                "width": "52px",
                                "height": "120px",
                                "z-index": 10000,
                                "mask": "rgba(0,0,0,0)",// 遮罩层透明
                                "background": "transparent",
                                "style": {
                                    "popGesture": "none" // 组织侧滑返回, none,close
                                }
                            }  
                        },
                        {
                            "id": "mapsubd2", // 唯一标识  
                            "path": "pages/map/subnvued/mapsubd2", // 页面路径  
                            /*"type": "popup",  这里不需要*/  
                            "style": {  
                                "position": "fixed",
                                "bottom": "30px",
                                "right": "20px",
                                "width": "38px",
                                "height": "70px",
                                "z-index": 9998,
                                "mask": "rgba(0,0,0,0)",// 遮罩层透明
                                "background": "transparent",
                                "style": {
                                    "popGesture": "none" // 组织侧滑返回, none,close
                                }
                            }  
                        }
                    ]  
                }
            }
        },
pages.json

二、创建子窗体文件mapsubd1.nuve文件

<template>
    <div class="wrapper">
        <div class="rightbox">
            <div class="boxitem btd" @click.stop="changeTab(3)" v-if="tabIndex3Show">
                <image class="itemimg" :src="tabIndex3 ? map3 : map3" mode=""></image>
                <text class="itemname" :class="tabIndex3 ? '' : ''">线始点</text>
                
            </div>
            <div class="boxitem" @click.stop="changeTab(6)">
                <image class="itemimg" :src="tabIndex6 ? map6: map66" mode=""></image>
                <text class="itemname" :class="tabIndex6 ? '' : ''">显示点</text>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                map3: '/static/map/map3.png',
                map6: '/static/map/map6.png',
                map66: '/static/map/map66.png',
                tabIndex3Show: true, //线始点-是否展示
                tabIndex6Show: true,//显示点
                tabIndex3: true,
                tabIndex6: true,
            }
        },
        methods: {
            //子窗口切换
            changeTab(index) {
                var _this = this;
                //触发监听时间-传参ID
                var post_obj={};
                post_obj.tool_id=index;
                if(index==3){
                    post_obj.tabIndex3=_this.tabIndex3;    
                }else if(index==6){
                    _this.tabIndex6=!_this.tabIndex6;
                    post_obj.tabIndex6=_this.tabIndex6;
                }
                uni.$emit('mapdtool', post_obj);
            },
        }
    }
</script>

<style>
    .btd{
        border-bottom: 1rpx dashed #ccc;width: 100%;
    }
    .wrapper {
        align-items: center;
        flex-direction: column;
        justify-content: center;
        /* padding: 10rpx 15rpx; */
        background-color: #fff;
        /*     width: 52px; */
        /* box-shadow: 10rpx 14rpx 18rpx 10rpx rgba(0, 0, 0, 0.7); */
        box-shadow: 0rpx 4rpx 8rpx 0rpx rgba(200, 200, 200, 0.5);
        border-radius: 14rpx;
    }
    .rightbox {
        align-items: center;
        justify-content: center;
        /* padding: 0 12rpx; */
        background: #FFFFFF;
    /*     box-shadow: 0rpx 4rpx 8rpx 0rpx rgba(200, 200, 200, 0.5);
        border-radius: 14rpx; */
    
    }
    .boxitem {
        display: flex;
        flex-direction: column;
        text-align: center;
        align-items: center;
        justify-content: center;
        padding-bottom: 4rpx;
        padding-left: 16rpx;
        padding-right: 16rpx;
    }

    .itemimg {
        width: 40rpx;
        height: 40rpx;
        margin: 10rpx  4rpx;
    }

    .itemname {
        font-size: 22rpx;
        font-weight: 400;
        color: #333333;
        line-height: 42rpx;
    }

    .active {
        color: #2765F1;
    }


    .closeicon {
        width: 40rpx;
        height: 40rpx;
        position: absolute;
        right: 16rpx;
        top: 12rpx;
    }

</style>
mapsubd1.nvue

三、创建子窗体文件mapsubd2.nuve文件

<template>
    <div class="wrapper">
        <div class="rightbox">
            <div class="boxitem btd" @click.stop="changeTab(7)">
                <image class="itemimg" :src="map7" mode=""></image>
            </div>
            <div class="boxitem" @click.stop="changeTab(8)">
                <image class="itemimg" :src="map8" mode=""></image>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                map7: '/static/map/map7.png',
                map8: '/static/map/map8.png',
            }
        },
        methods: {
            //子窗口切换
            changeTab(index) {
                var _this = this;
                //触发监听时间-传参ID
                //uni.$emit('mapdtool', {'tool_id': index});
                var post_obj={};
                post_obj.tool_id=index;
                uni.$emit('mapdtool', post_obj);
                
            },
        }
    }
</script>

<style>
    .btd{
        border-bottom: 1rpx dashed #ccc;width: 100%;
    }
    .wrapper {
        align-items: center;
        flex-direction: column;
        justify-content: center;
        /* padding: 10rpx 15rpx; */
        background-color: #fff;
        box-shadow: 0rpx 4rpx 8rpx 0rpx rgba(200, 200, 200, 0.5);
        border-radius: 14rpx;
    }
    .rightbox {
        align-items: center;
        justify-content: center;
        /* padding: 0 12rpx; */
        background: #FFFFFF;
    /*     box-shadow: 0rpx 4rpx 8rpx 0rpx rgba(200, 200, 200, 0.5);
        border-radius: 14rpx; */
    
    }
    

    .boxitem {
        display: flex;
        flex-direction: column;
        text-align: center;
        align-items: center;
        justify-content: center;
        padding-bottom: 4rpx;
        padding-left: 16rpx;
        padding-right: 16rpx;
    }

    .itemimg {
        width: 40rpx;
        height: 40rpx;
        margin: 10rpx  4rpx;
    }

    .itemname {
        font-size: 22rpx;
        font-weight: 400;
        color: #333333;
        line-height: 42rpx;
    }

    .active {
        color: #2765F1;
    }


    .closeicon {
        width: 40rpx;
        height: 40rpx;
        position: absolute;
        right: 16rpx;
        top: 12rpx;
    }

</style>
mapsubd2.nvue

四、创建主窗体文件mapd.nuve文件,注意一定要是nvue文件

<template>
    <view>
        <map style="width: 750rpx;" :style="'height:'+windowHeight*2+'rpx;'" id="mapd" 
            :latitude="data_info.latitude"
            :longitude="data_info.longitude" 
            :scale="data_info.scale"
            :markers="covers" 
            :polyline='polyline'
            >
        </map>
        <cover-view class="disbox">
            <text style="color: blue;font-size: 28rpx;">总长度:{{data_info.dis}}</text>  
        </cover-view>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                windowHeight : uni.getSystemInfoSync().windowHeight+22,//屏幕高度
                tid:0,//任务ID
                data_info:{
                    'latitude':'',
                    'longitude':'',
                    'scale':18,//缩放级别(类型为Number,默认值为16,缩放级别取值范围为5-18)
                    'dis':0,//轨迹长度
                },
                data_detail:[],//根据ID获取的详情信息
                covers: [],// 标记点
                
                //指定一系列坐标点,从数组第一项连线至最后一项
                polyline:[],
            }
        },
        onLoad(options) {
            var _this= this;
            
            if(options.tid){
                _this.tid=options.tid;
                //获取详情
                _this.get_details();
            }else{
                uni.showToast({
                    title:'参数错误',
                    icon:'none'
                })
                //uni.navigateBack();
                return false;
            }
            
            const mapsubd1= uni.getSubNVueById('mapsubd1'); // 通过 id 获取 nvue 子窗体 
            const mapsubd2= uni.getSubNVueById('mapsubd2'); // 通过 id 获取 nvue 子窗体 
            mapsubd1.show('slide-in-left', 250); // 打开 nvue 子窗体
            mapsubd2.show('slide-in-left', 250); // 打开 nvue 子窗体
            
            //监听子窗口操作
            uni.$on('mapdtool',(res)=>{  
                //console.log(res);
                var tool_id=res.tool_id;
                if (tool_id == 3) {
                    //线始点
                    //第一个点跳转中心点start
                    var lat =_this.data_detail.firstdata.latitude;
                    var lon =_this.data_detail.firstdata.longitude;
                    _this.mapToLocation(lat,lon);
                    //第一个点跳转中心点end
                }else if(tool_id == 6){
                    //显示点与不显示点
                    if(res.tabIndex6){
                        //标点数据start
                        _this.covers=_this.data_detail.markers;
                        //标点数据end
                    }else{
                        _this.covers=[];
                    }
                }else if(tool_id == 7 || tool_id == 8){
                    //缩放级别
                    _this.getzoom(tool_id);
                }else {
                }
            })  
            
        },
        onUnload() {  
            // 移除子窗口监听事件 
            //因为事件监听是全局的,所以使用 uni.$on ,需要使用 uni.$off 移除全局的事件监听,避免重复监听。
            uni.$off('mapdtool');  
        },
        methods: {
            //任务详情
            get_details(){
                var _this=this;
                let post_obj={};
                post_obj.tid=_this.tid;
                uni.$u.api.task_detail(post_obj).then(res => {
                    console.log(res);
                    if (res.code == 1) {
                        var data_detail=res.data;
                        _this.data_detail=data_detail;
                        //第一个点跳转中心点start
                        var lat =data_detail.firstdata.latitude;
                        var lon =data_detail.firstdata.longitude;
                        _this.mapToLocation(lat,lon);
                        //第一个点跳转中心点end
                        
                        //标点数据start
                        _this.covers=data_detail.markers;
                        //标点数据end
                        
                        //标线数据start
                        _this.polyline=data_detail.polyline;
                        //标线数据end
                        
                        //轨迹长度start
                        _this.data_info.dis=data_detail.dis;
                        //轨迹长度end
                    }
                })
            },
            //重置中心位置
            mapToLocation(lat,lon){
                this.data_info.latitude=lat;
                this.data_info.longitude=lon;
                let mapObjs = uni.createMapContext('mapd', this)
                mapObjs.moveToLocation({
                    latitude: lat,
                    longitude: lon
                }, {
                    complete: res => {}
                })
            },
            //缩放级别
            getzoom(tool_id) {
                let _this=this;
                let scale=_this.data_info.scale;
                if(tool_id==7 && scale<=18){
                    //缩放+
                    _this.data_info.scale=scale+1;
                }else if(tool_id==8 && scale>=5){
                    //缩放-
                    _this.data_info.scale=scale-1;
                }
            },
        }
    }
</script>

<style>
    
    .disbox {
        width: 750rpx;
        display: flex;
        justify-content: center;
        align-items: center;
        padding: 24rpx 0rpx;
        position: fixed;
        bottom: 18rpx;
    }
</style>
mapd.nvue

 附php后端部分代码

五、后端数据渲染接口

public function task_detail(){
        $post=request()->only(['user_id'=>0,'tid'=>0]);
        if($post['tid']==0){
            return returnData(0,'操作失败');
        }
        $data=[];//返回的参数
        $where=[];
        $info = TaskM::where('tid',$post['tid'])->where($where)->find();
        $info['dm3data']=Dm3dataM::where('dm3Task_tid',$info['tid'])->select();
        
        //第一个点坐标,用于确定中心位置start
        $firstdata=[];
        $firstdata['latitude']='';
        $firstdata['longitude']='';
        if($info['dm3data']){
            $firstdata['latitude']=$info['dm3data'][0]['latitude'];
            $firstdata['longitude']=$info['dm3data'][0]['longitude'];
        }
        $info['firstdata']=$firstdata;
        //第一个点坐标,用于确定中心位置end
        
        //标点数据start
        $markers=[];
        $polyline=[];
        $points=[];
        $polylinearr=[];
        $dis=0;//轨迹长度
        if($info['dm3data']){
            //$d_l=count($info['dm3data']);
            foreach ($info['dm3data'] as $k=>$v){
                if($k>=1){
                    // 起点坐标
                    $longitude1 =$info['dm3data'][$k-1]['longitude'];
                    $latitude1 = $info['dm3data'][$k-1]['latitude'];
                    // 终点坐标
                    $longitude2 = $info['dm3data'][$k]['longitude'];
                    $latitude2 = $info['dm3data'][$k]['latitude'];
                    $distance = getDistance($longitude1, $latitude1, $longitude2, $latitude2);
                    $dis+=$distance;
                }
                $arr=[];
                $arr['id']=$k+1;
                $arr['width']=22;
                $arr['height']=30;
                $arr['rotate']=0;
                $arr['latitude']=$v['latitude'];
                $arr['longitude']=$v['longitude'];
                $arr['iconPath']='/static/map/mark1.png';
                
                
                //markers图标上数字start
                $label['content']=$k+1;
                $label['color']='#333333';
                $label['display']='ALWAYS';
                $label['y']=-26;
                $label['x']=-3;
                $label['bgColor']='transparent';
                $arr['label']=$label;
                //markers图标上数字end
                
                array_push($markers,$arr);
                
                
                $arr1=[];
                $arr1['latitude']=$v['latitude'];
                $arr1['longitude']=$v['longitude'];
                array_push($points,$arr1);
            }
            $polyline['points']=$points;
            $polyline['color']='#31c27c';
            $polyline['width']=20;
            $polyline['arrowLine']=true;
            $polyline['borderWidth']=2;
            //$polyline['arrowIconPath']='/static/map/mapline.png';
            
        }
        $info['dis']=$dis.'m';//轨迹长度
        $info['markers']=$markers;
        $info['polyline']=[];
        array_push($polylinearr,$polyline);
        $info['polyline']=$polylinearr;
        //标点数据end
        
        $data=$info;
        return returnData(1,'成功',$data);
    }
数据渲染方法

六、计算两点距离方法

/**
 * 计算两点地理坐标之间的距离
 * @param  Decimal $longitude1 起点经度
 * @param  Decimal $latitude1  起点纬度
 * @param  Decimal $longitude2 终点经度 
 * @param  Decimal $latitude2  终点纬度
 * @param  Int     $unit       单位 1:米 2:公里
 * @param  Int     $decimal    精度 保留小数位数
 * @return Decimal
 */
function getDistance($longitude1, $latitude1, $longitude2, $latitude2, $unit=1, $decimal=2){
    $EARTH_RADIUS = 6370.996; // 地球半径系数
    $PI = 3.1415926;
    $radLat1 = $latitude1 * $PI / 180.0;
    $radLat2 = $latitude2 * $PI / 180.0;
    $radLng1 = $longitude1 * $PI / 180.0;
    $radLng2 = $longitude2 * $PI /180.0;
    $a = $radLat1 - $radLat2;
    $b = $radLng1 - $radLng2;
    $distance = 2 * asin(sqrt(pow(sin($a/2),2) + cos($radLat1) * cos($radLat2) * pow(sin($b/2),2)));
    $distance = $distance * $EARTH_RADIUS * 1000;
    if($unit==2){
        $distance = $distance / 1000;
    }
    return round($distance, $decimal);
}
计算两点距离的方法

 

posted @ 2024-02-27 11:15  zhang_you_wu  阅读(94)  评论(0编辑  收藏  举报