效果图:
未处理城市数据:
html部分:
header 搜索栏部分:
<ion-header>
<ion-navbar>
</ion-navbar>
<ion-searchbar class="searchBox" placeholder="请输入城市拼音或汉字" (ionInput)="getItems($event)"></ion-searchbar>
<div class="flexContainer current align_center">
<div class="f1 city">
目前所选定位:<span #containermap (tap)="citySelect(curPos)">{{curPos}}</span>
</div>
<div class="flex">
<div class="row_end reset" (tap)="getPosition()">重新定位 </div>
<div class="resetPos" (tap)="citySelect(resetPosition)">{{resetPosition}}</div>
</div>
</div>
</ion-header>
content部分: 主要是显示全部城市列表和经过搜索后过滤出来的列表
<ion-content>
<div class="citiesBox">
<div class="left_city" #left_city>
<div class="recent_title" *ngIf="cacheSearchCity">最近访问</div>
<div class="recent" *ngIf="cacheSearchCity">
<span *ngFor="let his of cacheSearchCity" tappable (click)="citySelect(his)">{{his.name}}</span>
</div>
<div class="recent_title">已入驻城市</div>
<div #list>
<ion-list >
<!--搜索过滤的数组-->
<ion-item-sliding *ngFor="let c of filteredCities">
<ion-item tappable (click)="citySelect(c)">{{c.name}}</ion-item>
</ion-item-sliding>
<!--全部城市数组-->
<ion-item-group *ngFor="let item of cities" #cityGroup>
<ion-item-divider>
<ion-label class="index_title">{{item.index}}</ion-label>
</ion-item-divider>
<ion-item *ngFor="let c of item.cities" (tap)="citySelect(c)">{{c.name}}</ion-item>
</ion-item-group>
</ion-list>
</div>
</div>
</div>
</ion-content>
footer部分: A~Z的字母索引
<ion-footer>
<div id="indexs-bar" class="right_indexes">
<div class="index-bar"
*ngFor="let item of rightIndexes;let i = index"
(touchstart)="IndexTouchStart($event)"
id="item"
>{{item}}</div>
</div>
</ion-footer>
ts部分:
import { Component , ViewChild ,ElementRef , ViewChildren, Renderer2} from '@angular/core';
import { IonicPage, NavController, NavParams , Content, Events } from 'ionic-angular';
import { Storage } from '@ionic/storage';
import { NativeService } from '../../services/native.service';
import { RestService } from '../../services/rest.services';
import Bscroll from 'better-scroll';
@IonicPage()
@Component({
selector: 'page-location',
templateUrl: 'location.html',
})
export class LocationPage{
@ViewChild(Content) content: Content;
@ViewChildren('cityGroup') cityGroup;
@ViewChildren('list') list:ElementRef;
@ViewChild("containermap") containermap: ElementRef;
curPos:string = ""; //当前定位
cities: Array<any> = []; //城市数组
oriCities: Array<any> = []; //城市数组--接口返回值
filteredCities: Array<any> = []; //过滤城市数组
cacheSearchCity:Array<any>=[];//历史搜索
resetPosition:string="";
public scroll;
//右侧字母排序数组
rightIndexes = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
constructor(
public navCtrl: NavController,
public navParams: NavParams,
public nativeService: NativeService,
public storage: Storage,
public ele: ElementRef,
public r2: Renderer2,
public restService: RestService,
public events: Events,
) {
this.curPos = this.navParams.data.curPosition;
this.storage.get("city_history").then(cacheCity=>{
this.cacheSearchCity = cacheCity;
});
}
ionViewDidLoad() {
this.storage.get("citydata")
.then(data=>{
if(data){
this.cities = this.getGroupCities(data);
this.oriCities = data;
}else{
this.restService.locationCity()
.subscribe((citisArr:any)=>{
console.log(citisArr)
this.oriCities = citisArr.body.cities;
this.cities = this.getGroupCities(this.oriCities);
this.storage.set("citydata",this.oriCities);
})
}
})
}
ionViewDidEnter(){
this.scroll = new Bscroll(this.content.getNativeElement().children[1]);
}
/*
* 重新定位
* @memberof LocationPage
*/
getPosition(){
this.resetPosition = "定位中...";
this.getResetPos().then((data:string)=>{
this.resetPosition = data;
},(err)=>{
this.resetPosition = "定位失败";
})
}
getResetPos(){
return new Promise((resolve,reject)=>{
(<any>window).GaoDe.getCurrentPosition((successData)=>{
resolve(successData.city)
}, (faileData)=>{
reject("定位失败");
});
})
}
IndexTouchStart(ev){
this.alphabetMove(ev, true);
}
/**
*
* 滚动效果
* @param {*} e
* @param {*} move
* @returns
* @memberof LocationPage
*/
alphabetMove(e, move) {
let currentItem;
currentItem = e.target;
if (!currentItem || currentItem.className.indexOf('index-bar') < 0) return;
if (move) {
let index = this.rightIndexes.join('').indexOf(currentItem.innerText);
let scrollHeight = this.cityGroup._results[index].nativeElement.offsetTop;
this.content.scrollTo(this.content.contentTop,scrollHeight-5,300);
}
}
/**
* 城市分组排序
*/
getGroupCities(cities){
var group = [];
this.rightIndexes.forEach(c => {
let cCities = cities.filter(cityItem=>cityItem.index===c);
group.push({
index:c,
cities:cCities
})
});
return group;
}
/**
* 点击选择搜索的城市
* @param city 选择的城市
*/
citySelect(city) {
this.storage.get("city_history").then((cities:any)=>{
if(cities == null) cities = [];
cities.forEach((element,index) => {
if(city.name == element.name){
cities.splice(index,1);
}
});
if(cities.length >=3){
cities.pop();
cities.unshift(city);
this.storage.set("city_history",cities);
this.cacheSearchCity = cities;
}else{
cities.unshift(city);
this.storage.set("city_history",cities);
this.cacheSearchCity = cities;
}
this.navCtrl.pop();
this.events.publish("select_postion",city);
})
}
/**
*城市搜索
*
* @memberof LocationPage
*/
getItems(ev){
var newVal = ev.target.value;
if (newVal) {
this.filteredCities = this.filterCities(newVal);
}
else {
this.filteredCities = [];
}
this.content.scrollToTop(500);
}
/**
*过滤符合条件的城市
*
* @param {*} val
* @memberof LocationPage
*/
filterCities(val){
var filterCities = [];
this.oriCities.filter(item=>{
if(item.name.indexOf(val)>-1){
filterCities.push(item);
}
})
return filterCities;
}
/**
* 选择当前定位,返回首页
*/
comfirmCurPostion(){
this.navCtrl.pop();
}
}
css:
page-location {
background: transparent;
.searchbar-ios.searchBox{
background: #fff;
border: 0;
input{
background-color: #f3f3f3 ;
border-radius: .5rem ;
}
}
.searchbar-ios.searchBox .searchbar-search-icon{
top: .2rem ;
width: .4rem ;
height: .3rem ;
background-size: .4rem .36rem ;
}
.reset {
background: url("../assets/imgs/zhinz.png") #fff right center no-repeat;
background-size: .24rem;
padding-right: .3rem;
color: #999;
font-size: .26rem;
margin: .2rem 0 .05rem 0;
}
.resetPos{
margin-left: 30%;
}
.current {
padding: .22rem;
background-color: #fff;
min-height: .88rem;
.city {
font-size: .26rem;
span {
font-size: .26rem;
font-weight: 200;
}
}
}
.recent_title {
height: (.68rem);
line-height: (.68rem);
font-size: .26rem;
background-color: #f3f3f3;
padding-left: .22rem;
}
.recent {
display: flex;
height: .88rem;
justify-content: center;
align-items: center;
span {
flex: 1;
text-align: center;
font-size: .24rem;
font-weight: 200;
display: inline-block;
}
}
.citiesBox{
position: absolute;
top: 0;
left: 0;
right: .6rem;
overflow-y: scroll;
.left_city{
overflow: visible;
}
}
//A-Z
.right_indexes{
position: absolute;
top: 0;
right: 0;
width: .6rem;
text-align: center;
color: #cb9e5e;
div{
cursor: pointer;
font-size: .3rem;
line-height: 1.2;
}
}
/* 列表 */
.item-divider-ios{
background: #fff;
}
.item-block{
min-height: inherit;
}
.label-ios{
font-size: .26rem;
}
.fixed-content,.scroll-content{
margin-bottom: 0 !important;
}
ion-footer{
top: (3rem);
right: 0;
left: auto;
width:.6rem;
}
}
over~