头图

Tencent location service development application-tutorial, case sharing, knowledge summary

腾讯位置服务
中文

Preface

As a programmer with a working position of [Front-end Development Engineer], the applications I develop often need to obtain user location information, and need to use the display map and certain locations of the map dealer in some occasions, and need to obtain the administrative division list ( Provinces and cities) and address details, you need to plan a (dynamic) route on the map, track playback, car movement, and create an information window for the display of summary information of the location.

What the company does is a shared project. The scenario is like this, a common shared power bank (the function is almost the same as that of a popular shared bicycle). When doing the homepage of the mini program, what you need to do is scan the code to charge and contact customer service (question Feedback), get the geographic location, the beginning is a geographic location, you can get the store information in the area near you, click on the logo of the store to get the store's geographic location, business hours, store name, distance, whether it is the current store Whether there is information such as a power bank that can be borrowed.

Shared charging electric car🚗, the home page is also a geographic location map, you can get the nearest shared electric car near you, get the address, status and other information of the car. Display the remaining power of the car, use records, lease orders, get the itinerary trajectory, the mileage in a certain period of time, and dynamically display the trajectory.

There are actually a lot of sharing content involved (for example, in addition to electric cars, power banks, equipment can be rented, etc.), but most of them have almost the same functions. Deposits, rental fees, and credit-free deposits are required. I have developed apps, H5, web sites, and small program projects that are closely related to map-related location services. Let me talk about the stories related to location services.

The following is mainly about the map function and other functions, and the Tencent location development service is also used. Will explain step by step, do some case demonstrations, code explanations, and use tutorials. (Note that I will go back to the development tutorial here, try to explain the usage of each function familiarly)
1. What is Tencent's location service?
Tencent location service is undoubtedly to obtain information content such as location service. Highlights of this product:

  1. Positioning: Provide perfect location solutions for partners and developers, and provide professional and accurate positioning services for social, travel, games, commerce, O2O, logistics and other fields
  2. Map: Tencent's location service provides developers with rich map display forms on multiple platforms, helping developers who belong to different fields to easily complete the work of building maps and creating exclusive content based on them. At the same time, it cooperates with massive data, personalized customization, visualization and other capabilities to meet the needs for maps in various industry scenarios
  3. Location search: Based on massive POI data, it provides various search capabilities such as surrounding search, city-wide search, keyword input prompts, classification filtering, etc., and creates exclusive search strategies for social, logistics, travel and other industries, and the experience is better All in one
  4. Route planning: According to the starting point, destination and route strategy settings, combined with accurate real-time traffic conditions, it provides driving, walking, cycling, and public transportation route planning capabilities, helping developers to provide users with a caring and user-friendly travel experience
  5. WeChat Mini Program Solution: Tencent Location Services fully embraces the mini program ecosystem, serving mini program developers who need different scenarios from multiple levels such as service APIs, basic map components, plug-ins, and industry solutions, helping mini programs plug in the "wings of the map" "!
  6. Personalized map: Personalized style: Thousands of lines and thousands of faces, helping developers to select or create a map style matching the style according to their product usage scenarios and interface colors, and the experience is even better; Personalized layers: real, cool, and helpful Developers generate map tiles from exquisite drawings and place them on the map, making the display effect of tourist attractions, universities and colleges unique

Second, use steps

1. Uniapp development map description

Uniapp is used because it is a framework that uses vue.js to develop all front-end applications. Developers write a set of codes that can be published to ios, android, web and various small programs, fast apps and other platforms.
Use the map map component to develop. The map component is used to display the map (Tencent map when used). Let’s talk about its properties:

longitude (the type is Number, there is no default value, which means the longitude of the center)
latitude (the type is Number, there is no default value, which means the center latitude)
scale (The type is Number, the default value is 16, the zoom level range is 5-18)
markers (The type is an Array, which means there can be multiple on the map, and there is no default value, which means markers)
polyline (type is Array array, there is no default value, indicating route, all points on the array are connected into a line)
circles (Array of type Array, representing circles)
controls (Array of type Array, representing controls)
include-points (Array of type Array, indicating that the zoomed field of view has included all the given coordinate points)
enable-3D (the type is Boolean, the default value is false, which means whether to display 3D blocks)
show-compass (The type is Boolean, the default value is false, which means whether to show the compass)
enable-overlooking (the type is Boolean, the default value is false, which means whether to turn on the overlook)
enable-satellite (the type is Boolean, the default value is false, which means whether to open the satellite image)
enable-traffic (the type is Boolean, the default value is false, indicating whether to enable real-time traffic)
show-location (the type is Boolean, which means that the current location with direction is displayed)
polygons (type Array, represented as polygons)

Click on properties

  1. @markertap- means it is triggered when the marker is clicked, e.detail={markerId}
  2. @labeltap- means it is triggered when the label is clicked, e.detail = {markerId}
  3. @callouttap- means it is triggered when the bubble corresponding to the marker point is clicked, e.detail = {markerId}
  4. @controltap- means it is triggered when the control is clicked, e.detail = {controlId}
  5. @regionchange- indicates that the field of view changes
  6. @tap- means it is triggered when the map is clicked; App-nuve, WeChat applet 2.9 support returning longitude and latitude
  7. @updated- means it is triggered when the map rendering update is complete
When we write the map component, it is recommended to write the width/height of the component directly, for example, 750rpx, do not set the percentage value, only gcj02 coordinates are supported in uni-app.

introduces the markers attribute-the type is Array

As can be seen from the previous description, the marker attribute type is Array, which means that the marker point is used to display the position of the marker on the map. This array property has its object configuration properties in it, which are:

  1. id indicates the id of the marker point. The type is Number. It is required. The marker click event callback will return this id. It is recommended to set the Number type id for each marker to ensure better performance when updating the marker.
  2. latitude, latitude, type Number, required field, floating point number, range -90 ~ 90
  3. longitude, longitude, type Number, required item, floating point number, range -180 ~ 180
  4. title, mark the name, type String, is not required, it will be displayed when clicked, and will be ignored when the callout exists
  5. iconPath, displayed icon, type String, required item, image path in the project directory
  6. rotate, rotation angle, type Number, not required, clockwise rotation angle, range 0 ~ 360, default is 0
  7. alpha, the transparency of the label, the type Number, is not required, the default is 1, no transparency, the range is 0 ~ 1
  8. width, the width of the label icon, type Number, is not required, the default is the actual width of the picture
  9. height, the height of the label icon, type Number, is not required, the default is the actual height of the picture
  10. callout, the bubble window above the custom marker point, type Object, not required-line breaks can be recognized
  11. label, add a label next to the marked point, type Object, not required-line breaks can be recognized
  12. Anchor, the latitude and longitude are at the anchor point of the label icon. The default bottom side midpoint is not required. {x, y}, x means horizontal (0-1), y means vertical (0-1). {x: .5, y: 1} represents the midpoint of the bottom edge

Bubble callout on the marker (Object type)
Use attributes of the attribute callout object on the marker array:

  1. content, text, String
  2. color, text color, String
  3. fontSize, text size, Number
  4. borderRadius, callout border rounded corners, Number
  5. bgColor, background color, String
  6. padding, left blank at the edge of the text, Number
  7. display,'BYCLICK': click to display;'ALWAYS': often display, String
  8. textAlign, text alignment. Valid values: left, right, center, String

The label on the marker label (Object type)

  1. content, text, String
  2. color, text color, String
  3. fontSize, text size, Number
  4. x, the coordinates of the label, the origin is the latitude and longitude corresponding to the marker, Number
  5. y, the coordinates of the label, the origin is the latitude and longitude corresponding to the marker, Number
  6. borderWidth, border width, Number
  7. borderColor, border color, String
  8. borderRadius, rounded corners of the border, Number
  9. bgColor, background color, String
  10. padding, left blank at the edge of the text, Number
  11. textAlign, text alignment. Valid values: left, right, center, String

polyline

polyline means to specify a series of coordinate points, connecting from the first item to the last item of the array

  • points, longitude and latitude array, type is Array, required, such as: [{latitude: 0, longitude: 0}]
  • color, the color of the line, the type is String, no need to fill in, such as: #0000AA
  • width, the width of the line, the type is Number, no need to fill in
  • dottedLine, whether it is a dotted line, the type is Boolean, do not need to fill in, the default value is false
  • arrowLine, the line with arrow, the type is Boolean, do not need to fill in, the default value is false
  • arrowIconPath, replace the arrow icon, the type is String, do not need to fill in, when arrowLine is true, the default line with arrow takes effect
  • borderColor, the border color of the line, the type is String, no need to fill in
  • borderWidth, the thickness of the line, the type is Number, no need to fill in

polygon
Polygon specifies a series of coordinate points, and generates a closed polygon according to the points coordinate data

  • points, latitude and longitude array, array, required, such as: [{latitude: 0, longitude: 0}]
  • strokeWidth, the width of the stroke, Number, No
  • strokeColor stroke color, String, no
  • fillColor, fill color, String, no
  • zIndex, set the value of the Z axis of the polygon, Number, No

circles
circles show circles on the map

  • latitude, latitude, Number, required, floating point number, range -90 ~ 90
  • longitude, longitude, Number, required, floating point number, range -180 ~ 180
  • color, the color of the stroke, String, no need to fill in, such as: #0000AA
  • fillColor, fill color, String, no need to fill, such as: #0000AA
  • radius, radius, Number, required
  • strokeWidth, the width of the stroke, Number, no need to fill in

controls
controls display controls on the map, the controls do not move with the map

  • id, control id, Number, do not need to fill in, this id will be returned in the callback of the control click event
  • position, the position of the control on the map, Object, required, the position of the control relative to the map
  • iconPath, displayed icon, String, required, the image path in the project directory, supports relative path writing, starting with'/' means relative project root directory; temporary path is also supported
  • clickable, whether clickable, Boolean, do not need to fill in, default is not clickable
    position
  • left, how far from the left border of the map, Number, do not need to fill in, the default is 0
  • top, how far from the upper boundary of the map, Number, do not need to fill in, the default is 0
  • width, the width of the control, Number, do not need to fill in, the default is the width of the picture
  • height, the height of the control, Number, do not need to fill in, the default is the height of the picture
Note that the latitude and longitude of the map component in uniapp are required. If not, the default value of the latitude and longitude is the latitude and longitude of Beijing.

2. Uniapp uses map component

Basic usage

Using the map component in uniapp development, the basic usage method:
The code is as follows (example):

<map :scale="scale" style="width: 100%; height: 100%;"
enable-3D="false" show-compass="false" enable-overlooking="false"
:enable-satellite="false" :enable-traffic="false" show-location="false"
:latitude="latitude" :longitude="longitude" :markers="covers">
</map>

To use the markers attribute, the code is as follows (example):

markers: [{
    id: 1, // Number
    title: '1', // String-标注点名
    rotate: 180, // Number - 顺时针旋转的角度,范围 0 ~ 360,默认为 0
    alpha: 0.5, // 默认1,无透明,范围 0 ~ 1
    latitude: 39.899,
    longitude: 116.39742,
    width: 30,
    height: 30,
    // callout: {
    //     display: "BYCLICK",
    //     padding: 10,
    //     borderRadius: 5,
    //     content: '',
    // },
    // anchor: {},
    iconPath: '../../../static/location.png', // 显示的图标
}, {
    id: 2,
    title: '2', // String
    latitude: 39.90,
    longitude: 116.39,
    callout: {
        color: '#007AFF', // 文本颜色
        bgColor: '#563BFF', // 背景色
        display: "ALWAYS", // 'BYCLICK':点击显示; 'ALWAYS':常显
        fontSize: 15,
        textAlign: 'left', // 文本对齐方式。有效值: left, right, center
        padding: 10, // 文本边缘留白
        borderRadius: 5,
        content: '腾讯地图',
    },
    label: {
        content: 'Jeskson',
        color: '#000000',
        fontSize: 12,
        borderWidth: 12,
        borderColor: '#007AFF',
        borderRadius: 5,
        padding: 5,
        textAlign: 'center',
        bgColor: '#563BFF',
    },
    iconPath: '../../../static/location.png'
}]

The preview effect is as follows:

controls:[{
    // 在地图上显示控件,控件不随着地图移动
    id: 1, // 控件id
    iconPath:'../../static/icon.png', // 显示的图标
    position:{
     // 控件在地图的位置
     left: 15,
     top: 15,
     width: 50,
     height: 50
   },    
}],

Address search

uni-app only supports gcj02 coordinates

The object parameter in uni.getLocation(OBJECT)

Get the current geographic location and speed. In the WeChat Mini Program, after the user leaves the application, this interface cannot be called unless the background continuous positioning permission is requested; when the user clicks "display at the top of the chat", this interface can continue to be called.

OBJECT parameter description

  • type, String, do not need to fill in, the default is wgs84 to return gps coordinates, gcj02 to return to China National Surveying Bureau coordinates, can be used
    The coordinates of uni.openLocation, the app platform AutoNavi SDK only supports returning gcj02
  • altitude, Boolean, don’t need to be filled in. Passing true will return altitude information. Because obtaining altitude requires high accuracy, it will slow down the interface return speed.
  • geocode, Boolean, no need to fill in, default false, whether to resolve address information
  • success, Function, required, the callback function of the interface calling successfully, please refer to the return parameter description for details of the return content
  • fail, Function, do not need to fill in, the callback function of the interface call failure
  • complete, Function, do not need to fill in, the callback function of the end of the interface call (the call will be executed if it succeeds or fails)

For success return parameter description:

  • latitude, latitude, floating point number, range -90~90, negative number means southern latitude
  • longitude, longitude, floating point number, range -180~180, negative number means west longitude
  • speed, speed, floating point number, unit m/s
  • accuracy, the accuracy of the location
  • altitude, height in m
  • verticalAccuracy, vertical accuracy, unit m (Android can’t get it, return 0)
  • horizontalAccuracy, horizontal accuracy, unit m
  • address, address information (only supported by App, geocode needs to be set to true)

address address information description

  • country, String, country such as "China", if not, return undefined
  • province, String, province name such as "Beijing", if not, return undefined
  • city, String, city name, such as "Beijing", if not, return undefined
  • district, String, district, county name such as "Chaoyang District", if not, return undefined
  • street, String, street information, such as "jiuxianqiao road", if not, return undefined
  • streetNum, String, get street number information, such as "No. 3", if not, return undefined
  • poiName, String POI information, such as "Electronic City. International Electronic Headquarters", if not, return undefined
  • postalCode, String, postal code, such as "100016", if not, return undefined
  • cityCode, String, city code, such as "010", if not, return undefined

uni.chooseLocation(OBJECT) opens the map to select a location.

  • latitude, String, do not need to fill in, the latitude of the target
  • longitude, String, do not need to fill in, the longitude of the target
  • keyword, String, do not need to fill in, search keywords, only App platform supports
  • success, Function, required
  • fail, Function, no need to fill in
  • complete, Function, don’t need to fill in

Success return parameter description:

  • name, location name
  • address, detailed address
  • Latitude, latitude, floating point number, range -90~90, negative number means south latitude, use gcj02 China National Surveying Bureau coordinate system.
  • longitude, longitude, floating point number, the range is -180~180, negative number means west longitude, using the gcj02 national survey bureau coordinate system.

The code is as follows (example):

chooseLocation(e) { //打开地图选择位置
    uni.chooseLocation({
        success: res => {
            console.log('位置名称:' + res.name);
            console.log('详细地址:' + res.address);
            console.log('纬度:' + res.latitude);
            console.log('经度:' + res.longitude);
            uni.getLocation({
                type: 'gcj02',
                altitude:true,
                geocode:true,
                success: function(res) {
                    console.log('当前位置的经度:' + res.longitude);
                    console.log('当前位置的纬度:' + res.latitude);
                }
            });
            console.log('省:' + res.address.slice(0, res.address.indexOf('省') + 1));
            console.log('市:' + res.address.slice(res.address.indexOf('省') + 1, res.address.indexOf('市') + 1));
            console.log('区:' + res.address.slice(res.address.indexOf('市') + 1, res.address.indexOf('区') + 1));
            this.query.address = res.address;
            this.query.latitude = res.latitude;
            this.query.longitude = res.longitude;
            this.query.province = res.address.slice(0, res.address.indexOf('省') + 1)
            this.query.city = res.address.slice(res.address.indexOf('省') + 1, res.address.indexOf('市') + 1)
            this.query.district = res.address.slice(res.address.indexOf('市') + 1, res.address.indexOf('区') + 1)
        }
    });
},

Preview effect:

Get nearby dynamics, point aggregation

uni.getNetworkType(OBJECT) gets the network type.

uni.createMapContext(mapId,this) creates and returns a map context mapContext object. In the custom component, the second parameter is passed into the component instance this to operate the <map> component in the component.

mapContext-mapContext is bound to a <map> component through mapId, through which the corresponding <map> component can be operated.

List of methods for this object:

  • getCenterLocation OBJECT Get the latitude and longitude of the current map center, the return is the gcj02 coordinate system, which can be used for uni.openLocation
  • moveToLocation OBJECT moves the center of the map to the current location point, which needs to be used with the show-location of the map component
  • translateMarker OBJECT translation marker with animation
  • includePoints OBJECT zoom field of view to display all latitude and longitude
  • getRegion OBJECT Get the field of view of the current map
  • getScale OBJECT Get the zoom level of the current map
  • $getAppMap Get the native map object plus.maps.Map

OBJECT parameter list of getCenterLocation

success Function do not need to fill in, the interface calls the callback function for success, res = {longitude: "longitude", latitude: "latitude"}

OBJECT parameter list of moveToLocation-no need to fill in

OBJECT parameter list of translateMarker

  • markerId Number is required to specify the marker
  • destination Object is required to specify the target point to which the marker moves
  • autoRotate Boolean It is not necessary to fill in whether the marker is automatically rotated during the movement
  • rotate Number does not need to fill in the rotation angle of the marker
  • duration Number does not need to fill in the duration of the animation, the default value is 1000ms, translation and rotation are calculated separately
  • animationEnd Function does not need to fill in the animation end callback function
  • fail Function No need to fill in the callback function of the interface call failure

The code is as follows (example):

<view id="activeMap">
    <view @tap="activeMarker={}">
        <view class="page-body map-view" style="z-index: 1;position: relative;">
            <view class="page-section page-section-gap map-view">
                <map :markers="shops" id="map1" :show-location="true" :latitude="latitude" :longitude="longitude" @regionchange="regionChange"
                 @markertap="markerTap" @tap="activeMarker={}">
                    <!-- @markertap 点击标记点时触发,e.detail = {markerId}-->
                    <!-- @tap 点击地图时触发-->
                    <!-- @regionchange 视野发生变化时触发-->
                </map>
                <cover-image class="map-image" src="../static/address.png"></cover-image>
            </view>
        </view>
    </view>
</view>
regionChange() { // 移动地图后重新获取门店
    uni.createMapContext('map1', this).getCenterLocation({
        success: res => {
            console.log(res.latitude)
            console.log(res.longitude)
            this.shopTimeout = setTimeout(_ => {
                this.shops = [{
                    address: "广东省汕头市xxx区xx大道1",
                    distance: 122,
                    end_time: "1",
                    id: 2,
                    latitude: "22.72078500009999",
                    longitude: "114.36090200009999",
                    shop: {
                        iconPath: '/static/logo.png',
                        id: 3,
                        latitude: "22.72078500009999",
                        longitude: "114.36090200009999",
                        height: 34,
                        width: 34,
                        shop: {return: 0}
                    },
                    return: 0,
                    height: 34,
                    width: 34,
                    start_time: "1",
                    store_name: "三星大酒店",
                    iconPath: '/static/shop.png',
                }]
            }, 500)
        },
        fail: res => {
            uni.showModal({
                content: '获取位置失败',
                showCancel: false
            })
        }
    })
},

The preview effect is as follows:

People nearby are marked on the map

The code is as follows (example):

list: [{
    id: 1264640,
    user_id: 335187,
    place: "Jeskson市",
    text: "dadaqianduan.cn",
    latitude: "27.267520",
    longitude: "111.727120",
    status: "normal",
    nickname: "dada",
    avatar: "https://image.aishencn.com/2020/10/20/002207441_40845724-user.jpg",
    distance: 13419,
}, {
    id: 1272720,
    user_id: 36950,
    place: "dadaqianduan市",
    text: "dadaqianduan.cn",
    latitude: "27.257640",
    longitude: "111.747910",
    deletetime: null,
    status: "normal",
    nickname: "dadaqianduan",
    avatar: "https://image.aishencn.com/2020/04/09/004135379_37869100-user.jpg",
    distance: 27070,
}, {
    id: 1316740,
    user_id: 366172,
    place: "dadaqianduan.cn",
    text: "dadaqianduan.cn",
    images: "https://image.aishencn.com/2020/11/04/215134979_98197351-bbs.jpg",
    latitude: "27.257430",
    longitude: "111.732960",
    status: "normal",
    nickname: "dada",
    avatar: "https://image.aishencn.com/2020/11/04/182622730_98197351-user.venus/cache/ext/crop/1604518314542_jpg",
    distance: 27190,
    images_arr: ["https://image.aishencn.com/2020/11/04/215134979_98197351-bbs.jpg"]
}],

The preview effect is as follows:

Locate nearby stores

The code is as follows (example):

// 两点间距离
distance(la1, lo1, la2, lo2) {
    var La1 = (la1 * Math.PI) / 180.0
    var La2 = (la2 * Math.PI) / 180.0
    var La3 = La1 - La2
    var Lb3 = (lo1 * Math.PI) / 180.0 - (lo2 * Math.PI) / 180.0
    var s =
        2 *
        Math.asin(
            Math.sqrt(
                Math.pow(Math.sin(La3 / 2), 2) +
                Math.cos(La1) * Math.cos(La2) * Math.pow(Math.sin(Lb3 / 2), 2)
            )
        )
    s = s * 6378.137 //地球半径
    s = Math.round(s * 10000) / 10000
    return s
},
// 计算最近的距离
nearDistance(array, centerLatitude, centerLongitude) {
    let temp = []
    for (let i = 0, l = array.length; i < l; i++) {
        const element = array[i]
        let d = this.distance(
            element.latitude,
            element.longitude,
            centerLatitude,
            centerLongitude
        )
        temp.push(d)
    }
    this.distanceL = Math.min.apply(null, temp)
}

The effect is as follows:

Sliding track

The code is as follows (example):

<map :polyline="polyline" :scale="scale" id="maps" :markers="markers" :latitude="center.latitude"
:longitude="center.longitude">
</map>
// 播放标记点
playMarkars() {
    if (this.polyline.length == 0) {
        uni.showModal({
            content: '当前时间范围内没有轨迹,无法播放!',
        })
        this.isPlay = false // 无
        this.playIndex = 0 // 第一个
        return
    }
    this.playIndex = Math.min(this.points.length - 1, this.playIndex)
    this.markers = [this.formatMarker(this.points[this.playIndex++], 'ALWAYS')]
    this.timer = setInterval(_ => {
        var i = this.playIndex++
        this.nextAdaress(i);
        if (i >= this.points.length) {
            clearInterval(this.timer)
            this.isPlay = false
            this.playIndex = 0
            this.initMarkers()
            return
        }
        this.markers = [this.formatMarker(this.points[i], 'ALWAYS')]
    }, 1000)
},

formatMarker(point, display = "BYCLICK") {
    let content = [
        "时间:" + parseTime(point.create_time),
        "运动状态:" + (point.sport == 1 ? '运动' : '静止'),
        "地址:" + point.address || ''
    ]
    return {
        id: point.id,
        iconPath: '/static/dada.png',
        width: 35,
        height: 35,
        latitude: point.latitude,
        longitude: point.longitude,
        callout: {
            display: display,
            padding: 10,
            borderRadius: 5,
            content: content.join("\n")
        }
    }
},
nextAdaress(index) {
    const len = 10;
    if (this.isGetAddress) {
        return
    }
    for (let i = 0; i < len; i++) {
        if (!this.points[i + index]) {
            break
        }
        if (this.points[i + index].address === undefined) {
            this.isGetAddress = true
            this.getAddress(i + index, len * 2, _ => {
                this.isGetAddress = false
            });
            break
        }
    }
},

The picture effect is as follows:

Vue access to Tencent map interface

Tencent (recommended)

https://apis.map.qq.com/ws/location/v1/ip={$ip}&key={$key}

Need to apply for a key, fast, with basic information

Click on the homepage to register and apply for a key:

Key management, create a new key, fill in the corresponding information
1. Create a map preview effect as follows:

<script charset="utf-8" src="https://map.qq.com/api/gljs?v=1.exp&key=申请的key"></script>

 <script type="text/javascript">
    function initMap() {
        var center = new TMap.LatLng(39.984104, 116.307503);
        //初始化地图
        var map = new TMap.Map("container", {
            rotation: 20,//设置地图旋转角度
            pitch:30, //设置俯仰角度(0~45)
            zoom:12,//设置地图缩放级别
            center: center//设置地图中心点坐标
        });
    }
</script>

2. The effect map after the map has been loaded:

<script>
    function initMap() {
        //初始化地图
        var map = new TMap.Map("container", {
            center: new TMap.LatLng(39.984104, 116.307503)
        });
        //监听地图瓦片加载完成事件
        map.on("tilesloaded", function () {
            document.getElementById("tip").innerHTML = "地图瓦片已加载完成"
        })
    }
</script>

3. Load the map asynchronously

<script>
        function initMap() {
            var map = new TMap.Map("container", {
                pitch: 45,
                zoom: 12,
                center: new TMap.LatLng(39.984104, 116.307503)
            });
        }
        function loadScript() {
            //创建script标签,并设置src属性添加到body中
            var script = document.createElement("script");
            script.type = "text/javascript";
            script.src = "https://map.qq.com/api/gljs?v=1.exp&key=申请key";
            document.body.appendChild(script);
        }
        window.onload = loadScript;
    </script>

4. Simultaneously load two map renderings as follows:

<script>
    function initMap() {
        //初始化地图一
        var mapOne = new TMap.Map("containerOne", {
            pitch:45,
            center: new TMap.LatLng(39.984104, 116.307503)
        });
        //初始化地图二
        var mapTwo = new TMap.Map("containerTwo", {
            center: new TMap.LatLng(39.984104, 116.307503)
        });
    }
</script>

5. Get the map center effect as shown below:

<script>
    var centerInfo = document.getElementById("center-info");

    var center = new TMap.LatLng(39.984104, 116.307503);//设置中心点坐标
    //初始化地图
    var map = new TMap.Map("container", {
        center: center
    });
    //获取地图中心点事件
    function getCenter() {            
        var mapCenter = map.getCenter(); //获取地图中心点坐标
        centerInfo.innerHTML = "当前地图中心为: " + mapCenter.getLat().toFixed(6) + "," + mapCenter.getLng().toFixed(6);
    }
    //设置地图中心点事件
    function setCenter() {
        map.setCenter(new TMap.LatLng(39.908802,116.397502));//坐标为天安门
        centerInfo.innerHTML = "当前地图中心为: 39.908802,116.397502";
    }
</script>

6. The effect of map translation is as follows:

<script>
    function initMap() {
        var position = document.getElementById("position");
        var txt = document.getElementById("txt");
        var center = new TMap.LatLng(39.984104, 116.307503);//设置中心点坐标
        //初始化地图
        var map = new TMap.Map("container", {
            center: center
        });
        location.innerHTML = map.getCenter().toString();
        //监听地图开始平移
        map.on("panstart", function () {
            txt.innerHTML = "地图开始平移"
        })
        //监听地图平移
        map.on("pan",function(){
            txt.innerHTML = "地图正在平移";
            position.innerHTML = map.getCenter().toString();//获取地图中心点
        })
        //监听地图平移结束
        map.on("panend",function(){
            txt.innerHTML = "地图结束平移";
        })
    }
</script>

3.vue access to Tencent map

<template>
  <div>
    <div id="map" style="width:500px;height:500px;"></div>
  </div>
</template>
 
<script>
export default {
  data() {
    return {
      longitude: "",
      latitude: ""
    };
  },
  
  methods: {
    init() {
      let address = "";
      let that = this;
      var center = new qq.maps.LatLng(34.754152, 113.667636);
      var map = new qq.maps.Map(document.getElementById('map'), {
        center: center,
        zoom: 13,
        disableDefaultUI: true
      });
      var marker = new qq.maps.Marker({
        position: center,
        map: map
      });
      var infoWin = new qq.maps.InfoWindow({
        map: map
      });
      var geocoder = new qq.maps.Geocoder({
        complete: function(res) {
          console.log(res);
          address = res.detail.nearPois[0].name;
        }
      });
      qq.maps.event.addListener(map, "click", function(event) {
        this.longitude = event.latLng.getLat();
        this.latitude = event.latLng.getLng();
        console.log(event);
        let lat = new qq.maps.LatLng(this.longitude, this.latitude);
        geocoder.getAddress(lat);
        setTimeout(() => {
          infoWin.open();
          infoWin.setContent(
            '<div style="text-align:center;white-space:nowrap;">' +
              address +
              "</div>"
          );
          infoWin.setPosition(event.latLng);
        }, 200);
      });
    }
  },
  mounted() {
    this.init();
  }
};
</script>
<style scoped>
</style>

You need to import <script charset="utf-8" src="https://map.qq.com/api/js?v=2.exp&key=YOUR_KEY"></script> in index.html before use Use the map.

<script charset="utf-8" src="https://map.qq.com/api/js?v=2.exp&key=yourkey"></script>
<template>
    <div>
        <div id="container" style="width:500px;height:500px;"></div>
    </div>
</template>

<script>
    export default{
        data() {
            return {
                longitude:39.956987, // 经度
                latitude:116.235128 // 纬度
            }
        },
        mounted () {
            this.init();
        },
        methods:{
            init() {
                var myLatlng = new qq.maps.LatLng(39.945687,116.3976968);
                var myOptions = {
                  zoom: 8,               // 设置地图缩放级别
                  center: myLatlng,      // 设置中心点样式
                  mapTypeId: qq.maps.MapTypeId.ROADMAP   
                }
                var map = new qq.maps.Map(document.getElementById("container"), myOptions);
            }
        }
    }
</script>
Create a map instance
var map=new qq.maps.Map(document.getElement('container'),{
center,//坐标,即最初显示的地图中心
zoom    //缩放级别,即显示的比例
})
Add events to the map
qq.maps.event.addListener(map,'click',function(res){
// res即点击后的位置信息
})
Add tag
var marker=new qq.maps.Marker({
position, // 标记点的位置,也可以是通过IP获取到的坐标
map, // 标记在哪个地图上
animation, // 标记显示时的动画效果
title, // 鼠标悬浮到标记上时的标题
draggable // 是否可拖拽
})
Create information window
var info=new qq.maps.InfoWindow({
map, // 标记在哪个地图上
content // 信息窗口的内容
})
cover
var polyline=new qq.maps.Polyline({
map, // 标记在哪个地图上
path, // 一个坐标数组,折线、多边形就是依靠这些坐标数组来成形的
strokeColor, // 折线颜色
strokeDashStyle, // 折线样式
strokeWeight, // 折线宽度
editable, // 折线是否可编辑
clickable // 是否可点击
})

Single mark point

Call the initialization map method after the mounted life cycle or information is obtained from the background interface

initMap (latitude, longitude, message) {
    var center = new qq.maps.LatLng(latitude, longitude);
    var map = new qq.maps.Map(
        document.getElementById("container"),
        {
            center: center,
            zoom: 13
        }
    );

    var marker = new qq.maps.Marker({
        position: center,
        map: map
    });

    var info = new qq.maps.InfoWindow({
        map: map
    });
    
    // 悬浮标记显示信息
    qq.maps.event.addListener(marker, 'mouseover', function() {        
        info.open();
        info.setContent(`<div style="margin:10px;">${message}</div>`);
        info.setPosition(center);
    });
    qq.maps.event.addListener(marker, 'mouseout', function() {
        info.close();
    });
},

Multiple label points

markers: [  ]; // 标记点数组

mounted () {
    this.initMap(this.markers)
},

initMap (arr) {
    // 默认以数组第一项为中心
    var center = new qq.maps.LatLng(arr[0].latitude, arr[0].longitude);
    
    var map = new qq.maps.Map(
        document.getElementById("container"),
        {
            center: center,
            zoom: 13
        }
    );
    
    // 提示窗
    var info = new qq.maps.InfoWindow({
        map: map
    });
    
    for (var i = 0; i < arr.length; i++) {
        var data = arr[i];

        var marker = new qq.maps.Marker({ 
            position: new qq.maps.LatLng(data.latitude, data.longitude), 
            map: map 
        });

        marker.id = data.id;
        marker.name = data.name;
        // 点击事件
        qq.maps.event.addListener(marker, 'mouseover', function() {
            info.open();
            // 设置提示窗内容
            info.setContent(`<div><p>${this.name}</p></div>`);
            // 提示窗位置 
            info.setPosition(new qq.maps.LatLng(this.position.lat, this.position.lng));
        });
        qq.maps.event.addListener(marker, 'mouseout', function() {
            info.close();                    
        });
    }
}

4. Personalized map style

Why use a personalized map to improve the display effect and user experience of the map in different scenarios.

Why choose Tencent location service personalized map:

  • Universal on all platforms
  • Minimal development cost
  • Personalized style supports dynamic update
  • Support global configuration and hierarchical configuration
  • Editing platform UI controls are fully optimized
  • All configurable attributes of each element are open
  • Can support custom map elements expanded to 52 types

5. Steps for getting started with Tencent's location

1. Log in to Tencent's location service

2. Verify mobile phone and email
3. Apply for a development key (Key)
4. Choose the product you need

Location display component
route planning component
map point component
Front end positioning assembly

3. WeChat Mini Program JavaScript SDK

1. I applied for the developer key key
2. Open webserviceAPI service: console -> key management -> settings (key to use this function) -> check webserviceAPI -> save
(Small program SDK needs to use some services of webserviceAPI, so the KEY to use this function needs to have corresponding permissions)
Daily call volume: 10,000 times / Key ---- concurrent number: 5 times / key / second.

onLoad() {
    console.log('页面加载了')
    // 实例化API核心类
    qqmapsdk = new QQMapWX({
        // key: '申请的key'
    });
},
onShow() {
    console.log('页面显示了')
    // 调用接口dadaqianduan
    qqmapsdk.search({
        keyword: '酒店',
        success: (res) => {
            console.log(res);
        },
        fail: (err) => {
            console.log(err);
        },
        complete: (cres) => {
            console.log(cres);
        }
    })
},

The data I returned is shown in the figure:

QQMapWX-Mini Program JavaScriptSDK core class-new QQMapWX(options:Object)

// 引入SDK核心类
var QQMapWX = require('xxx/qqmap-wx.js');
 
// 实例化API核心类
var demo = new QQMapWX({
    key: '开发密钥(key)' // 必填
});

Location search:

// 地点搜索
nearbySearchBtn() {
    qqmapsdk.search({
        keyword: 'kfc', //搜索关键词
        location: '39.980014,116.313972', //设置周边搜索中心点
        success: (res) => {
            var mks = []
            for (var i = 0; i < res.data.length; i++) {
                mks.push({ // 获取返回结果,放到mks数组中
                    title: res.data[i].title,
                    id: res.data[i].id,
                    latitude: res.data[i].location.lat,
                    longitude: res.data[i].location.lng,
                    iconPath: "/location.png", //图标路径
                    width: 20,
                    height: 20
                })
            }
            this.markers = mks
        },
        fail: (res) => {
            console.log(res);
        },
        complete: (res) => {
            console.log(res);
        }
    });
},

The effect is as follows:

<script>
    // 引入SDK核心类,js文件根据自己业务,位置可自行放置
    // var QQMapWX = require('../../js_sdk/wxmp-qqmap/qqmap-wx-jssdk.js');
    import QQMapWX from '../../js_sdk/wxmp-qqmap/qqmap-wx-jssdk.js';
    var qqmapsdk;
    export default {
        components: {},
        data() {
            return {
                backfill: '',
                markers: [],
                suggestion: [],
            }
        },
        onLoad() {
            console.log('页面加载了') // 实例化API核心类
            qqmapsdk = new QQMapWX({ // key: '申请的key'
                key: '自己申请,我的就不放出来了'
            });
        },
        onShow() {
            console.log('页面显示了') // 调用接口dadaqianduan
            qqmapsdk.search({
                keyword: '酒店',
                success: (res) => {
                    console.log(res);
                },
                fail: (err) => {
                    console.log(err);
                },
                complete: (cres) => {
                    console.log(cres);
                }
            })
        },
        onReady() {
            console.log('页面初次渲染完成了')
        },
        methods: {
            getsuggest(e) {
                console.log(e.detail.value)
                qqmapsdk.getSuggestion({
                  keyword: e.detail.value, //用户输入的关键词,可设置固定值,如keyword:'KFC'
                  //region:'北京', //设置城市名,限制关键词所示的地域范围,非必填参数
                  success: (res) => {//搜索成功后的回调
                    console.log(res);
                    var sug = [];
                    for (var i = 0; i < res.data.length; i++) {
                      sug.push({ // 获取返回结果,放到sug数组中
                        title: res.data[i].title,
                        id: res.data[i].id,
                        addr: res.data[i].address,
                        city: res.data[i].city,
                        district: res.data[i].district,
                        latitude: res.data[i].location.lat,
                        longitude: res.data[i].location.lng
                      });
                    }
                     this.suggestion = sug
                  },
                  fail: (error)=> {
                    console.error(error);
                  },
                  complete: (res)=> {
                    console.log(res);
                  }
                });
            },
            backfillBtn(e) {
                var id = e.currentTarget.id;
                for (var i = 0; i < this.suggestion.length; i++) {
                    if (i == id) {
                        this.backfill = this.suggestion[i].title
                    }
                }
            },
            // 地点搜索
            nearbySearchBtn() {
                qqmapsdk.search({
                    keyword: 'kfc', //搜索关键词
                    location: '39.980014,116.313972', //设置周边搜索中心点
                    success: (res) => {
                        var mks = []
                        for (var i = 0; i < res.data.length; i++) {
                            mks.push({ // 获取返回结果,放到mks数组中
                                title: res.data[i].title,
                                id: res.data[i].id,
                                latitude: res.data[i].location.lat,
                                longitude: res.data[i].location.lng,
                                iconPath: "/static/location.png", //图标路径
                                width: 20,
                                height: 20
                            })
                        }
                        this.markers = mks
                    },
                    fail: (res) => {
                        console.log(res);
                    },
                    complete: (res) => {
                        console.log(res);
                    }
                });
            },
        },
        onHide() {
            console.log('页面隐藏了')
        },
    }
</script>

The preview effect is as follows:

<script>
    import QQMapWX from '../../js_sdk/wxmp-qqmap/qqmap-wx-jssdk.js';
    var qqmapsdk;
    export default {
        components: {},
        data() {
            return {
                backfill: '',
                markers: [],
                poi: {
                    latitude: 39.984060,
                    longitude: 16.307520
                },
            }
        },
        onLoad() {
            console.log('页面加载了') // 实例化API核心类
            qqmapsdk = new QQMapWX({ // key: '申请的key'
                key: ''
            });
        },
        onShow() {
            console.log('页面显示了')
        },
        onReady() {
            console.log('页面初次渲染完成了')
        },
        methods: {
            formSubmit(e) {
                qqmapsdk.reverseGeocoder({
                    location: e.detail.value.reverseGeo || '',
                    //获取表单传入的位置坐标,不填默认当前位置,示例为string格式
                    //get_poi: 1, //是否返回周边POI列表:1.返回;0不返回(默认),非必须参数
                    success: (res) => {
                        console.log(res);
                        var res = res.result;
                        var mks = [];
                        /**
                         *  当get_poi为1时,检索当前位置或者location周边poi数据并在地图显示,可根据需求是否使用
                         *
                            for (var i = 0; i < result.pois.length; i++) {
                            mks.push({ // 获取返回结果,放到mks数组中
                                title: result.pois[i].title,
                                id: result.pois[i].id,
                                latitude: result.pois[i].location.lat,
                                longitude: result.pois[i].location.lng,
                                iconPath: './resources/placeholder.png', //图标路径
                                width: 20,
                                height: 20
                            })
                            }
                        *
                        **/
                        //当get_poi为0时或者为不填默认值时,检索目标位置,按需使用
                        mks.push({ // 获取返回结果,放到mks数组中
                            title: res.address,
                            id: 0,
                            latitude: res.location.lat,
                            longitude: res.location.lng,
                            iconPath: '/static/location.png', //图标路径
                            width: 20,
                            height: 20,
                            callout: { //在markers上展示地址名称,根据需求是否需要
                                content: res.address,
                                color: '#000',
                                display: 'ALWAYS'
                            }
                        });
                        this.markers = mks;
                        // this.poi = {
                        //     latitude: res.location.lat,
                        //     longitude: res.location.lng
                        // }
                    },
                    fail: (error) => {
                        console.error(error);
                    },
                    complete: (res) => {
                        console.log(res);
                    }
                })
            }
        },
        onHide() {
            console.log('页面隐藏了')
        },
    }
</script>

geocoder-Provides the conversion from the address description to the location coordinates, which is the opposite of the reverse Geocoder() process.
The preview effect is as follows:

formSubmit(e) {
    //调用地址解析接口
    qqmapsdk.geocoder({
      //获取表单传入地址 e.detail.value.geocoder
      address: e.detail.value, //地址参数,例:固定地址,address: '北京市海淀区彩和坊路海淀西大街74号'
      success: (res)=> {//成功后的回调
        console.log(res);
        var res = res.result;
        var latitude = res.location.lat;
        var longitude = res.location.lng;
        //根据地址解析在地图上标记解析地址位置
         this.markers = [{
            id: 0,
            title: res.title,
            latitude: latitude,
            longitude: longitude,
            iconPath: '/static/location.png',//图标路径
            width: 20,
            height: 20,
            callout: { //可根据需求是否展示经纬度
              content: latitude + ',' + longitude,
              color: '#000',
              display: 'ALWAYS'
            }
          }],
          this.poi= { //根据自己data数据设置相应的地图中心坐标变量名称
            latitude: Number(latitude),
            longitude:  Number(longitude),
          }
      },
      fail: (error)=> {
        console.error(error);
      },
      complete: (res)=> {
        console.log(res);
      }
    })
}

The preview effect is as follows:

formSubmit(e){
        //调用距离计算接口
        console.log(this.start,'dadaqianduan')
        qqmapsdk.calculateDistance({
            //mode: 'driving',//可选值:'driving'(驾车)、'walking'(步行),不填默认:'walking',可不填
            //from参数不填默认当前地址
            //获取表单提交的经纬度并设置from和to参数(示例为string格式)
            // from: e.detail.value.start || '', //若起点有数据则采用起点坐标,若为空默认当前地址
            from: this.start || '',
            to: this.end,
            // to: e.detail.value.dest, //终点坐标
            success: (res)=> {//成功后的回调
              console.log(res);
              var res = res.result;
              var dis = [];
              for (var i = 0; i < res.elements.length; i++) {
                dis.push(res.elements[i].distance); //将返回数据存入dis数组,
              }
              this.distance=dis
            },
            fail: (error)=> {
              console.error(error);
            },
            complete: (res)=> {
              console.log(res);
            }
        });
    }
},

Call the Get City List interface, the effect diagram is as follows:

onShow() {
    console.log('页面显示了')
    //调用获取城市列表接口
    qqmapsdk.getCityList({
        success: (res) => { //成功后的回调
            console.log(res);
            console.log('省份数据:', res.result[0]); //打印省份数据
            this.a = res.result[0]
            console.log('城市数据:', res.result[1]); //打印城市数据
            this.b = res.result[1]
            console.log('区县数据:', res.result[2]); //打印区县数据
            this.c = res.result[2]
        },
        fail: (error) => {
            console.error(error);
        },
        complete: (res) => {
            console.log(res);
        }
    });
},

Get the city districts and counties, the renderings are as follows:

onShow() {
    console.log('页面显示了')
    //调用获取城市列表接口
    qqmapsdk.getCityList({
        success: (res) => { //成功后的回调
            console.log(res);
            console.log('省份数据:', res.result[0])
            var city = res.result[0];
            //根据对应接口getCityList返回数据的Id获取区县数据(以北京为例)
            qqmapsdk.getDistrictByCityId({
                // 传入对应省份ID获得城市数据,传入城市ID获得区县数据,依次类推
                id: city[0].id, //对应接口getCityList返回数据的Id,如:北京是'110000'
                success: (res) => { //成功后的回调
                    console.log(res);
                    console.log('对应城市ID下的区县数据(以北京为例):', res.result[0]);
                },
                fail: (error) => {
                    console.error(error);
                },
                complete: (res) => {
                    console.log(res);
                }
            });
        },
        fail: (error) => {
            console.error(error);
        },
        complete: (res) => {
            console.log(res);
        }
    });
},

Tencent's location service provides WeChat applet with basic punctuation, line and circle drawing interface and other map components and location display, map selection and other map API location service capabilities, allowing developers to freely implement their own WeChat applets product. On this basis, Tencent’s location service WeChat applet JavaScript SDK is an LBS data service toolkit specially provided for applet developers. It can call Tencent’s location service’s POI search, keyword input prompts, address resolution, and reverse in the applet. Data services such as address resolution, administrative divisions and distance calculation make your applet more powerful!

Original Author: Programmer Doraemon
Original link: https://blog.csdn.net/qq_36232611/article/details/111408399
阅读 1.3k

腾讯位置服务
腾讯位置服务产品、技术交流。

立足生态,连接未来

1.6k 声望
0 粉丝
0 条评论
推荐阅读
2022广东春运指南:让回家的路更顺畅一些
春节的脚步越来越近,又迎来一年的春运返乡高峰,小伙伴们是不是等不及要回家过大年?是不是还在忙着搜索各种攻略,研究如何避开春运高峰,让回家的路更顺畅一些呢?

腾讯位置服务阅读 526

封面图
还在用定时器吗?借助 CSS 来监听事件
平时工作中很多场合都要用到定时器,比如延迟加载、定时查询等等,但定时器的控制有时候会有些许麻烦,比如鼠标移入停止、移出再重新开始。这次介绍几个借助 CSS 来更好的控制定时器的方法,一起了解一下吧,相信...

XboxYan29阅读 2k评论 2

封面图
如何优雅地中断 Promise?来试试 AbortController 吧!
欢迎大家来到 前端小课堂 的第五期,今天我们来聊一聊如何终止正在进行中的 Fetch 以及 Promise。文中会跟大家详细介绍这里面的两个关键知识点 AbortController 和 AbortSignal。对动手实践比较感兴趣的同学还可...

dreamapplehappy23阅读 2.9k评论 4

封面图
CSS 绘制一只思否猫
欢迎关注我的公众号:前端侦探练习 CSS 有一个比较有趣的方式,就是发挥想象,绘制各式各样的图案,比如来绘制一只思否猫?思否猫,SegmentFault 思否的吉祥物,是一只独一无二、特立独行、热爱自由的(&gt;^ω^&lt...

XboxYan37阅读 1.7k评论 13

封面图
前端性能优化(图文并茂,通俗易懂)
默认情况下,我们静态导入的所有模块都会添加到初始捆绑包中。使用默认 ES2015 导入语法 导入的模块将静态导入。import module from 'module'

寒水寺一禅26阅读 2.8k评论 1

CSS transition 小技巧!如何保留 hover 的状态?
欢迎关注我的公众号:前端侦探通常情况下,hover 是无法保存状态的。鼠标移入触发额外样式,一旦移出就还原了 {代码...} 这就意味着,如果需要保留hover的状态,可能就不得不借助JS了,比如下面是某某书院的首页...

XboxYan29阅读 3k评论 2

封面图
CSS 如何设置自动滚动定位的“安全”间距?
欢迎关注我的公众号:前端侦探介绍两个和滚动定位相关的 CSS 属性:scroll-padding和 scroll-margin在平时开发中,经常会碰到需要快速定位的问题,比如常见的锚点定位 {代码...} 这样,在点击a标签时会自动定位到...

XboxYan27阅读 1.6k评论 2

封面图

立足生态,连接未来

1.6k 声望
103 粉丝
宣传栏