如何自己給百度地圖添加慣性縮放效果

沒錯(cuò)吁峻,這又是關(guān)于地圖方面的一篇文章,如果讀者看過我前幾篇文章的話费尽,是不是會(huì)很好奇為啥最近老是寫地圖,哈哈羊始,主要是因?yàn)樽罱恢痹诟愕貓D了旱幼,從重構(gòu)到現(xiàn)在算起來也快有一個(gè)月的時(shí)間了,基本每天到公司后的第一件事突委,就是打開地圖頁(yè)柏卤,一邊滑動(dòng)著地圖,一邊對(duì)照著代碼和官方文檔匀油,看看有哪些地方可以繼續(xù)優(yōu)化缘缚。不出意外的話,你會(huì)發(fā)現(xiàn)敌蚜,要優(yōu)化的地方桥滨,還真不少。。

之前我們已經(jīng)對(duì)地圖頁(yè)的代碼結(jié)構(gòu)進(jìn)行過優(yōu)化齐媒,并且針對(duì)特定的地圖高亮多邊形需求蒲每,提出過通用的解決方案,前幾天還給過地圖阻尼運(yùn)動(dòng)的簡(jiǎn)易實(shí)現(xiàn)方式喻括。然后我就發(fā)現(xiàn)一件事情邀杏,其實(shí)除了代碼結(jié)構(gòu)這點(diǎn),另外兩點(diǎn)双妨,包括今天要講述的地圖慣性縮放淮阐,其實(shí)都應(yīng)該是百度地圖api的事情。

只是由于種種原因刁品,百度地圖沒有提供給我們這種便利泣特,那就需要我們自力更生。

好了挑随,下面是我們今天要討論的事情状您,如何hook百度地圖的私有方法,給我們的地圖添加慣性縮放的效果兜挨。

首先膏孟,什么是地圖慣性縮放?

注意是縮放拌汇,不是移動(dòng)柒桑。
移動(dòng)是一個(gè)手指在地圖上劃過,這個(gè)是有慣性的噪舀,也就是說魁淳,你的手指離開后,地圖不會(huì)立馬停止与倡,而是會(huì)有一個(gè)逐漸減速的效果界逛。但是縮放是什么,縮放是兩個(gè)手指做捏合運(yùn)動(dòng)來改變地圖的層級(jí)纺座,這個(gè)在百度開放給我們的效果中是沒有慣性的息拜,也就是說一旦你的兩個(gè)手指離開屏幕,你的地圖會(huì)立馬停止運(yùn)動(dòng)净响,幾乎沒有什么物理世界中的慣性效果少欺。

就像是你開著車在行駛,快到家門的時(shí)候馋贤,你松開了油門狈茉,你希望你的車能夠靠著慣性走完剩下的一小段路,可是你發(fā)現(xiàn)在你松開油門的時(shí)候掸掸,你的車也立馬停止運(yùn)動(dòng)了,先不說你回不了家了,這突如其來的剎車扰付,還有可能會(huì)閃了你的老腰堤撵,導(dǎo)致你上不了床了。(好吧羽莺,我承認(rèn)实昨,一不小心開車了)

思考:如何實(shí)現(xiàn)地圖慣性縮放。

為了讓大伙不閃到腰盐固,我們需要思考怎么解決這個(gè)事情荒给。思考之前我們需要跳出百度api的束縛,單純的從數(shù)學(xué)角度來思考這個(gè)慣性運(yùn)動(dòng)的問題刁卜。

然后你就會(huì)發(fā)現(xiàn)志电,這個(gè)問題其實(shí)很簡(jiǎn)單,就是一個(gè)拋物線問題蛔趴,并且是地圖層級(jí)zoomLevel關(guān)于時(shí)間t的一元二次函數(shù)問題挑辆。

先上一張圖:

level-time拋物線.png

圖中顯示的是一條拋物線,橫軸是時(shí)間t,縱軸是對(duì)應(yīng)時(shí)間下的地圖級(jí)別孝情,其中_tPinStart是雙指剛開始接觸屏幕的時(shí)間鱼蝉,也就是剛開始縮放運(yùn)動(dòng)時(shí)候的時(shí)間,_tPinEnd是縮放運(yùn)動(dòng)結(jié)束時(shí)候的時(shí)間箫荡,對(duì)應(yīng)的_levelPinStart_levelPinEnd分別是縮放運(yùn)動(dòng)開始與結(jié)束時(shí)候的地圖層級(jí)魁亦。

對(duì)一元二次方程求導(dǎo)數(shù),可以得到對(duì)應(yīng)時(shí)間下的速率羔挡,很明顯洁奈,在A2點(diǎn),也就是在手勢(shì)離開的時(shí)候婉弹,地圖的速度_vPinEnd并不為0睬魂。

從拋物線中我們可以看到,這條曲線速率為0的時(shí)候镀赌,其實(shí)正是它的拋物線頂點(diǎn)氯哮,這個(gè)時(shí)候它對(duì)應(yīng)的點(diǎn)是圖中的AStirless點(diǎn),對(duì)應(yīng)的時(shí)間是_tStirless商佛。如果想讓地圖縮放有一個(gè)慣性效果的話喉钢,也就是說不讓它戛然而止而閃到腰,那么我們就需要在手勢(shì)移開后良姆,讓地圖的層級(jí)按照?qǐng)D中拋物線_tPinEnd_tStirless之間的運(yùn)動(dòng)軌跡變化肠虽。

原理知道了,就是一個(gè)求解拋物線的問題玛追,那么如何獲取這條拋物線的方程呢税课。

先復(fù)習(xí)下一元二次方程的通式:
y = aX^2 + bX + c

如果想求解這個(gè)方程闲延,那么我們起碼需要知道以下幾點(diǎn):

  • 捏合手勢(shì)開始時(shí)候的時(shí)間與此時(shí)對(duì)應(yīng)的地圖層級(jí),也就是A1點(diǎn)的坐標(biāo)韩玩。
  • 捏合手勢(shì)離開時(shí)候的時(shí)間與此時(shí)對(duì)應(yīng)的地圖層級(jí)垒玲,也就是A2點(diǎn)的坐標(biāo)。

現(xiàn)在假如我們知道了這兩個(gè)點(diǎn)找颓,可是兩個(gè)方程要解出a,b,c三個(gè)未知數(shù)是不可能的合愈,仔細(xì)回想一下一元二次方程的特點(diǎn),我們會(huì)發(fā)現(xiàn)二次項(xiàng)系數(shù)a的值不一般击狮,這是一個(gè)決定拋物線開口大小的參數(shù)佛析,并且參數(shù)a的絕對(duì)值越大,開口越小彪蓬,意味著曲率越大寸莫,曲率越大意味著,相同單位時(shí)間內(nèi)的y值變化越大寞焙。換句話說储狭,這個(gè)二次項(xiàng)系數(shù)是一個(gè)影響慣性大小的參數(shù),所以這個(gè)參數(shù)捣郊,我們可以自己設(shè)定辽狈。

既然二次項(xiàng)的值,可以自己設(shè)定呛牲,以便于我們控制慣性的大小刮萌,那么在知道A1點(diǎn)與A2點(diǎn)的情況下,我們就可以得到一次項(xiàng)系數(shù)b和常數(shù)項(xiàng)c的值了娘扩。

問題轉(zhuǎn)變成如何獲得捏合手勢(shì)開始與結(jié)束時(shí)候的A1點(diǎn)A2點(diǎn)坐標(biāo)着茸。

這個(gè)問題看起來比較簡(jiǎn)單,可是在百度地圖沒有直接給你的時(shí)候琐旁,就變得比較費(fèi)事了涮阔。如果你有好的方式,請(qǐng)告訴我灰殴,我相信簡(jiǎn)單的才是好的敬特。如果你還沒有找到好的方式,那么不妨繼續(xù)往下看看我是如何一步一步找到的牺陶。

  • 首先使用蘋果私有的調(diào)試工具,獲取地圖的層級(jí)結(jié)構(gòu)伟阔,然后逐個(gè)分析捏合手勢(shì)最有可能發(fā)生在哪一層上。簡(jiǎn)單介紹下它的幾個(gè)重要的層級(jí)結(jié)構(gòu)掰伸,BaiduMapEAGLView(繪制openGL的圖層)皱炉,TapDetctingView(負(fù)責(zé)展示標(biāo)注的圖層),以上兩個(gè)圖層狮鸭,都是添加在地圖私有的MapView上的合搅。而這個(gè)MapView又是放在BMKMapView上的多搀,BMKMapView就是百度地圖開放給我們的mapView,好吧,想說历筝,開放的好少酗昼,上面提到的只開放了一個(gè)。最后我們將目標(biāo)定位到了TapDetectingView上梳猪。

  • 然后我們通過Runtime工具,將這個(gè)可疑的TapDetectingView的所有實(shí)例方法都打印了出來蒸痹,挨個(gè)去找春弥,希望能有什么發(fā)現(xiàn)。下面簡(jiǎn)單羅列幾個(gè)方法:

Some InstanceMethods Of TapDetctingView:(
    handleSingleTap,              //處理單擊事件
    "handleForceTouch:",          //處理重壓事件
    handleDoubleBeginTouchPoint,  //開始處理兩個(gè)手指的點(diǎn)擊事件(可疑方法)
    handleDoubleMoveTouchPoint,   //處理兩個(gè)手指的運(yùn)動(dòng)事件(可疑方法)
    handleMoveTouchPoint,         //處理單個(gè)手指的運(yùn)動(dòng)事件
    "handleScale:",                //暫時(shí)不知道叠荠,但是scale跟縮放有關(guān)(可疑方法)
    "handleRoate:",                //處理旋轉(zhuǎn)事件
    handleEndTouchPoint,           //處理單個(gè)手指的結(jié)束事件
    handleDoubleEndTouchPoint,      //處理兩個(gè)手指的結(jié)束事件(可疑方法)
    handleTwoFingerTap,             //處理兩個(gè)手指的點(diǎn)擊事件
)

在上面的部分方法中匿沛,我們根據(jù)方法名定位出了四個(gè)可能跟地圖縮放有關(guān)的方法,事實(shí)證明榛鼎,處理縮放事件手勢(shì)的也確實(shí)是這四個(gè)方法逃呼。

從方法名看,那四個(gè)方法確實(shí)可疑者娱,可是我們?cè)撊绾芜M(jìn)一步確定呢抡笼。

使用Aspects 來 hookTapDetctingView的所有方法。

我們使用了一個(gè)輕量級(jí)的面向切面編程的庫(kù)Aspects來實(shí)現(xiàn)我們的目的黄鳍。在TapDetctingView的每一個(gè)方法執(zhí)行完后都會(huì)進(jìn)入我們自己的代碼塊中推姻,在我們的代碼塊中,做了打印方法名的操作框沟。這樣我們就可以在地圖運(yùn)動(dòng)中藏古,來看具體調(diào)用了哪個(gè)方法。

#pragma mark 處理百度地圖的相關(guān)私有視圖
- (void)handleRelevantPrivateViewOfBaiduMap{
    id mapViewClass = NSClassFromString(@"MapView");
    for (UIView *subView in _mapView.subviews) {
        if ([subView isKindOfClass:[mapViewClass class]]) {
            id TapDetectingView = NSClassFromString(@"TapDetectingView");
            for (UIView *subclassView in subView.subviews) {
                if ([subclassView isKindOfClass:[TapDetectingView class]]) {
                    [self hookMethodsInTapDetectingView:subclassView];
                }
            }
        }
    }
}

#pragma mark hook地圖私有視圖的相關(guān)方法
- (void)hookMethodsInTapDetectingView:(UIView *)mapTapDetectingView{
    void (^MethodHookedBlock)(id<AspectInfo>,...) = ^(id<AspectInfo>hookedObject,...){
        NSInvocation *invocation = [hookedObject originalInvocation];
        SEL hookedSelector = invocation.selector;
        NSLog(@"hookedSelector = %@",NSStringFromSelector(hookedSelector));
    };
    for (NSString * selString  in [mapTapDetectingView.class arrayOfInstanceMethods]) {
        [mapTapDetectingView aspect_hookSelector:NSSelectorFromString(selString) withOptions:AspectPositionAfter usingBlock:MethodHookedBlock error:nil];
    };
}

通過上面的代碼忍燥,再通過我們慢慢地操作地圖拧晕,查看打印的方法,我們就可以獲得當(dāng)前響應(yīng)的是哪個(gè)方法了梅垄,讀者可以自己試試厂捞,總之最后我們確定了,跟地圖縮放有關(guān)的就是那四個(gè)方法哎甲。這里需要注意的是那個(gè)handleScale:函數(shù)蔫敲,這個(gè)函數(shù)有一個(gè)參數(shù),這個(gè)參數(shù)是正的時(shí)候炭玫,說明地圖等級(jí)正在變大奈嘿,為負(fù)的時(shí)候,說明等級(jí)正在變小吞加。

那么現(xiàn)在我們想要在開始縮放和縮放結(jié)束的時(shí)候獲取A1點(diǎn)與A2點(diǎn)就容易多了裙犹。因?yàn)?code>zoomLevel是很好獲取的尽狠,而我們只需要再記錄兩個(gè)時(shí)間戳就可以了。這樣兩個(gè)方程叶圃,兩個(gè)未知數(shù)袄膏,我們可以求出一次項(xiàng)的系數(shù)與常數(shù)項(xiàng)的值,從而進(jìn)一步確定手勢(shì)離開屏幕的時(shí)候掺冠,這條即時(shí)的拋物線的函數(shù)了沉馆。

現(xiàn)在我們得到了手勢(shì)離開時(shí)候的地圖等級(jí)zoomLevel相對(duì)于時(shí)間time的拋物線,那么我們就讓它按照既定的軌跡繼續(xù)運(yùn)動(dòng)吧德崭。

得到拋物線方程后斥黑,我們就可以計(jì)算出速率為0時(shí)候的時(shí)間了,

一元二次方程 :y = aX^2 + bX + c 
求導(dǎo)數(shù)      :v = 2aX+ b
所以v = 0時(shí)眉厨,X = -b/2a;

這意味著慣性運(yùn)動(dòng)停止的時(shí)候锌奴,時(shí)間是_tStirless = -b/2a(ab分別是二次項(xiàng)與一次項(xiàng)的系數(shù),此時(shí)都是可知的了)憾股,這樣我們就可以得到手指離開后鹿蜀,它應(yīng)該靠慣性再運(yùn)動(dòng)多長(zhǎng)一段時(shí)間了。也就是_tStirless - _tPinEnd服球。

看到這里茴恰,是不是累了,好吧有咨,馬上就結(jié)束了琐簇,我們需要把這段時(shí)間均分一下,然后帶入方程座享,獲取此時(shí)對(duì)應(yīng)的zoomLevel婉商,然后每隔均分的時(shí)間,就更新一下zoomLevel,這個(gè)步驟的思路就跟上篇的地圖阻尼運(yùn)動(dòng)的思路一致了渣叛。代碼如下:

 /*
     參數(shù)說明:
    ?NSTimeInterval _tPinEnd:記錄捏合手勢(shì)開始的時(shí)間丈秩。
    ?NSTimeInterval _tPinStart:記錄捏合手勢(shì)結(jié)束的時(shí)間。
    ?NSTimeInterval _tPinMoving: 記錄雙指在地圖上的的捏合時(shí)長(zhǎng)淳衙。
                    _tPinMoving =  _tPinEnd - _tPinStart;
    ? NSTimeInterval _tStirless:記錄慣性運(yùn)動(dòng)停止蘑秽,速度為0(也就是靜止)時(shí)候的時(shí)間。
                    _tStirless-_tPinMoving可以得出手指離開后箫攀,慣性運(yùn)動(dòng)的時(shí)長(zhǎng)  
  */
#pragma mark  刷新拋物線上的y值:也就是地圖的zoomlevel肠牲,時(shí)間段在這里分成了10份
- (void)parabola_refreshMapZoomLevel{
    float unitZoomLevelDuringTime = (_tStirless - _tPinMoving)/MAP_ZOOM_NUMS;
    for (int i = 1; i<=MAP_ZOOM_NUMS; i++) {
        float tempZoomLevel = [self parabola_calculateMapZoomLevelAtRealTime:_tPinMoving+i*unitZoomLevelDuringTime];
        dispatch_time_t time =  dispatch_time(DISPATCH_TIME_NOW, (uint64_t)(NSEC_PER_SEC * (i*unitZoomLevelDuringTime)));
        dispatch_after(time, dispatch_get_main_queue(), ^{
            [_mapView setZoomLevel:tempZoomLevel];
        });
    }
}
 /*
     參數(shù)說明:
    ?_quadraticCoefficient:慣性運(yùn)動(dòng)方程的二次項(xiàng)系數(shù)
    ?_oneCoefficient :慣性運(yùn)動(dòng)方程的一次項(xiàng)系數(shù)
    ?_constantCoefficient:慣性運(yùn)動(dòng)方程的常數(shù)項(xiàng)
 */
#pragma mark  實(shí)時(shí)計(jì)算拋物線上time所對(duì)應(yīng)的maplevel
- (CGFloat)parabola_calculateMapZoomLevelAtRealTime:(float)realTime{
    return _quadraticCoefficient *(realTime *realTime) + _oneCoefficient * realTime + _zoomLevelPinStart;
}

好了,寫到這里基本就實(shí)現(xiàn)了我們的慣性效果靴跛,在這里只列出了部分的關(guān)鍵代碼缀雳,還有很多其他的沒有羅列,都羅列的話梢睛,篇幅就比較長(zhǎng)了肥印,建議自己下載demo查看具體實(shí)現(xiàn)识椰,demo中對(duì)手勢(shì)持續(xù)時(shí)間超過0.8s的,不做慣性處理深碱,因?yàn)槌^這個(gè)時(shí)間的話腹鹉,那么有很大的可能性證明此時(shí)的用戶正在認(rèn)真的查找某一層級(jí)的東西,這時(shí)候就不對(duì)它進(jìn)行慣性縮放了敷硅。

更新:
最近將地圖慣性運(yùn)動(dòng)相關(guān)的代碼功咒,抽離到了BMKMapViewAdapter類中,該類提供更簡(jiǎn)潔的api如下:

/**
 
 @param mapView mapView description
 @param inertiaCoefficient 慣性系數(shù)绞蹦,系數(shù)越大航瞭,慣性越大,越不容易改變坦辟。
 */
+ (void)mapView:(BMKMapView *)mapView openInertiaDragWithCoefficient:(float)inertiaCoefficient;
/**
 @param mapView mapView description
 @param close close description
 */
+ (void)mapView:(BMKMapView *)mapView closeMapInertialDrag:(BOOL)close;

除了對(duì)核心代碼的抽離,對(duì)于最后一步(也就是從雙手離開屏幕到它完全停止的這個(gè)過程)也改變了它的實(shí)現(xiàn)方式章办,之前是將這段時(shí)間分成N份锉走,然后逐步設(shè)置當(dāng)前時(shí)間點(diǎn)下的zoomlevel,現(xiàn)在的話,采用CADisplaylink藕届,使之設(shè)置level的頻率與屏幕的刷新頻率一致挪蹭,并且取消了原來GCD的使用,而改用performSelector:afterDelay:這樣就可以方便的進(jìn)行取消操作了休偶,代碼如下:

 static int zoomDisplayCount;
 static CADisplayLink *displayLink;
/**
 雙指離開屏幕后梁厉,還會(huì)繼續(xù)運(yùn)動(dòng)的時(shí)間
 @param time time description
 */
- (void)startAnimateWithtimeDuration:(NSTimeInterval)time{
    if (time > 0) {
        if (displayLink) {
            displayLink.paused = YES;
        }
        displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(changeMapLevelByStep)];
        [displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
        displayLink.paused = NO;
        [self performSelector:@selector(moveDidEnd) withObject:nil afterDelay:time];
    }
}
/**
 逐步改變地圖的level級(jí)別
 */
- (void)changeMapLevelByStep{
    zoomDisplayCount ++;
    float time = zoomDisplayCount/60.f;
    float tempZoomLevel = [self parabola_calculateMapZoomLevelAtRealTime:_tPinMoving + time];
    [_mapView setZoomLevel:tempZoomLevel];
}
/**
 運(yùn)動(dòng)停止
 */
- (void)moveDidEnd{
    displayLink.paused = YES;
    [displayLink invalidate];
    displayLink = nil;
    zoomDisplayCount = 0;
}

地圖慣性縮放.gif

建議下載demo,體驗(yàn)效果。

傳送門:地圖系列的其他文章:
給你的地圖模塊動(dòng)手術(shù) -----一種輕量級(jí)的地圖解決方案踏兜。
地圖阻尼運(yùn)動(dòng)
給你的地圖點(diǎn)燈

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末词顾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子碱妆,更是在濱河造成了極大的恐慌肉盹,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疹尾,死亡現(xiàn)場(chǎng)離奇詭異上忍,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)纳本,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門窍蓝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人繁成,你說我怎么就攤上這事吓笙。” “怎么了朴艰?”我有些...
    開封第一講書人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵观蓄,是天一觀的道長(zhǎng)混移。 經(jīng)常有香客問我,道長(zhǎng)侮穿,這世上最難降的妖魔是什么歌径? 我笑而不...
    開封第一講書人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮亲茅,結(jié)果婚禮上回铛,老公的妹妹穿的比我還像新娘。我一直安慰自己克锣,他們只是感情好茵肃,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著袭祟,像睡著了一般验残。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上巾乳,一...
    開封第一講書人閱讀 51,737評(píng)論 1 305
  • 那天您没,我揣著相機(jī)與錄音,去河邊找鬼胆绊。 笑死氨鹏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的压状。 我是一名探鬼主播仆抵,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼种冬!你這毒婦竟也來了镣丑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤传轰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后谷婆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體慨蛙,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年纪挎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了期贫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡异袄,死狀恐怖通砍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤封孙,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布迹冤,位于F島的核電站,受9級(jí)特大地震影響虎忌,放射性物質(zhì)發(fā)生泄漏泡徙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一膜蠢、第九天 我趴在偏房一處隱蔽的房頂上張望堪藐。 院中可真熱鬧,春花似錦挑围、人聲如沸礁竞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)模捂。三九已至,卻和暖如春蜘矢,著一層夾襖步出監(jiān)牢的瞬間枫绅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工硼端, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人寓搬。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓珍昨,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親句喷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子镣典,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

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