maps.vue 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. <template>
  2. <view class="maps-container">
  3. <view class="search-bar">
  4. <view class="search-bar-form">
  5. <view class="search-bar-box">
  6. <icon class="icon-search-in-box" type="search" :size="16"></icon>
  7. <input confirm-type="search" class="search-bar-input" placeholder="请输入您的目的地" :value="inputVal" :focus="inputShowed"
  8. @confirm="bindInput" @input="inputTyping" />
  9. <view class="icon-clear" v-if="inputVal" @tap="clearInput">
  10. <icon type="clear" size="14"></icon>
  11. </view>
  12. </view>
  13. <view class="search-bar-label" v-show="!inputShowed" @tap="showInput">
  14. <icon class="icon-search" type="search" :size="16"></icon>
  15. <view class="search-bar-text">请输入您的目的地</view>
  16. </view>
  17. </view>
  18. <view class="cancel-btn" @tap="hideInput" v-show="inputShowed">取消</view>
  19. </view>
  20. <map class="tui-map" :latitude="lat" :longitude="lng" :markers="covers" @markertap="marker" :scale="12"></map>
  21. <scroll-view scroll-y class="scrollView" :style="{height:scrollH +'px'}">
  22. <view class="tui-list">
  23. <view class="tui-list-cell" :class="[index==address.length-1?'tui-cell-last':'']" v-for="(item,index) in address"
  24. :key="index">
  25. <view class="addr-title">
  26. <text>{{item.title}}</text>
  27. </view>
  28. <view class="addr-box ">
  29. <view class="addr-detail ">
  30. <text class="distance">{{item.distance}}m</text>
  31. {{item.address}}
  32. </view>
  33. <view class="addr-opera ">
  34. <view class="opera-box " hover-class="tui-opcity" :hover-stay-time="150 " @tap="call " :data-id="item.id" v-if="item.tel">
  35. <image src="/static/images/my/call.png" class="mini-img"></image>
  36. <view class="text">打电话</view>
  37. </view>
  38. <view class="opera-box " hover-class="tui-opcity" :hover-stay-time="150" @tap="go" :data-id="item.id">
  39. <image src="/static/images/my/go.png" class="mini-img"></image>
  40. <view class="text">到这里</view>
  41. </view>
  42. </view>
  43. </view>
  44. </view>
  45. </view>
  46. </scroll-view>
  47. </view>
  48. </template>
  49. <script>
  50. const amap = require('@/libs/amap-wx.js')
  51. export default {
  52. data() {
  53. return {
  54. inputShowed: false,
  55. inputVal: "",
  56. amapPlugin: null,
  57. key: "6799b5f6f88d3d9fb52ac244855a8759",
  58. lat: 22.63137,
  59. lng: 114.010857,
  60. covers: [],
  61. address: [],
  62. scrollH: 256
  63. }
  64. },
  65. onLoad(options) {
  66. this.amapPlugin = new amap.AMapWX({
  67. key: this.key
  68. });
  69. setTimeout(() => {
  70. let winHeight = uni.getSystemInfoSync().windowHeight;
  71. this.scrollH = winHeight - 44 - uni.upx2px(600);
  72. this.getLocation(() => {
  73. this.getPoiAround(options.key || "加油站")
  74. });
  75. }, 300)
  76. },
  77. onNavigationBarButtonTap(e) {
  78. uni.navigateTo({
  79. url: './details'
  80. });
  81. },
  82. methods: {
  83. trim: function(value) {
  84. return value ? value.toString().replace(/(^\s*)|(\s*$)/g, "") : value;
  85. },
  86. showInput() {
  87. this.inputShowed = true
  88. },
  89. hideInput() {
  90. this.inputVal = "";
  91. this.inputShowed = false;
  92. uni.hideKeyboard(); //强行隐藏键盘
  93. },
  94. clearInput() {
  95. this.inputVal = ""
  96. },
  97. inputTyping: function(e) {
  98. this.inputVal = e.detail.value
  99. },
  100. getLocation(callback) {
  101. const that = this
  102. this.amapPlugin.getRegeo({
  103. success: (data) => {
  104. that.lng = data[0].longitude;
  105. that.lat = data[0].latitude;
  106. callback();
  107. },
  108. fail: (info) => {
  109. callback();
  110. }
  111. })
  112. },
  113. getPoiAround(keywords) {
  114. //检索周边的POI
  115. uni.showLoading({
  116. title: "加载中..."
  117. })
  118. const that = this;
  119. setTimeout(() => {
  120. this.amapPlugin.getPoiAround({
  121. querykeywords: keywords,
  122. location: '', //location: 经纬度坐标。 为空时, 基于当前位置进行地址解析。 格式: '经度,纬度'
  123. success: (data) => {
  124. let arr = [];
  125. let addr = [];
  126. for (let i = 0; i < data.markers.length; i++) {
  127. arr.push({
  128. id: i,
  129. latitude: data.markers[i].latitude,
  130. longitude: data.markers[i].longitude,
  131. title: data.markers[i].name
  132. })
  133. let tel = that.trim(data.poisData[i].tel);
  134. if (~tel.indexOf(";")) {
  135. tel = tel.split(";")[0]
  136. }
  137. addr.push({
  138. id: i,
  139. latitude: data.markers[i].latitude,
  140. longitude: data.markers[i].longitude,
  141. title: data.markers[i].name,
  142. address: data.markers[i].address,
  143. tel: tel,
  144. distance: data.poisData[i].distance
  145. })
  146. }
  147. this.address = addr;
  148. this.covers = arr;
  149. uni.hideLoading()
  150. },
  151. fail: (info) => {
  152. uni.showToast({
  153. title: '获取位置信息失败,请检查是否打开位置权限'
  154. })
  155. uni.hideLoading()
  156. }
  157. })
  158. }, 0);
  159. },
  160. bindInput: function(e) {
  161. const keywords = e.detail.value;
  162. this.getPoiAround(keywords);
  163. },
  164. marker: function(e) {
  165. const that = this
  166. const item = that.address[e.markerId || 0];
  167. const menu = item.tel ? ["打电话", "到这里"] : ["到这里"];
  168. uni.showActionSheet({
  169. itemList: menu,
  170. success(res) {
  171. if (res.tapIndex == 0 && item.tel) {
  172. uni.makePhoneCall({
  173. phoneNumber: item.tel
  174. })
  175. } else {
  176. const latitude = Number(item.latitude)
  177. const longitude = Number(item.longitude)
  178. uni.openLocation({
  179. name: item.title,
  180. address: item.address,
  181. latitude,
  182. longitude,
  183. scale: 18
  184. })
  185. }
  186. },
  187. fail(res) {
  188. console.log(res.errMsg)
  189. }
  190. })
  191. },
  192. call(event) {
  193. const index = Number(event.currentTarget.dataset.id);
  194. const tel = this.address[index].tel;
  195. if (tel) {
  196. uni.makePhoneCall({
  197. phoneNumber: tel
  198. })
  199. }
  200. },
  201. go(event) {
  202. const index = Number(event.currentTarget.dataset.id)
  203. const item = this.address[index];
  204. const latitude = Number(item.latitude)
  205. const longitude = Number(item.longitude)
  206. uni.openLocation({
  207. name: item.title,
  208. address: item.address,
  209. latitude,
  210. longitude,
  211. scale: 18
  212. })
  213. }
  214. }
  215. }
  216. </script>
  217. <style>
  218. page {
  219. height: 100%;
  220. }
  221. .tui-list {
  222. background-color: #fff;
  223. position: relative;
  224. width: 100%;
  225. display: flex;
  226. flex-direction: column;
  227. padding-bottom: env(safe-area-inset-bottom);
  228. }
  229. .tui-list-cell {
  230. position: relative;
  231. display: flex;
  232. flex-direction: row;
  233. justify-content: space-between;
  234. align-items: center;
  235. }
  236. .tui-list-cell::after {
  237. content: '';
  238. position: absolute;
  239. border-bottom: 1rpx solid #eaeef1;
  240. -webkit-transform: scaleY(0.5);
  241. transform: scaleY(0.5);
  242. bottom: 0;
  243. right: 0;
  244. left: 30rpx;
  245. }
  246. .tui-cell-last::after {
  247. border-bottom: 0;
  248. }
  249. .maps-container {
  250. width: 100%;
  251. height: 100%;
  252. overflow: hidden;
  253. }
  254. .tui-map {
  255. width: 100%;
  256. height: 600rpx;
  257. display: block;
  258. }
  259. .scrollView {
  260. width: 100%;
  261. padding-bottom: 100rpx;
  262. background-color: #fff;
  263. }
  264. .search-bar {
  265. position: relative;
  266. padding: 8px 10px;
  267. display: -webkit-flex;
  268. display: flex;
  269. box-sizing: border-box;
  270. align-items: center;
  271. background-color: #fff;
  272. }
  273. .icon-search {
  274. margin-right: 8px;
  275. }
  276. .icon-search-in-box {
  277. margin-right: 8rpx;
  278. }
  279. .search-bar-form {
  280. position: relative;
  281. -webkit-box-flex: 1;
  282. -webkit-flex: auto;
  283. flex: auto;
  284. border-radius: 5px;
  285. background-color: #f0f0f0;
  286. }
  287. .search-bar-text {
  288. display: inline-block;
  289. font-size: 14px;
  290. vertical-align: middle;
  291. }
  292. .search-bar-box {
  293. width: 100%;
  294. height: 30px;
  295. padding-left: 10px;
  296. padding-right: 30px;
  297. box-sizing: border-box;
  298. display: flex;
  299. align-items: center;
  300. flex-wrap: nowrap;
  301. position: relative;
  302. z-index: 1;
  303. }
  304. .search-bar-input {
  305. font-size: 14px;
  306. flex: 1;
  307. }
  308. .icon-clear {
  309. height: 100%;
  310. position: absolute;
  311. top: 0;
  312. right: 0;
  313. padding: 0 8px;
  314. font-size: 0;
  315. display: flex;
  316. align-items: center;
  317. }
  318. .search-bar-label {
  319. width: 100%;
  320. height: 100%;
  321. position: absolute;
  322. left: 0;
  323. top: 0;
  324. z-index: 2;
  325. border-radius: 3px;
  326. text-align: center;
  327. color: #9b9b9b;
  328. background: #f0f0f0;
  329. display: flex;
  330. align-items: center;
  331. justify-content: center;
  332. }
  333. .cancel-btn {
  334. margin-left: 10px;
  335. line-height: 30px;
  336. color: #5982fd;
  337. white-space: nowrap;
  338. font-size: 15px;
  339. }
  340. .tui-list-cell {
  341. display: initial;
  342. padding: 30rpx;
  343. }
  344. .addr-title {
  345. font-size: 30rpx;
  346. line-height: 40rpx;
  347. color: #000;
  348. font-weight: bold;
  349. width: 100%;
  350. padding-bottom: 20rpx;
  351. }
  352. .addr-box {
  353. display: flex;
  354. align-items: flex-end;
  355. justify-content: space-between;
  356. }
  357. .addr-detail {
  358. width: 450rpx;
  359. overflow: hidden;
  360. text-overflow: ellipsis;
  361. display: -webkit-box;
  362. -webkit-line-clamp: 2;
  363. /* autoprefixer: off */
  364. -webkit-box-orient: vertical;
  365. /* autoprefixer: on */
  366. font-size: 24rpx;
  367. color: #999;
  368. }
  369. .distance {
  370. color: #5677fc;
  371. padding-right: 6rpx;
  372. }
  373. .addr-opera {
  374. display: flex;
  375. align-items: center;
  376. justify-content: space-between;
  377. }
  378. .opera-box {
  379. text-align: center;
  380. margin-left: 26rpx;
  381. }
  382. .mini-img {
  383. width: 44rpx;
  384. height: 44rpx;
  385. }
  386. .text {
  387. color: #333;
  388. font-size: 24rpx;
  389. line-height: 30rpx;
  390. }
  391. </style>