Browse Source

地图组件重写

yfso 2 năm trước cách đây
mục cha
commit
70decb945c
4 tập tin đã thay đổi với 408 bổ sung148 xóa
  1. 76 71
      components/hch-position/hch-position.vue
  2. 33 76
      pages/map/map.vue
  3. 298 0
      pages/map/scrollHotel.vue
  4. 1 1
      setting.js

+ 76 - 71
components/hch-position/hch-position.vue

xqd xqd xqd xqd xqd
@@ -1,10 +1,10 @@
 <template>
-	<view>
-		<view class="page-body">
-			<view class="page-section page-section-gap">
-				<map  scale="10"  ubkey='CQIBZ-P2MR5-PM3IB-QRKTX-SEVJE-GYF34' :showScale="false" :showLocation="true"  :showCompass="false" enableZoom="true" enableScroll="true" enableBuilding="true" enable3D="true" id="myMap" style="width: 100%; height: 600px;"
-					:latitude="latitude" 
-					:longitude="longitude"
+	<view style="height:100%;">
+		<view class="page-body" style="height:100%;">
+			<view class="page-section page-section-gap" style="height:100%;">
+				<map scale="10"  ubkey='CQIBZ-P2MR5-PM3IB-QRKTX-SEVJE-GYF34' :showScale="false" :showLocation="true"  :showCompass="false" enableZoom="true" enableScroll="true" enableBuilding="true" enable3D="true" id="myMap" style="width: 100%; height: 100%;"
+					:latitude="innerGeo.latitude" 
+					:longitude="innerGeo.longitude"
 					:markers="markersIn" 
 					:layerStyle="mapStyle"  
 					@markertap='markertap'
@@ -17,7 +17,8 @@
 				style="position: fixed;left:0px;top: -500px;"
 				isRenderImage
 				:board="painter.base"
-				@success="(e)=>{painter.path = e; painter.wait=0}"
+				@success="canvasSuccess"
+				@fail="canvasFail"
 			/>
 		</view>
 	</view>
@@ -52,15 +53,25 @@
 						},
 					},
 				]
+			},
+			geo:{
+				type: Object,
+				default:{
+					latitude:30.6034799,
+					longitude:104.1132550,
+				}
 			}
 		},
 		data() {
 			return {
+				updateMode: true,
 				isisMarkering: false,
 				isActiveMarker: 0,
 				isActiveMarkerIndex: -1,
-				latitude: 30.6034799,
-				longitude: 104.1132550,
+				innerGeo:{
+					latitude: 30.6034799,
+					longitude: 104.1132550,
+				},
 				mapStyle: 1, //个性化地图
 				markersIn: [],
 				isUpdate: false,
@@ -117,72 +128,60 @@
 		},
 		methods: {
 			goLocation(la,lo){
-				this.latitude = la
-				this.longitude = lo
-			},
-			//生成图片
-			generateImg(imgUrl){
-				this.painter.base.views[1].src = imgUrl;
-				this.painter.wait = 1;
-				
-				return new Promise(resolve=>{
-					let timer = setInterval(()=>{
-						if(this.painter.wait === 0){
-							clearInterval(timer);
-							resolve(this.painter.path);
-						}else if(this.painter.wait <= 3000){
-							this.painter.wait += 10
-						}else{
-							clearInterval(timer);
-							this.painter.wait = 0;
-							resolve(this.painter.path);
-						}
-					}, 10);
-				})
+				this.innerGeo = {
+					latitude:la,
+					longitude:lo
+				}
 			},
 			//	点击标记点时触发,e.detail = {markerId}
-			markertap(e, mode = true, isQt = false) {
-				
-				
-				let index = 0;
-				if(typeof e.index !== 'undefined'){
-					index = e.index;
-				}else if(typeof e.index === 'undefined'){
-					index = e.markerId;
-				}	
-				
-				if(!isQt && (this.isActiveMarkerIndex === index || this.isMarkering)) return;
-				this.isMarkering = true;
-				setTimeout(()=>{
-					this.isMarkering = false
-				}, 200)
-				const itemOld = this.markersIn[this.isActiveMarkerIndex];
-				if(itemOld){
-					itemOld.width = itemOld.noActive.width;
-					itemOld.height = itemOld.noActive.height;
-					itemOld.iconPath = itemOld.noActive.iconPath;
-					itemOld.isActive = false;
-					this.$set(this.markersIn, this.isActiveMarkerIndex, itemOld);
+			markertap(index, mode = true, isQt = false) {
+				console.log(index)
+				this.updateMode = mode
+				if(typeof index == 'object'){
+					index = index.markerId
 				}
-				this.isActiveMarkerIndex = index;
-				const item = this.markersIn[this.isActiveMarkerIndex];
-				item.width = item.active.width;
-				item.height = item.active.height;
-				item.iconPath = this.painter.path;
-				item.isActive = true;
-				this.$set(this.markersIn, index, item);
-				this.latitude = item.latitude
-				this.longitude = item.longitude
 				if(this.painter.wait != 0) return;
-				this.generateImg(item.active.iconPath).then(()=>{
-					// if(this.isActiveMarker != item.id) return;
-					item.width = item.active.width;
-					item.height = item.active.height;
-					item.iconPath = this.painter.path;
-					item.isActive = true;
-					this.$set(this.markersIn, index, item);
-				})
-				mode&&this.$emit('moveToMarkId',index);
+				if(this.isActiveMarkerIndex === index) return;
+				if(this.markersIn[this.isActiveMarkerIndex]){
+					this.markersIn[this.isActiveMarkerIndex].width = '34rpx';
+					this.markersIn[this.isActiveMarkerIndex].height = '40rpx';
+					this.markersIn[this.isActiveMarkerIndex].iconPath = '../../static/icon/late02.png';					
+				}
+				this.isActiveMarkerIndex = index;
+				this.innerGeo = {
+					latitude: this.markersIn[this.isActiveMarkerIndex].latitude,
+					longitude: this.markersIn[this.isActiveMarkerIndex].longitude
+				}
+				this.painter.wait = 1;
+				this.painter.base.views[1].src = this.markersIn[this.isActiveMarkerIndex].activeIconPath				
+			},
+			canvasSuccess(e){
+				if(this.isActiveMarkerIndex == -1)return;
+				this.markersIn[this.isActiveMarkerIndex].width = '82rpx';
+				this.markersIn[this.isActiveMarkerIndex].height = '90rpx';
+				this.markersIn[this.isActiveMarkerIndex].iconPath = e;
+				this.markersIn = Object.assign(this.markersIn);
+				this.painter.wait=0
+				uni.vibrateShort({
+					success: function () {
+						console.log('success');
+					}
+				});
+				this.updateMode&&this.$emit('moveToMarkId',this.isActiveMarkerIndex);
+			},
+			canvasFail(){
+				if(this.isActiveMarkerIndex == -1)return;
+				this.markersIn[this.isActiveMarkerIndex].width = '82rpx';
+				this.markersIn[this.isActiveMarkerIndex].height = '90rpx';
+				this.markersIn[this.isActiveMarkerIndex].iconPath = "";
+				this.markersIn = Object.assign(this.markersIn);
+				this.painter.wait=0
+				uni.vibrateShort({
+					success: function () {
+						console.log('fail');
+					}
+				});
+				this.updateMode&&this.$emit('moveToMarkId',this.isActiveMarkerIndex);
 			},
 			//点击定位标时触发,e.detail = {longitude, latitude}
 			anchorpointtap(e) {
@@ -208,6 +207,12 @@
 					})
 				},
 			},
+			'geo':{
+				handler(v){
+					this.latitude = v.latitude
+					this.longitude = v.longitude
+				}
+			}
 		}
 	}
 </script>

+ 33 - 76
pages/map/map.vue

xqd xqd xqd xqd xqd xqd xqd xqd xqd xqd
@@ -102,10 +102,10 @@
 
 		</view>
 		<view class="address">
-			<view style="height:1232rpx;">
-				<hch-position ref="map" :markers="hotelList" @moveToMarkId="moveToMarkId"/>
+			<view style="height:1300rpx;">
+				<hch-position ref="map" :markers="hotelList" :geo="geo" @moveToMarkId="moveToMarkId"/>
 			</view>
-			<view class="address-nav" style="overflow-x: visible; height:159px;">
+			<view class="address-nav" style="overflow-x: visible; height:318rpx;">
 				<!-- 遮挡地图修正 
 				<view class="address-nav-btn">
 					<view class="" @click="goLocation">
@@ -120,47 +120,10 @@
 					style="width: 100%; overflow-x: scroll; display: none;align-items: center;justify-content: space-between;">	
 				</view>
 				<!-- @scroll="bottomScroll" -->
-				<scroll-view style="width: calc(100% + 16px);height:159px;white-space: nowrap;margin-left: -8px;z-index:10" 
-					@scrolltolower="scrollTolower(hotelList.length-1)" 
-					@scrolltoupper="scrollTolower(0)"
-					@scroll="bottomScroll"
-					:scroll-x="true" 
-					:scroll-left="scrolls.scrollX" 
-					:scroll-with-animation="true"
-					:show-scrollbar="false"
-				>
-					<view style="width: 8px;display: inline-block;"></view>
-					<view class="address-detail" v-for="(item,index) in hotelList" :key="index">
-						<view class="mark" style="overflow: hidden;">
-							<image :src="item.bg_img" mode="aspectFill"></image>
-						</view>
-						<view class="inner">
-							<view class="address-detail-main">
-								<view class="address-detail-main-left">
-									<text class="title">{{item.name}}</text>
-									<view class="content" :style="{opacity: item.label?1:0}">
-										<template v-if="item.label">
-											<text v-for="(v,k) in item.label.split(',')" :key="k">{{v}}</text>
-										</template>
-									</view>
-									<view class="bottom" :style="{opacity: item.min_price?1:0}">
-										<text class="bottom-left">¥</text>
-										<text class="bottom-right">{{item.min_price}}起</text>
-									</view>
-								</view>
-								<view class="address-detail-main-right" @click="goBook(index)">
-									<text>预订</text>
-								</view>
-							</view>
-							<view class="address-detail-position" v-if="item.distanceToMe">
-								<image style="width: 18rpx;height: 22rpx;" src="/static/icon/address02.png" mode="">
-								</image>
-								<text style="margin-left:4rpx ;">{{item.distanceToMe}}km</text>
-							</view>
-						</view>
-					</view>
-					<view style="width: 1px;display: inline-block;"></view>
-				</scroll-view>
+				<view style="width: calc(100% + 32rpx);margin-left: -16rpx;z-index:10">
+					<scroll-hotel ref="scrollHotel" :hotelList="hotelList" @updateIndex="updateMapIndex"/>
+				</view>
+				
 				<view class="address-nav-button" @click="goLocation">
 					<image style="width: 84rpx;height: 84rpx;" src="/static/icon/location.png" mode=""></image>
 				</view>
@@ -222,11 +185,13 @@
 	import TabBar from '../../components/TabBar/tabbar.vue'
 	import HchPosition from '../../components/hch-position/hch-position.vue'
 	import MyNav from "@/components/my-nav/my-nav.vue"
+	import scrollHotel from "./scrollHotel.vue"
 	export default {
 		components: {
 			TabBar,
 			HchPosition,
-			MyNav
+			MyNav,
+			scrollHotel
 		},
 		data() {
 			return {
@@ -236,8 +201,12 @@
 				//门店在地图上的标记 以下字段必填
 				markers: [],
 				//经纬度
-				latitude:'',
-				longitude:'',
+				geo:{
+					latitude: 30.6034799,
+					longitude: 104.1132550,
+				},
+				latitude: 30.6034799,
+				longitude: 104.1132550,
 				//暂无数据
 				status: 'noMore',
 				contentText: {
@@ -305,6 +274,9 @@
 			})
 		},
 		methods: {
+			touchMove(e){
+				console.log(e)
+			},
 			syncSearchInput(e){
 				this.search.text = e
 			},
@@ -361,10 +333,11 @@
 				let _this = this
 				uni.getLocation({
 					type: "gcj02", //返回可以用于wx.openLocation的经纬度
-					success: function(res) {
-						_this.latitude = res.latitude
-						_this.longitude = res.longitude
-						_this.$refs.map.goLocation(res.latitude,res.longitude)
+					success: (res) => {
+						this.geo = Object.assign({
+							latitude: res.latitude + Math.random()/100000,
+							longitude: res.longitude
+						})
 					},
 					fail: function(res) {
 						console.log(res)
@@ -457,25 +430,10 @@
 								id:item.id,
 								latitude: item.latitude,
 								longitude: item.longitude,
-								width:'34rpx',
-								height:'40rpx',
-								iconPath:'../../static/icon/late02.png' ,
-								active: {
-									width: '90rpx',
-									height: '100rpx',
-									iconPath: item.logo,
-								},
-								noActive:{
-									width:'34rpx',
-									height:'40rpx',
-									iconPath:'../../static/icon/late02.png' ,
-								},
-								callout1: {
-									content:item.name,
-									borderRadius: 10,
-									padding: 10,
-									display: "ALWAYS",
-								},
+								iconPath: '../../static/icon/late02.png',
+								activeIconPath: item.logo,
+								width: '34rpx',
+								height: '40rpx',
 							}
 						}
 					})
@@ -492,7 +450,7 @@
 					}
 					setTimeout(()=>{
 						if(!this.beginConfig.hotel_id){
-							this.$refs.map.markertap({markerId: this.hotelList[0].id,index:0},true,this.search.isSearch)
+							this.$refs.map.markertap(0,true,this.search.isSearch)
 							this.beginConfig.hotel_id = 0
 							this.search.isSearch = false
 						}else{	
@@ -545,11 +503,7 @@
 			},
 			//下面酒店位移
 			moveToMarkId(index){
-				this.scrollData.spa = true;
-				this.scrolls.scrollX = (256 * index) - (this.screenWidth-256)/2 + 'px';
-				setTimeout(()=>{
-					this.scrollData.spa = false
-				},500)
+				this.$refs.scrollHotel.setActiveIndex(index);
 			},
 			localToMark(markId,index){
 				// this.moveToMarkId(markId)
@@ -566,6 +520,9 @@
 					this.scrollData.spa = false;
 				}, 300)
 			}, 
+			updateMapIndex(index){
+				this.$refs.map.markertap(index, false)
+			},
 			moveToTabX(e){
 				this.scrollData.spa = true;
 				this.scrolls.scrollX = (256 * this.scrollData.activeIndex+1) - (this.screenWidth-256)/2 + 'px';

+ 298 - 0
pages/map/scrollHotel.vue

xqd
@@ -0,0 +1,298 @@
+<template>
+	<view style="width:100%;overflow:hidden">
+	<view class="scroll-hotel" 
+		@touchstart="touchStart"
+		@touchmove="touchMove"
+		@touchend="touchEnd"
+		@touchcancel="touchEnd"
+		:style="{transform: scrollX,width: totalWidth+'rpx'}"
+	>
+		<view style="width: 16rpx;display: inline-block;"></view>
+		<view class="address-detail" v-for="(item,index) in hotelList" :key="index">
+			<view :class="{mark:true, on:index == -activeIndex}" style="overflow: hidden;">
+				<image :src="item.bg_img" mode="aspectFill"></image>
+			</view>
+			<view class="inner">
+				<view class="address-detail-main">
+					<view class="address-detail-main-left">
+						<text class="title">{{item.name}}</text>
+						<view class="content" :style="{opacity: item.label?1:0}">
+							<template v-if="item.label">
+								<text v-for="(v,k) in item.label.split(',')" :key="k">{{v}}</text>
+							</template>
+						</view>
+						<view class="bottom" :style="{opacity: item.min_price?1:0}">
+							<text class="bottom-left">¥</text>
+							<text class="bottom-right">{{item.min_price}}起</text>
+						</view>
+					</view>
+					<view class="address-detail-main-right" @click="goBook(index)">
+						<text>预订</text>
+					</view>
+				</view>
+				<view class="address-detail-position" v-if="item.distanceToMe">
+					<image style="width: 18rpx;height: 22rpx;" src="/static/icon/address02.png" mode="">
+					</image>
+					<text style="margin-left:4rpx ;">{{item.distanceToMe}}km</text>
+				</view>
+			</view>
+		</view>
+		<view style="width: 16rpx;display: inline-block;"></view>
+	</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name:"scroll-hotel",
+		props:{
+			hotelList:{
+				type: Array,
+				required: true
+			},
+			speed: {
+				type: Number,
+				default: 2
+			}
+		},
+		data(){
+			return {
+				scrolls:{
+					screenWidth: 0,
+					scrollX: 0,
+					itemWidth: 512,
+					isAppend: false,
+				},
+				move:{
+					oldX: 0,
+					direct: 0,
+					isMove: false
+				}
+			}
+		},
+		computed:{
+			scrollX(){
+				return `translateX(${this.scrolls.scrollX}rpx)`;
+			},
+			totalWidth(){
+				return this.hotelList.length*this.scrolls.itemWidth;
+			},
+			maxRight(){
+				return -this.totalWidth + this.scrolls.itemWidth
+			},
+			activeIndex(){
+				return Math.floor(this.scrolls.scrollX / this.scrolls.itemWidth)
+			},
+		},
+		onReady(){
+			uni.getSystemInfo({
+				success: (res)=>{
+					const r = res.screenWidth / 750;
+					this.scrolls.screenWidth = res.screenWidth / r 
+					console.log(res.screenWidth, r, this.scrolls.screenWidth)
+				}
+			});
+		},
+		methods:{
+			touchStart(e){
+				this.move.oldX = e.touches[0].clientX;
+			},
+			touchMove(e){
+				if(this.move.isMove) return;
+				const newX = e.touches[0].clientX
+				const baseSpeed = Math.abs(newX - this.move.oldX);
+				if(baseSpeed<2) return;
+				
+				this.move.direct = newX > this.move.oldX ? 1 : -1;
+				this.move.oldX = newX;
+				const newScrollX = this.scrolls.scrollX + this.speed*baseSpeed*this.move.direct;
+				if(newScrollX > 20){
+					this.scrolls.scrollX = 20;
+				}else if(this.hotelList.length<=1 && newScrollX < this.maxRight - 20 ){
+					this.scrolls.scrollX = this.maxRight - 20;
+				}else if(this.hotelList.length>1 && newScrollX < this.maxRight  - 40 + (this.scrolls.screenWidth - this.scrolls.itemWidth-16)){
+					this.scrolls.scrollX = this.maxRight  - 40 + (this.scrolls.screenWidth - this.scrolls.itemWidth-16);
+				}else{
+					this.scrolls.scrollX = newScrollX
+				}
+				this.move.isMove = true;
+				setTimeout(()=>{
+					this.move.isMove = false;
+				}, 30)
+			},
+			touchEnd(isUpdate){
+				if(this.scrolls.scrollX > 0){
+					this.scrolls.scrollX = 0;
+				}else if(this.hotelList.length<=1 && this.scrolls.scrollX < this.maxRight){
+					this.scrolls.scrollX = this.maxRight;
+				}else if(this.hotelList.length>1 && this.scrolls.scrollX < this.maxRight + (this.scrolls.screenWidth - this.scrolls.itemWidth-16)){
+					this.scrolls.scrollX = this.maxRight  + (this.scrolls.screenWidth - this.scrolls.itemWidth-16)
+				}else{
+					if(this.activeIndex == 0){
+						this.scrolls.scrollX = 0;
+					}else if(this.activeIndex == -(this.hotelList.length - 1)){
+						this.scrolls.scrollX = this.maxRight  + (this.scrolls.screenWidth - this.scrolls.itemWidth -16)
+					}else{
+						this.scrolls.scrollX = this.activeIndex * this.scrolls.itemWidth + (this.scrolls.screenWidth - this.scrolls.itemWidth)/2
+					}
+				}
+				isUpdate && this.$emit('updateIndex', -this.activeIndex);
+			},
+			setActiveIndex(index){
+				this.scrolls.scrollX = -index * this.scrolls.itemWidth;
+				this.touchEnd(false);
+			},
+		},
+		watch:{
+			hotelList:{
+				handler(newValue){
+					this.scrolls.scrollX = 0;
+				}
+			},
+		}
+	}
+</script>
+
+<style scoped lang="scss">
+	.scroll-hotel{
+		height:318rpx;white-space: nowrap;
+		transition: transform 50ms linear;
+		
+		.address-detail {
+			display: inline-block;
+			position: relative;
+			flex: none;
+			width:496rpx;
+			height: 318rpx;
+			border-radius: 10rpx;
+			margin-right: 16rpx;
+			overflow: hidden;
+
+			&:last-child {
+				margin-right: 0rpx;
+			}
+
+			.mark{
+				height: inherit;
+				width: inherit;
+				overflow: hidden;
+				border-radius: 10rpx;
+				filter: contrast(0.5);
+				transition: 0.3s all;
+				
+				image{
+					// width: 100%;
+					height: 318rpx;
+					width: 690rpx;
+					border-radius: 10rpx;
+				}
+				
+				&.on{
+					filter: contrast(1.2)!important;
+				}
+			}
+
+			.inner {
+				width: 100%;
+				height: inherit;
+				border-radius: 10rpx;
+				position: absolute;
+				z-index: 2;
+				top: 0;
+				left: 0;
+
+				.address-detail-main {
+					position: absolute;
+					left: 0;
+					bottom: 30rpx;
+					width: 100%;
+					display: flex;
+					align-items: flex-end;
+					justify-content: space-between;
+					
+
+					.address-detail-main-left {
+						position: absolute;
+						left: 20rpx;
+
+						.title {
+							font-size: 32rpx;
+							font-weight: bold;
+							color: #FFFFFF;
+						}
+
+						.content {
+							width: 100%;
+							height: 64rpx;
+							display: flex;
+							align-items: center;
+							justify-content: flex-start;
+							flex-wrap: nowrap;
+							overflow: hidden;
+							
+							text{
+								line-height: 36rpx;
+								height: 36rpx;
+								padding: 0 10rpx;
+								/* padding: 4rpx 6rpx; */
+								font-size: 22rpx;
+								color: #ffffff;
+								background: rgba(142, 160, 166, 0.6);
+								border-radius: 17rpx;
+								margin-right: 10rpx;
+							}
+						}
+						
+
+						.bottom {
+							display: flex;
+							align-items: center;
+							justify-content: flex-start;
+
+							.bottom-left {
+								font-size: 24rpx;
+								font-weight: bold;
+								color: #ffffff;
+								margin-right: 6rpx;
+							}
+
+							.bottom-right {
+								font-size: 32rpx;
+								font-weight: bold;
+								color: #ffffff;
+							}
+						}
+					}
+
+					.address-detail-main-right {
+						position: absolute;
+						right: 24rpx;
+						width: 120rpx;
+						height: 44rpx;
+						background: #FF6300;
+						box-shadow: 0px 4rpx 8rpx 0px rgba(0, 0, 0, 0.08);
+						border-radius: 22rpx;
+						display: flex;
+						align-items: center;
+						justify-content: center;
+						color: #ffffff;
+						font-size: 28rpx;
+					}
+
+				}
+
+				.address-detail-position {
+					position: absolute;
+					top: 22rpx;
+					right: 24rpx;
+					display: flex;
+					align-items: center;
+					justify-content: center;
+					font-weight: 500;
+					color: #FFFFFF;
+					font-size: 20rpx;
+				}
+			}
+		}
+	}
+</style>

+ 1 - 1
setting.js

xqd
@@ -1,7 +1,7 @@
 /**
  * Created by JianJia.Zhou<jianjia.zhou> on 2022/3/18.
  */
-const IS_DEV = process.env.NODE_ENV === 'development'
+const IS_DEV = process.env.NODE_ENV === 'development1'
 
 // const URL = 'https://t9.9026.com'
 const URL = 'https://ihg.9026.com'