[IOS] 高德地圖 不同類型 導(dǎo)航 線路規(guī)劃及展示

(文章末尾可下載源碼)

目前在試著做一個旅游類app項目,自己想加入一個功能:定位當前用戶位置务热,并能規(guī)劃出到旅游目的地的不同類型的線路及展示,界面參照拉鉤網(wǎng)app工作地址詳情頁己儒,采用高德地圖的接口崎岂,琢磨下高德地圖的demo,實現(xiàn)起來挺容易闪湾,直接上圖:

2017-06-11 22.51.20.gif

1.集成高德地圖

首先要集成高德地圖冲甘,需要在高德地圖官網(wǎng)申請高德地圖的開發(fā)者賬號,然后導(dǎo)入其第三方庫等步驟途样,可以參考http://www.reibang.com/p/bc9462f9c1e9江醇。

2.顯示用戶位置及目的地展示

通過第一步,地圖應(yīng)該能顯示出來了(高興)何暇,接下來就是在地圖上顯示出我們需要的信息陶夜,首先是目的地展示(這里我采用大頭針來顯示目的地),以及當前定位當前用戶裆站,使用高德地圖的第三方庫也都幾句代碼的事条辟,官方文檔也有說明這里也不多說直接上代碼:
地圖初始化完成后的方法中

_mapView.centerCoordinate=CLLocationCoordinate2DMake(self.ampDistancePoint.latitude,self.ampDistancePoint.longitude);//定位中心點
_mapView.zoomLevel=16.5;//地圖縮放級別
_mapView.showsUserLocation = YES;  //顯示定位藍點

在這里要說一下大頭針,大頭針也可以參考高德地圖中的點標記繪制來進行自定義宏胯,在viewDidAppear中

    MAPointAnnotation *pointAnnotation = [[MAPointAnnotation alloc] init];
    pointAnnotation.coordinate = CLLocationCoordinate2DMake(self.ampDistancePoint.latitude,self.ampDistancePoint.longitude);
    pointAnnotation.title = self.model.name; //大頭針
    [_mapView addAnnotation:pointAnnotation];

然后 實現(xiàn) <MAMapViewDelegate> 協(xié)議中的 mapView:viewForAnnotation:回調(diào)函數(shù)羽嫡,設(shè)置標注樣式

- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id <MAAnnotation>)annotation
{
    if ([annotation isKindOfClass:[MAPointAnnotation class]])
    {
        static NSString *pointReuseIndentifier = @"pointReuseIndentifier";
        MAPinAnnotationView*annotationView = (MAPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndentifier];
        if (annotationView == nil)
        {
            annotationView = [[MAPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndentifier];
        }
        annotationView.canShowCallout= YES;       //設(shè)置氣泡可以彈出,默認為NO
        annotationView.animatesDrop = YES;        //設(shè)置標注動畫顯示肩袍,默認為NO
        annotationView.draggable = YES;        //設(shè)置標注可以拖動厂僧,默認為NO
        annotationView.pinColor = MAPinAnnotationColorPurple;
        return annotationView;
    }
    return nil;
}

3.不同類型路線規(guī)劃

關(guān)于路線規(guī)劃,主要參照了官方demo了牛,使用AMapSearchAPI類,發(fā)起路線規(guī)劃請求颜屠,駕車和步行的路線規(guī)劃區(qū)別不大,公共交通出行路線倒是有點不同鹰祸。

3.1駕車路線規(guī)劃發(fā)起

在這里我自定義了一個路線類型屬性甫窟,1為駕車,2為公共交通蛙婴,3為步行粗井。這樣做的用意,大家后面就知道了。

-(void)driveNav{
   
   routeType=1;//自定義的路線類型浇衬,1為駕車懒构,2為公共交通,3為步行
   AMapDrivingRouteSearchRequest *navi = [[AMapDrivingRouteSearchRequest alloc] init];
   navi.requireExtension = YES;//是否返回擴展信息耘擂,默認為 NO
   navi.strategy = 5;// 駕車導(dǎo)航策略([default = 0]) 0-速度優(yōu)先(時間)胆剧;1-費用優(yōu)先(不走收費路段的最快道路);2-距離優(yōu)先醉冤;3-不走快速路秩霍;4-結(jié)合實時交通(躲避擁堵);5-多策略(同時使用速度優(yōu)先蚁阳、費用優(yōu)先铃绒、距離優(yōu)先三個策略);6-不走高速螺捐;7-不走高速且避免收費颠悬;8-躲避收費和擁堵;9-不走高速且躲避收費和擁堵
   /* 出發(fā)點. */
   navi.origin = [AMapGeoPoint locationWithLatitude:_mapView.userLocation.location.coordinate.latitude
                                          longitude:_mapView.userLocation.location.coordinate.longitude];
   /* 目的地. */
   navi.destination =self.ampDistancePoint;
   [self.search AMapDrivingRouteSearch:navi];//駕車路線規(guī)劃
}

3.2公共交通路線規(guī)劃發(fā)起

公共交通不一樣的點主要是多了一個city屬性定血,必須要讓高德地圖知道是哪個城市的公共交通路線椿疗。

-(void)busNav{
    routeType=2;
    AMapTransitRouteSearchRequest *navi = [[AMapTransitRouteSearchRequest alloc] init];
    navi.requireExtension = YES;
    navi.strategy = 4;//公交換乘策略([default = 0])0-最快捷模式;1-最經(jīng)濟模式糠悼;2-最少換乘模式;3-最少步行模式浅乔;4-最舒適模式倔喂;5-不乘地鐵模式
    navi.city =@"chongqing";
    /* 出發(fā)點. */
    navi.origin = [AMapGeoPoint locationWithLatitude:_mapView.userLocation.location.coordinate.latitude
                                           longitude:_mapView.userLocation.location.coordinate.longitude];
    /* 目的地. */
    navi.destination =self.ampDistancePoint;
    [self.search AMapTransitRouteSearch:navi];//公共交通路線規(guī)
}

3.3步行路線規(guī)劃發(fā)起

步行路線和駕車大致相同

-(void)WalkNav{
    routeType=3;
    AMapWalkingRouteSearchRequest *navi = [[AMapWalkingRouteSearchRequest alloc] init];
    /* 出發(fā)點. */
    navi.origin = [AMapGeoPoint locationWithLatitude:_mapView.userLocation.location.coordinate.latitude
                                           longitude:_mapView.userLocation.location.coordinate.longitude];
    /* 目的地. */
    navi.destination = self.ampDistancePoint;
    [self.search AMapWalkingRouteSearch:navi];
}

4路徑規(guī)劃搜索回調(diào)

通過AMapSearchAPI類向服務(wù)器發(fā)起路線規(guī)劃請求后,如規(guī)劃成功則跳到onRouteSearchDone方法,response靖苇,包含類路線的所有信息耗時席噩,距離,換乘等等贤壁,否則跳轉(zhuǎn)到- (void)AMapSearchRequest:(id)request didFailWithError:(NSError *)error方法中悼枢,并附帶出錯原因。

在這里我使用了預(yù)加載的模式脾拆,在用戶跳轉(zhuǎn)到本界面時馒索,就自動發(fā)起多有類型路線的規(guī)劃,等所有路線類型都規(guī)劃完畢后名船,用戶才能查看各種類型的導(dǎo)航路線绰上。預(yù)加載可以讓用戶對三種路線規(guī)劃耗時一目了然,增強用戶體驗渠驼。
在預(yù)加載這里有一個問題蜈块,如果同時發(fā)起三種類型的路線規(guī)劃請求,將會收到三次回調(diào),但是由于異步的關(guān)系百揭,就不能知道哪次回調(diào)對應(yīng)著的是哪種類型的路線規(guī)劃請求爽哎。

所以在這里我用了一個笨方法,先發(fā)起步行路線規(guī)劃器一,等收到回調(diào)后再發(fā)起公共交通路線規(guī)劃课锌,用routeType屬性可以知道當前是哪種類型請求的回調(diào),再發(fā)起駕車路線規(guī)劃盹舞,等駕車路線規(guī)劃收到回調(diào)产镐,那么所有路線加載完畢,則隱藏小菊花踢步,用戶也就能查看到各種類型的導(dǎo)航路線了癣亚。

/* 路徑規(guī)劃搜索回調(diào). */
- (void) onRouteSearchDone:(AMapRouteSearchBaseRequest *)request response:(AMapRouteSearchResponse *)response
{
    if (response.route == nil)
    {
        return;
    }
    /* 預(yù)加載*/
    if (routeType==1) {
        self.driveRoute=response.route;
        self.driveDration.text=[self timeFomart: response.route.paths[0].duration];//預(yù)計用時
        [MBProgressHUD hideHUDForView:self.navView animated:YES];//隱藏菊花
        self.distance.text =[self disFormat:self.driveRoute.paths[0].distance];//顯示距離
        [self isHideNavView:false];//顯示控件
    }
    if (routeType==2) {
        self.busRoute=response.route;
        if (response.route.transits!=nil && response.route.transits.count!=0) {
            if(response.route.transits.lastObject!=nil){
                self.busDration.text=[self timeFomart:response.route.transits[0].duration];
            }
        }else{
            self.busDration.text=@"暫無";
            self.busBtn.enabled=false;
        }
        [self driveNav];
    }
    if (routeType==3) {
        self.walkRoute=response.route;
        if (response.route.paths!=nil) {
            self.walkDration.text=[self timeFomart: response.route.paths[0].duration];
        }
        else{
            self.walkDration.text=@"暫無";
            self.walkBtn.enabled=false;
        }
        [self busNav];
    }
    self.route = response.route;
    self.currentCourse = 0;
}

如若出錯,應(yīng)該就是網(wǎng)絡(luò)不好訪問超時获印,要么就是超過距離述雾,如超過了市區(qū)的公交線路導(dǎo)航,或其他原因系統(tǒng)無法規(guī)劃出路線兼丰,那么則在出錯處理中根據(jù)不同的類型進行錯誤的處理玻孟,并在此發(fā)起下一個類型的線路規(guī)劃請求,在這里為了方便鳍征,出錯的類型直接顯示暫無= =黍翎。
//出錯處理

- (void)AMapSearchRequest:(id)request didFailWithError:(NSError *)error
{
    if (routeType==1) {
        self.driveDration.text=@"暫無";
        self.carBtn.enabled=false;
    }
    if (routeType==2) {
        self.busDration.text=@"暫無";
        self.busBtn.enabled=false;
        [self driveNav];
    }
    if (routeType==3) {
        self.walkDration.text=@"暫無";
        self.walkBtn.enabled=false;
        [self busNav];
    }

5解析路線及路線的繪制

路線的解析以及路線的繪制,如用戶查看駕車路線時艳丛,直接解析已預(yù)加載好的路線規(guī)劃匣掸,然后再進行路線的繪制即可,在這里我直接是用的官方demo里的代碼氮双,僅僅根據(jù)自己的需求及界面的美觀小小的修改了一下碰酝。
路線的解析,注意有些類是demo中封裝好的戴差,非官方庫中的送爸。
注意:要先清楚地圖上的所有繪制

//清理繪制路線
- (void)clear
{
    [self.naviRoute removeFromMapView];
}

點擊駕車路線規(guī)劃圖標:

- (IBAction)drivingBtn:(id)sender {
    [self clear];
    routeType=1;
    self.distance.text =[self disFormat:self.driveRoute.paths[0].distance];
    [self presentCurrentCourse];//路線解析
}
//根據(jù)不同導(dǎo)航類型解析不同路線
- (void)presentCurrentCourse
{
    MANaviAnnotationType type = MANaviAnnotationTypeDrive;
    if (routeType==1) {
        type = MANaviAnnotationTypeDrive;
        self.naviRoute = [MANaviRoute naviRouteForPath:self.driveRoute.paths[self.currentCourse] withNaviType:type showTraffic:YES startPoint:[AMapGeoPoint  locationWithLatitude:_mapView.userLocation.location.coordinate.latitude longitude:_mapView.userLocation.location.coordinate.longitude]
                                              endPoint:self.ampDistancePoint];
        [self.naviRoute addToMapView:self.mapView];

    }
    if (routeType==2) {
        self.naviRoute = [MANaviRoute naviRouteForTransit:self.busRoute.transits[self.currentCourse] startPoint:[AMapGeoPoint  locationWithLatitude:_mapView.userLocation.location.coordinate.latitude longitude:_mapView.userLocation.location.coordinate.longitude]
                                                 endPoint:self.ampDistancePoint];
        [self.naviRoute addToMapView:self.mapView];
    }
    if (routeType==3) {
        type = MANaviAnnotationTypeWalking;
        self.naviRoute = [MANaviRoute naviRouteForPath:self.walkRoute.paths[self.currentCourse] withNaviType:type showTraffic:YES startPoint:[AMapGeoPoint  locationWithLatitude:_mapView.userLocation.location.coordinate.latitude longitude:_mapView.userLocation.location.coordinate.longitude]
                                              endPoint:self.ampDistancePoint];
        [self.naviRoute addToMapView:self.mapView];

    }    
    /* 縮放地圖使其適應(yīng)polylines的展示. */
    self.naviRoute.anntationVisible=YES;
    [self.mapView showOverlays:self.naviRoute.routePolylines edgePadding:UIEdgeInsetsMake(RoutePlanningPaddingEdge, RoutePlanningPaddingEdge, RoutePlanningPaddingEdge, RoutePlanningPaddingEdge) animated:YES];    
}

路線的繪制直接照搬官方demo中的(手動斜眼)

注意:地圖的繪制分兩個部分,路線的繪制以及路線節(jié)點(Annotation)的繪制

路線的繪制

//根據(jù)不同導(dǎo)航類型繪制路線
- (MAOverlayRenderer *)mapView:(MAMapView *)mapView rendererForOverlay:(id <MAOverlay>)overlay// 任何遵循此協(xié)議的對象
{
    if ([overlay isKindOfClass:[LineDashPolyline class]])
    {
        MAPolylineRenderer *polylineRenderer = [[MAPolylineRenderer alloc] initWithPolyline:((LineDashPolyline *)overlay).polyline];
        polylineRenderer.lineWidth   = 8;
        polylineRenderer.lineDashPattern = @[@10, @15];
        polylineRenderer.strokeColor = [UIColor redColor];
        
        return polylineRenderer;
    }
    if ([overlay isKindOfClass:[MANaviPolyline class]])
    {
        MANaviPolyline *naviPolyline = (MANaviPolyline *)overlay;
        MAPolylineRenderer *polylineRenderer = [[MAPolylineRenderer alloc] initWithPolyline:naviPolyline.polyline];
        
        polylineRenderer.lineWidth = 8;
        
        if (naviPolyline.type == MANaviAnnotationTypeWalking)
        {
            polylineRenderer.strokeColor = self.naviRoute.walkingColor;
        }
        else if (naviPolyline.type == MANaviAnnotationTypeRailway)
        {
            polylineRenderer.strokeColor = self.naviRoute.railwayColor;
        }
        else
        {
            polylineRenderer.strokeColor = self.naviRoute.routeColor;
        }        
        return polylineRenderer;
    }
    if ([overlay isKindOfClass:[MAMultiPolyline class]])
    {
        MAMultiColoredPolylineRenderer * polylineRenderer = [[MAMultiColoredPolylineRenderer alloc] initWithMultiPolyline:(MAMultiPolyline *)overlay];
        polylineRenderer.lineWidth = 8;
        polylineRenderer.strokeColors = [self.naviRoute.multiPolylineColors copy];
        polylineRenderer.gradient = YES;
        return polylineRenderer;
    }
    return nil;
}  

路線節(jié)點的繪制

//根據(jù)導(dǎo)航類型繪制覆蓋物
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id <MAAnnotation>)annotation
{  
    if ([annotation isKindOfClass:[MAPointAnnotation class]])
    {        
        static NSString *routePlanningCellIdentifier = @"RoutePlanningCellIdentifier";        
        MAAnnotationView *poiAnnotationView = (MAAnnotationView*)[self.mapView dequeueReusableAnnotationViewWithIdentifier:routePlanningCellIdentifier];
        if (poiAnnotationView == nil)
        {
            poiAnnotationView = [[MAAnnotationView alloc] initWithAnnotation:annotation
                                                             reuseIdentifier:routePlanningCellIdentifier];
        }        
        poiAnnotationView.canShowCallout = YES;
        poiAnnotationView.image = nil;               
        if ([annotation isKindOfClass:[MANaviAnnotation class]])
        {
            switch (((MANaviAnnotation*)annotation).type)
            {
                case MANaviAnnotationTypeRailway:
                    poiAnnotationView.image = [UIImage imageNamed:@"railway_station"];
                    break;                    
                case MANaviAnnotationTypeBus:
                    poiAnnotationView.image = [UIImage imageNamed:@"bus"];
                    break;                    
                case MANaviAnnotationTypeDrive:
                    poiAnnotationView.image = [UIImage imageNamed:@"car"];
                    break;                    
                case MANaviAnnotationTypeWalking:
                    poiAnnotationView.image = [UIImage imageNamed:@"man"];
                    break;               
                default:
                    break;
            }
        }
        else
        {
            /* 起點. */   //繪制起點的紅色大頭針在這里哦
            if ([[annotation title] isEqualToString:self.model.name])
            {
                    static NSString *pointReuseIndentifier = @"pointReuseIndentifier";
                    MAPinAnnotationView *annotationView = (MAPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndentifier];
                    if (annotationView == nil)
                    {
                        annotationView = [[MAPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndentifier];
                    }
                    annotationView.canShowCallout= YES;       //設(shè)置氣泡可以彈出暖释,默認為NO
                    annotationView.animatesDrop = YES;        //設(shè)置標注動畫顯示袭厂,默認為NO
                    annotationView.draggable = YES;        //設(shè)置標注可以拖動,默認為NO
                    annotationView.pinColor = MAPinAnnotationColorRed;
                    return annotationView;
            }
        }
        return poiAnnotationView;
    }
    return nil;
}

6其他

還有些邊角代碼:如時間格式轉(zhuǎn)換球匕,距離格式轉(zhuǎn)換嵌器,string類型的經(jīng)緯度轉(zhuǎn)換等也一并獻上吧,

-(AMapGeoPoint *)pointFormat:(NSString *)point{
    //經(jīng)緯度格式轉(zhuǎn)換
    NSArray *arry= [point componentsSeparatedByString:@","];
    double p2=((NSString *)arry[0]).doubleValue;
    double p1=((NSString *)arry[1]).doubleValue;
    return [AMapGeoPoint locationWithLatitude:CLLocationCoordinate2DMake(p1,p2).latitude
                                    longitude:CLLocationCoordinate2DMake(p1,p2).longitude];
}
//距離格式轉(zhuǎn)換
-(NSString *)disFormat:(double)meters {
    double intDistance=(int)round(meters);
    return [NSString stringWithFormat:@"距離:%0.2fKM",intDistance/1000 ];
}
//時間格式轉(zhuǎn)換
-(NSString *)timeFomart:(double)duration{
    return [NSString stringWithFormat:@"%0.0f分鐘",duration/60];
}
//笨方法谐丢,隱藏加載中的控件
-(void)isHideNavView:(BOOL) ishide{
    self.busBtn.hidden=ishide;
    self.busDration.hidden=ishide;
    self.driveDration.hidden=ishide;
    self.carBtn.hidden=ishide;
    self.walkDration.hidden=ishide;
    self.walkBtn.hidden=ishide;
}

項目demo開源在github歡迎Star(害羞#)

注:需手動導(dǎo)入AmpFrameworks
https://github.com/calvinWen/AmpDemo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末爽航,一起剝皮案震驚了整個濱河市蚓让,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌讥珍,老刑警劉巖历极,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異衷佃,居然都是意外死亡趟卸,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進店門氏义,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锄列,“玉大人,你說我怎么就攤上這事惯悠×谟剩” “怎么了?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵克婶,是天一觀的道長筒严。 經(jīng)常有香客問我,道長情萤,這世上最難降的妖魔是什么鸭蛙? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮筋岛,結(jié)果婚禮上娶视,老公的妹妹穿的比我還像新娘。我一直安慰自己睁宰,他們只是感情好肪获,可當我...
    茶點故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著勋陪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪硫兰。 梳的紋絲不亂的頭發(fā)上诅愚,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天,我揣著相機與錄音劫映,去河邊找鬼违孝。 笑死,一個胖子當著我的面吹牛泳赋,可吹牛的內(nèi)容都是我干的雌桑。 我是一名探鬼主播,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼祖今,長吁一口氣:“原來是場噩夢啊……” “哼校坑!你這毒婦竟也來了拣技?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤耍目,失蹤者是張志新(化名)和其女友劉穎膏斤,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體邪驮,經(jīng)...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡莫辨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了毅访。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沮榜。...
    茶點故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖喻粹,靈堂內(nèi)的尸體忽然破棺而出蟆融,到底是詐尸還是另有隱情,我是刑警寧澤磷斧,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布振愿,位于F島的核電站,受9級特大地震影響弛饭,放射性物質(zhì)發(fā)生泄漏冕末。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一侣颂、第九天 我趴在偏房一處隱蔽的房頂上張望档桃。 院中可真熱鬧,春花似錦憔晒、人聲如沸藻肄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嘹屯。三九已至,卻和暖如春从撼,著一層夾襖步出監(jiān)牢的瞬間州弟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工低零, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留婆翔,地道東北人。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓掏婶,卻偏偏與公主長得像啃奴,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子雄妥,可洞房花燭夜當晚...
    茶點故事閱讀 43,554評論 2 349

推薦閱讀更多精彩內(nèi)容