小程序使用高德开发平台api开发路径规划

在开发一些需要使用地图查找目的地的需求时,需要给用户规划地图线路,有时也需要在线路上标注一些标记点。实现一个交互功能。这次公司业务需求要求实现,使用小程序,实现使用高德开发平台的地图展示起点到终点多条路径规划,展示路径上的标记点,点击也要展示相应的信息。

下面只是分解核心步骤,完整代码,直接到最下方复制就行

一、小程序实现使用高德开发平台js,开发路径规划功能

这里使用的是Taro+vue3搭建的跨段应用小程序,如果使用的原生小程序,核心方法并没有区别,只是写法有些不一样

1.原生小程序或者Taro搭建好的框子或者uniapp搭建的框子,下载小程序使用的高德的js插件

下载地址

需要注意下载的插件代码里面请求高德的接口方式,wx,Taro, Uni请求的方式是不一样的,可以根据小程序开发的框架手动更换请求方式

下载好以后,放到项目里一个位置

插件里面一小段代码:

js 复制代码
// 插件里面一小段代码
AMapWX.prototype.getWxLocation = function (a, b) {
// 这个地方请求的方式,有wx,Taro, Uni,主要看你使用了什么框架开发小程序
    Taro.getLocation({
        type: "gcj02",
        success: function (c) {
            c = c.longitude + "," + c.latitude;
            Taro.setStorage({ key: "userLocation", data: c });
            b(c);
        },
        fail: function (c) {
            Taro.getStorage({
                key: "userLocation",
                success: function (d) {
                    d.data && b(d.data);
                },
            });
            a.fail({ errCode: "0", errMsg: c.errMsg || "" });
        },
    });
};

Taro+vue3引用高德插件(高德 key自己申请或者找公司申请js key)

js 复制代码
<script setup>
    // 路径根据代码位置来
    import { AMap } from "@/utils/amap-wx.130.js";
    // 实例化高德api方法
    let mapPlugin = new AMap({ key: 'xxxxxx' })
<script>
2.因为是使用的小程序html就使用小程序提供的组件map就可以,使用起来更加方便快捷舒适

微信小程序提供的map组件

js 复制代码
<map id="mapId" @regionchange="bindregionchange" @callouttap="bindcallouttap" style="width: 100%; height: 1000rpx;" :latitude="startlat" :longitude="startlng" :markers="markers"  :polyline="polyline" scale="12">
  <cover-view slot="callout">
    <cover-view v-for="(item, index) in markers">
      {{item}}
    </cover-view>
  </cover-view>
</map>

map组件携带的每一个参数,文档里面都有解释,注意写法,uni,Taro,wx原生,绑定方法的时候名称不一样。 uni,Taro ---> @regionchange; wx原生 ---> bindregionchange

3.路径规划api调用,获取路径的参数,只是获取到路径线路上的经纬度集合。
js 复制代码
  // 地图规划路径
    getMap () {
      mapPlugin.getDrivingRoute({
        origin: startlng.value + ',' + startlat.value,
        destination: endlng.value + ',' + endlat.value,
        strategy: 19,
        fail: (info) => {
          console.log('fail', info)
        },
        success: (data) => {
          if (!data.paths) {
            console.log('search failed')
            return;
          }
          console.log(data)
    },
4、获取到路径上的经纬度集合之后,最主要的是标注路径上的线条和标记点---标注线条使用polyline

polyline是一个list集合,传几个属性对象,就展示几条线路。属性里面可以设置线条的颜色,粗细,,等(看文档)

js 复制代码
 polylineArr.value.push({
  arrowLine: true,
  points: item,
  color: '#9BC69A',
  width: 6
},
{
  arrowLine: true,
  points1: item,
  color: '#9BC69A',
  width: 6
},
{
  arrowLine: true,
  points2: item,
  color: '#9BC69A',
  width: 6
})

points 就是 getDrivingRoute方法返会的经纬度集合,获取到经纬度集合点polyline就会画出对应的线条

这里注意一点,polyline我们生成多条线路的时候,需要像高德一样区分主线路和备选线路,但是,集合最后一条的线路颜色层级最高,其他线路无法覆盖 这时候就需要做颜色区分。我尝试了zIndex无法实现区分。处理方法是选择那一条线路的时候,把当前线路放到集合的最后一项。层级最高

5、获取路径上经纬度以后,需要展示经纬度上的标记点,marker

小程序map组件已经封装好了,只要按照文档格式传输markers的list集合就行。marker对象格式可以查看文档

js 复制代码
marker: [
 {
    id: 1,
    width: 26,
    height: 40,
    latitude: xxxx,
    longitude: xxxx,
    iconPath: 'https://img-warehouse.jiayudata.com/assets/xinyue/startPoint.png',
    customCallout: { display: 'ALWAYS' },
    callout: {
      content: '起点',
      color: "#0C0C0C",
      bgColor: "#fff",
      display: "ALWAYS",
      fontSize: "14",
      padding: "10",
      borderRadius: "6",
    }
  },
]

customCallout: { display: 'ALWAYS' }: 这个属性是用于自定义marker,一般情况系,marker是默认图标展示,但是我们需要在地图上自定义marker,那就把marker默认的图标宽高定义为最小,使用customCallout属性吧marker上方的气泡自定义为自己需要的样式,在map组件里面使用cover-view(官网可能有更新标签名,记得查看官网)开发。

6、自动缩小地图,展示完整路径,起点终点

小程序map组件,要求必传一个中心的经纬度。地图生成的时候,会自动把中心经纬度展示在地图中间,这样有一个问题,我们要求展示完整的路径规划的起点和终点,但是只展示了中心经纬度。解决办法,在生成地图实例的时候。

把起点和终点的经纬度传进includePoints方法,这个方法会把起点和终点的经纬度展示进去。完整的路径规划就会展示出来

js 复制代码
  const MapContext = wx.createMapContext('mapId');
  var points = [{longitude:startlng.value,latitude:startlat.value},{longitude:endlng.value,latitude:endlat.value}]
  MapContext.includePoints({
    // 缩放视野展示所有经纬度 [上,右,下,左]  这里四个值要一致
    padding: [80,80,80,80],
    points:points,
  })
7、完整代码。复制调整一下就可以用,没有真实接口,接口自己业务调整去
js 复制代码
<template>
  <view class="wrap">
    <view class="position">
      <view class="left">
        <view class="pl"><text class="start-circle"></text><text>起点</text></view>
        <view class="pl"><text class="end-circle"></text><text>终点</text></view>
      </view>
      <view class="center">
        <input class="start"  disabled="true" v-model="startName" />
        <view class="line"></view>
        <input class="end"  disabled="true" v-model="endName" />
      </view>
    </view>
    <map id="mapId" @regionchange="bindregionchange" @callouttap.stop="bindcallouttap" style="width: 100%; height: 1000rpx;" :latitude="startlat" :longitude="startlng" :markers="markers"  :polyline="polyline" scale="12">
      <cover-view slot="callout">
        <cover-view v-for="(item, index) in markers">
          <cover-view :key="index"  v-show="item.id !== 0.1 && item.id !== 0.2" class="custom-content-marker" :class="[index == marketId ? 'custom-content-active' : '']" :marker-id="item.id">
            <cover-view class="logo">快</cover-view>
            <cover-view class="marker-unit">闲</cover-view> 
            <cover-view class="marker-word">{{ item.freeFastChargeCount }}</cover-view>
        </cover-view>
        </cover-view>
      </cover-view>
    </map>
    <view class="road-tab">
      <view class="tabs" v-for="(item, index) in roadTabs" :class="[isPolicy === index ? 'po-active' : '']" @tap="handleChangePolicy(index)">
        <view class="policy">方案{{ index+1 }}</view>
        <view class="po-time">{{ item.hours || '0' }}时{{ item.minutes || '0' }}分</view>
        <view class="po-dis">{{ item.distance || '--' }}km</view>
      </view>
    </view>
    <view class="card-wrap" v-show="isShowCard" :class="[isAdmin ? '' : 'userCard']">
      <view class="card">
        <view class="card-left">
          <view class="cl-price">{{ stationDetail.unitPrice || '--' }}</view>
          <view class="cl-unit">元/度</view>
        </view>
        <view class="card-line"></view>
        <view class="card-right">
          <view class="cr-top">
            <view class="cr-top-left">
              <view class="sta-name">{{ stationDetail.stationName || '--'}}</view>
              <view class="sta-tips">{{ stationDetail.businessHours || '--' }}</view>
              <view class="sta-type">
                <view class="type" v-show="stationDetail.totalFastChargeCount>0"><image class="quick-pic" src="../../images/jianguan-quick.png" alt=""/><text>闲{{ stationDetail.freeFastChargeCount }}</text><text>/{{ stationDetail.totalFastChargeCount }}</text></view>
                <view v-show="stationDetail.totalTrickleChargeCount>0" class="type type-slow"><image class="slow-pic" src="../../images/jianguan-slow.png" alt=""/><text>闲{{ stationDetail.freeTrickleChargeCount }}</text><text>/{{ stationDetail.totalTrickleChargeCount }}</text></view>
              </view>
            </view>
            <view class="cr-top-right">
              <image class="guide" @tap="handleNavigation" src="../../images/jianguan-guide.png" alt=""/>
            </view>
          </view>
          <view class="cr-bottom" v-show="stationDetail.parkFee"><image src="../../images/jianguan-p.png" class="car-pic"/> <text class="car-word">{{ stationDetail.parkFee || '--' }}</text></view>
        </view>
      </view>
      <view class="price-wrap">
        <view class="price-tab"><text class="getTime">收费时段</text><text>总费用</text><text>=</text><text>电费</text><text>+</text><text>服务费</text></view>
        <view class="price-item-wrap">
          <view v-for="(item, index) in stationDetail.priceDetail && stationDetail.priceDetail.fastChargePrices" :key="index" class="price-item" :class="[index === 0 ? 'first-active' : '']"><text>{{ item && item.startTime || '--' }} - {{ item && item.endTime || '--' }}</text><text>{{ item && item.totalFee || '--' }}</text><text></text><text>{{ item && item.electricityFee || '--' }}</text><text></text><text>{{ item && item.serviceFee || '--' }}</text><image v-if="index === 0" src="../../images/jianguan-price.png" class="now-pic"/></view>
        </view>
      </view>
    </view>
  </view>
</template>

<script setup>
import Taro, { useLoad, useRouter } from '@tarojs/taro'
import { ref, nextTick, onMounted } from 'vue';
import { AMap } from "../../util/amap-wx.130.js";
const query = useRouter();

let mapPlugin = null // 高德地图
mapPlugin = new AMap({ key: 'xxxxxxxxxxxxxx' })
const MapContext = wx.createMapContext('mapId');

const startName = ref() // 起点名称
const endName = ref() // 终点名称
const markers = ref([]) // 集合点
const polyline = ref([]) // 路径线
const startlng = ref('') // 起点
const startlat = ref('') // 起点
const endlng = ref('') // 终点
const endlat = ref('') // 终点
const marketId = ref(null) // 选中的markerId
const isPolicy = ref(0) // 当前路径方案
const isShowCard = ref(false) // 是否展示卡片
const stationDetail = ref({}) // 场站详情数据
const routePlanId = ref('') // 场站路径接口id
const isAdmin = ref('')

const roadTabs = ref([]) // 需要循环的方案
const pointsArrData = ref([])
const roadPlanListArrData = ref([])

onMounted(() => {
  const { params } = query
  startlng.value = params.startlng && Number(params.startlng) || 120.209902
  startlat.value = params.startlat && Number(params.startlat) || 30.246567
  startName.value = params.startName && decodeURIComponent(params.startName) || '浙江省杭州市'
  endlng.value = params.endlng && Number(params.endlng) || 121.006657
  endlat.value = params.endlat && Number(params.endlat) || 29.144594
  endName.value = params.endName && decodeURIComponent(params.endName) || '浙江省天台县'
  routePlanId.value = params.routePlanId || ''
  getMap(0)
})

// 点击marker
const bindcallouttap = (e) => {
	marketId.value = e.detail.markerId
  const markerSta = markers.value.find(item => item.id ===  e.detail.markerId); // 根据 markerId 查找对应的 marker
  stationDetail.value = {}
  hadleStationDetail(markerSta.stationUniqueNumber)
  isShowCard.value = true
}

const bindregionchange = (e) => {
  if (e.causedBy == "scale" || e.causedBy == "drag") {
    console.log("缩放或拖动地图")
    isShowCard.value = false
    marketId.value = null
    stationDetail.value = {}
  }
}

// 跳转导航页面
const handleNavigation = () => {
	const {	stationLat, stationLng,	stationName, address } = stationDetail.value;
	Taro.openLocation({
		name: stationName,
		address: stationName,
		latitude: stationLat,
		longitude: stationLng
	});
};

// 切换不同方案
const handleChangePolicy = (index) => {
  var points = [{longitude:startlng.value,latitude:startlat.value},{longitude:endlng.value,latitude:endlat.value}]
    MapContext.includePoints({
    // 缩放视野展示所有经纬度 [上,右,下,左]  这里四个值要一致
    padding: [80,80,80,80],
    points:points,
  })
  isPolicy.value = index
  isShowCard.value = false
  marketId.value = null
  getMapPoliy(index)
}

const getMapPoliy = (policyIndex) => {
  // policyIndex === 1 ? '#58A159' : '#9BC69A',
  const polylineArr = []
  pointsArrData.value.forEach((item, index) => {
    polylineArr.push({
      arrowLine: true,
      points: item,
      color: '#9BC69A',
      width: 6
    })
  })
  polyline.value = polylineArr // 展示基础路径的数组
  const polyCopy = polylineArr // 复制一份操作
  // 如果pointsArrData长度为1,点击不存在路径切换颜色深浅问题,直接复制最深色
  if(pointsArrData.value.length === 1) {
    console.log('长度为1')
    polyCopy[0].color = '#58A159'
    polyline.value = polyCopy
    handleMarker(roadPlanListArrData.value[0])
  }
  // 如果pointsArrData长度为2,点击不同路径切换问题,把当前的索引路径放到数组最下方-颜色变为深色
  if(pointsArrData.value.length === 2) {
    console.log('长度为2')
    if(policyIndex === 0) {
      [polyCopy[0], polyCopy[1]] = [polyCopy[1], polyCopy[0]]
      polyCopy[1].color = '#58A159'
      polyline.value = polyCopy
      handleMarker(roadPlanListArrData.value[0])
    }
    if(policyIndex === 1) {
      [polyCopy[0], polyCopy[1]] = [polyCopy[0], polyCopy[1]]
      polyCopy[1].color = '#58A159'
      polyline.value = polyCopy
      handleMarker(roadPlanListArrData.value[1])
    }
  }
  // 如果pointsArrData长度为3,点击不同路径切换问题,把当前的索引路径放到数组最下方-颜色变为深色
  if(pointsArrData.value.length === 3) {
    console.log('长度为3')
    if(policyIndex === 0) {
      [polyCopy[0], polyCopy[1], polyCopy[2]] = [polyCopy[1], polyCopy[2], polyCopy[0]]
      polyCopy[2].color = '#58A159'
      polyline.value = polyCopy
      handleMarker(roadPlanListArrData.value[0])
    }
    if(policyIndex === 1) {
      [polyCopy[0], polyCopy[1], polyCopy[2]] = [polyCopy[0], polyCopy[2], polyCopy[1]]
      polyCopy[2].color = '#58A159'
      polyline.value = polyCopy
      handleMarker(roadPlanListArrData.value[1])
    }
    if(policyIndex === 2) {
      [polyCopy[0], polyCopy[1], polyCopy[2]] = [polyCopy[0], polyCopy[1], polyCopy[2]]
      polyCopy[2].color = '#58A159'
      polyline.value = polyCopy
      handleMarker(roadPlanListArrData.value[2])
    }
  }
}

// 获取场站详情的地图信息
const getMap = (policyIndex) => {
  roadTabs.value = []
  mapPlugin.getDrivingRoute({
    origin: startlng.value + ',' + startlat.value,
    destination: endlng.value + ',' + endlat.value,
    strategy: 19,
    fail: (info) => {
      console.log('fail', info)
    },
    success: (data) => {
      if (!data.paths) {
        console.log('search failed')
        return;
      }
      console.log(data, '路径的数据')
      // 循环展示方案
      const pointsArr = [] // 路径点集合
      const roadPlanListArr = [] // 路径经纬度集合
      data.paths.forEach((item, index) => {
        console.log(item, '每一个路径方案')
        const total =  item.duration
        const hours = Math.floor(total / 3600); // 取整数部分作为小时数
        const remainSeconds = total % 3600; // 取余数作为剩余的秒数
        const minutes = Math.floor(remainSeconds / 60); // 取整数部分作为分钟数
        const obj = { hours, minutes, distance: (item.distance / 1000).toFixed(2) }
        roadTabs.value.push(obj) // 方案集合
        pointsArr[index] = [] // 定义路径集合几个变量
        roadPlanListArr[index] = [] // 定义路径经纬度集合几个变量
        // 获取每个方案的路径点,用于规划路线
        item.steps.forEach(itemSteps => {
          const polylines = itemSteps.polyline.split(';')
          polylines.forEach(itemPoliy => {
            const locations = itemPoliy.split(',')
            pointsArr[index].push({ longitude: locations[0], latitude: locations[1], })
            roadPlanListArr[index].push({ lng: locations[0], lat: locations[1] })
          })
        })
      })
      pointsArrData.value = pointsArr // 每个路径的集合点
      roadPlanListArrData.value = roadPlanListArr // 每个路径经纬度集合点,需要传给后端获取场站信息
      getMapPoliy(0)
    }
  })
  var points = [{longitude:startlng.value,latitude:startlat.value},{longitude:endlng.value,latitude:endlat.value}]
  MapContext.includePoints({
    // 缩放视野展示所有经纬度 [上,右,下,左]  这里四个值要一致
    padding: [80,80,80,80],
    points:points,
  })
}

// 获取marker数据
const handleMarker = (roadPlanArr) => {
// 假数据
Taro.showLoading()
let markerArr = []
markerArr = [
  {
    id: 0.1,
    width: 26,
    height: 40,
    latitude: roadPlanArr[0].lat,
    longitude: roadPlanArr[0].lng,
    iconPath: 'https://img-warehouse.jiayudata.com/assets/xinyue/startPoint.png',
    customCallout: { display: 'ALWAYS' },
    callout: {
      content: '起点',
      color: "#0C0C0C",
      bgColor: "#fff",
      display: "ALWAYS",
      fontSize: "14",
      padding: "10",
      borderRadius: "6",
    }
  },
  {
    id: 1,
    width: 26,
    height: 40,
    latitude:  29.144778,
    longitude: 121.007923,
    iconPath: 'https://img-warehouse.jiayudata.com/assets/xinyue/endPoint.png',
    customCallout: { display: 'ALWAYS' }
  },
  {
    id: 0.2,
    width: 26,
    height: 40,
    latitude: roadPlanArr[roadPlanArr.length-1].lat,
    longitude: roadPlanArr[roadPlanArr.length-1].lng,
    iconPath: 'https://img-warehouse.jiayudata.com/assets/xinyue/endPoint.png',
    customCallout: { display: 'ALWAYS' },
    callout: {
      content: '终点',
      color: "#0C0C0C",
      bgColor: "#fff",
      display: "ALWAYS",
      fontSize: "14",
      padding: "10",
      borderRadius: "6",
    }
  }]
  markers.value = markerArr
}
// 获取单个场站详情接口
const hadleStationDetail = () => {
  isShowCard.value = true
}
</script>
<style lang="less">
.wrap{
  width: 100%;
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
  padding-top: 10px;
  position: relative;
  // background: #f9f9f9;
  .custom-content-marker{
    width: 100rpx;
    height: 40rpx;
    border: 2rpx solid #22C1BF;
    background: #fff;
    border-radius: 40rpx;
    display: flex;
    justify-content: flex-start;
    align-items: center;
    padding: 10rpx 12rpx;
    .logo{
      width: 36rpx;
      height: 36rpx;
      background: #22C1BF;
      color: #FFF;
      font-family: PingFang SC;
      font-size: 20rpx;
      font-style: normal;
      font-weight: 500;
      border-radius: 50%;
      text-align: center;
      line-height: 36rpx;
      margin-right: 12rpx;
    }
    .marker-word{
      min-width: 30rpx;
      color: #22C1BF;
      font-family: PingFang SC;
      font-size: 22rpx;
      font-style: normal;
      font-weight: 500;
      // border:1px solid #0f0;
    }
    .marker-unit{
      color: #22C1BF;
      font-family: PingFang SC;
      font-size: 22rpx;
      font-style: normal;
      font-weight: 500;
    }
  }
  .custom-content-active{
    background: #22C1BF;
    .logo{
      background: #FFF;
      color: #22C1BF;
    }
    .marker-word{
      color: #fff;
    }
    .marker-unit{
      color: #fff;
    }
  }
  .position{
    width: 90%;
    height: 160rpx;
    background: #f9f9f9;
    border-radius: 20rpx;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 30rpx;
    box-sizing: border-box;
    margin-bottom: 20rpx;
    .left{
      width: 20%;
      height: 100%;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      align-items: center;
      font-weight: 500;
      font-size: 28rpx;
      padding: 4rpx 0;
      box-sizing: border-box;
      .pl{
        display: flex;
        justify-content: flex-start;
        align-items: center;
        .start-circle{
          display: inline-block;
          width: 12rpx;
          height: 12rpx;
          border:1px solid #21CC84;
          border-radius: 50%;
          margin-right: 8rpx;
        }
        .end-circle{
          display: inline-block;
          width: 12rpx;
          height: 12rpx;
          border:1px solid #FF1C1C;
          border-radius: 50%;
          margin-right: 8rpx;
        }
      }
    }
    .center{
      flex:1;
      // height: 100px;
      height: 100%;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      align-items: flex-start;
      .start{
        width: 100%;
        height: 44rpx;
        outline: none;
        background-color: transparent;
        font-size: 28rpx;
      }
      .line{
        width: 100%;
        // height: px;
        border: 0.5px solid #e7e7e7;
      }
      .end{
        width: 100%;
        height: 44rpx;
        outline: none;
        background-color: transparent;
        font-size: 28rpx;
      }
    }
    .right{
      width: 20%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
    }
  }
  #mapId{
    flex:1;
    z-index: 1;
  }
  .road-tab{
    width: 100%;
    height: 188rpx;
    border-bottom:1px solid #e6e6e6;
    display: flex;
    justify-content: space-around;
    align-items: center;
    .tabs{
      display: flex;
      flex-direction: column;
      justify-content: flex-start;
      align-items: center;
      color: #262626;
      .policy{
        text-align: center;
        font-family: PingFang SC;
        font-size: 26rpx;
        font-style: normal;
        font-weight: 500;
      }
      .po-time{
        text-align: center;
        font-family: PingFang SC;
        font-size: 36rpx;
        font-style: normal;
        font-weight: 500;
      }
      .po-dis{
        text-align: center;
        font-family: PingFang SC;
        font-size: 24rpx;
        font-style: normal;
        font-weight: 400;
      }
    }
    .po-active{
      color: #22C1BF;
    }
  }
  // 卡片
  .card-wrap{
    position: absolute;
    width: 90%;
    // height: 118px;
    z-index: 100 ;
    bottom: 310rpx;
    background: #fff;
    padding: 24rpx 16rpx;
    border-radius: 20rpx;
    z-index: 10000;
    .card{
      // padding: 24rpx 36rpx;
      max-height: 236rpx;
      padding-bottom: 10rpx;
      display: flex;
      justify-content: flex-start;
      .card-left{
        width: 126rpx;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        padding-right: 5rpx;
        .cl-price{
          color: #FF1C1C;
          font-family: D-DIN;
          font-size: 52rpx;
          font-style: normal;
          font-weight: 700;
        }
        .cl-unit{
          color: #FF1C1C;
          font-family: PingFang SC;
          font-size: 24rpx;
          font-style: normal;
          font-weight: 500;
        }
      }
      .card-line{
        min-height: 80rpx;
        border: 0.5px solid #eee;
      }
      .card-right{
        flex:1;
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        padding-left: 15rpx;
        .cr-top{
          display: flex;
          justify-content: space-between;
          align-items: center;
          .cr-top-left{
            width: 90%;
            .sta-name{
              color: #262626;
              font-family: PingFang SC;
              font-size: 32rpx;
              font-style: normal;
              font-weight: 600;
              max-width: 440rpx;
              overflow: hidden;
              white-space: nowrap;
              text-overflow: ellipsis;
            }
            .sta-tips{
              color: #8C8C8C;
              font-family: PingFang SC;
              font-size: 24rpx;
              font-style: normal;
              font-weight: 300;
              max-width: 340rpx;
              overflow: hidden;
              white-space: nowrap;
              text-overflow: ellipsis;
              margin-top: 12rpx;
            }
            .sta-type{
              display: flex;
              justify-content: flex-start;
              align-items: center;
              margin-top: 12rpx;
              .type{
                min-width: 142rpx;
                height: 42rpx;
                border: 1px solid rgba(255, 95, 15, 0.25);
                display: flex;
                justify-content: flex-start;
                align-items: center;
                border-radius: 8rpx;
                padding-right: 4rpx;
                .quick-pic{
                  width: 42rpx;
                  height: 42rpx;
                }
                .slow-pic{
                  width: 42rpx;
                  height: 42rpx;
                }
                >text:nth-child(2){
                  color: #FF4D00;
                  font-family: PingFang SC;
                  font-size: 26rpx;
                  font-style: normal;
                  font-weight: 600;
                  margin-left: 8rpx;
                }
                >text:nth-child(3){
                  color: #BFBFBF;
                  font-family: PingFang SC;
                  font-size: 26rpx;
                  font-style: normal;
                  font-weight: 600;
                }
              }
              .type-slow{
                border:1px solid rgba(12, 188, 204, 0.25);
                margin-left: 16rpx;
                >text:nth-child(2){
                  color: #0CBCCC;
                  font-family: PingFang SC;
                  font-size: 26rpx;
                  font-style: normal;
                  font-weight: 600;
                  margin-left: 8rpx;
                }
              }
            }
          }
          .cr-top-right{
            .guide{
              width: 60rpx;
              height: 60rpx;
            }
            .distance{
              color:#8C8C8C;
              font-family: D-DIN;
              font-size: 28rpx;
              font-style: normal;
              font-weight: 700;
            }
          }
        }
        .cr-bottom{
          display: flex;
          justify-content: flex-start;
          align-items: center;
          padding-top: 12rpx;
          margin-top: 12rpx;
          border-top: 1px dashed #eee;
          .car-pic{
            width: 32rpx;
            height: 32rpx;
            margin-right: 10px;
          }
          .car-word{
            max-width: 360rpx;
            font-size: 24rpx;
            color: #424242;
            overflow: hidden;
            white-space: nowrap;
            text-overflow: ellipsis;
          }
        }
      }
    }
    .price-wrap{
      width: 100%;
      // border:1px solid #0f0;
      .price-type{
        height: 56rpx;
        display: flex;
        justify-content: space-around;
        align-items: center;
        background: #F5F5F5;
        border-radius: 16rpx;
        padding: 0 2px;
        .price-item{
          width: 50%;
          height: 48rpx;
          border-radius: 16rpx;
          display: flex;
          justify-content: center;
          align-items: center;
          color: #404040;
          text-align: center;
          font-family: PingFang SC;
          font-size: 24rpx;
          font-style: normal;
          font-weight: 500;
        }
        .activePrice{
          background: #fff;
          color: #22C1BF;
          font-family: PingFang SC;
          font-size: 24rpx;
          font-style: normal;
          font-weight: 500;
          line-height: normal;
          box-shadow: 0px 0px 8rpx 0px rgba(38, 38, 38, 0.08);
        }
      }
      .price-tab{
        // width: 100%;
        height: 60rpx;
        border-radius: 16rpx;
        background: #F9F9F9;
        margin-top: 8rpx;
        color: #262626;
        font-family: PingFang SC;
        font-size: 24rpx;
        font-style: normal;
        font-weight: 400;
        line-height: normal;
        display: flex;
        justify-content: flex-start;
        align-items: center;
        padding: 14rpx;
        >text{
          width: 16%;
          display: flex;
          justify-content: center;
          // border:1px solid #0f0;
        }
        .getTime{
          display: inline-block;
          width: 30%;
        }
      }
      .price-item-wrap{
        // width: 100%;
        max-height: 148rpx;
        // border:1px solid;
        overflow: auto;
        padding-top: 4rpx;
        .price-item{
          // width: 100%;
          height: 60rpx;
          border-radius: 16rpx;
          background: #F9F9F9;
          margin-top: 8rpx;
          color: #262626;
          font-family: PingFang SC;
          font-size: 24rpx;
          font-style: normal;
          font-weight: 400;
          line-height: normal;
          display: flex;
          justify-content: flex-start;
          align-items: center;
          padding: 14rpx;
          >text{
            width: 16%;
            color: #8C8C8C;
            font-family: D-DIN;
            font-size: 24rpx;
            font-style: normal;
            font-weight: 700;
            line-height: normal;
            text-align: center;
          }
          >text:nth-child(1){
            width: 30%;
          }
          >text:nth-child(2){
            color: #262626;
            font-family: D-DIN;
            font-size: 32rpx;
            font-style: normal;
            font-weight: 700;
            line-height: normal;
          }
        }
        .first-active{
          border-radius: 16rpx;
          border: 1px solid #22C1BF;
          background: rgba(34, 193, 191, 0.05);
          position: relative;
          padding: 10rpx;
          >text{
            width: 16%;
            color: #22C1BF;
            font-family: D-DIN;
            font-size: 24rpx;
            font-style: normal;
            font-weight: 700;
            line-height: normal;
            text-align: center;
          }
          >text:nth-child(2){
            color: #22C1BF;
          }
          .now-pic{
            position: absolute;
            width: 86rpx;
            height: 40rpx;
            left: -2rpx;
            top: -16rpx;
          }
        }
      }
    }
  }
  .userCard{
    bottom: 200rpx;
  }
}
</style>
相关推荐
燃先生._.38 分钟前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖2 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235242 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240253 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar3 小时前
纯前端实现更新检测
开发语言·前端·javascript
寻找沙漠的人3 小时前
前端知识补充—CSS
前端·css
GISer_Jing3 小时前
2025前端面试热门题目——计算机网络篇
前端·计算机网络·面试
m0_748245523 小时前
吉利前端、AI面试
前端·面试·职场和发展
理想不理想v4 小时前
webpack最基础的配置
前端·webpack·node.js