CoreAnimation day4

今天研究圖形變換

仿射變換

在第三章“圖層幾何學”中,我們使用了UIView的transform屬性旋轉(zhuǎn)了鐘的指針领斥,但并沒有解釋背后運作的原理端盆,實際上UIView的transform屬性是一個CGAffineTransform類型合呐,用于在二維空間做旋轉(zhuǎn),縮放和平移是偷。CGAffineTransform是一個可以和二維空間向量(例如CGPoint)做乘法的3X2的矩陣。

用CGPoint的每一列和CGAffineTransform矩陣的每一行對應元素相乘再求和,就形成了一個新的CGPoint類型的結果蛋铆。要解釋一下圖中顯示的灰色元素馋评,為了能讓矩陣做乘法,左邊矩陣的列數(shù)一定要和右邊矩陣的行數(shù)個數(shù)相同刺啦,所以要給矩陣填充一些標志值留特,使得既可以讓矩陣做乘法,又不改變運算結果洪燥,并且沒必要存儲這些添加的值磕秤,因為它們的值不會發(fā)生變化,但是要用來做運算捧韵。

因此市咆,通常會用3×3(而不是2×3)的矩陣來做二維變換,你可能會見到3行2列格式的矩陣再来,這是所謂的以列為主的格式蒙兰,只要能保持一致,用哪種格式都無所謂芒篷。

當對圖層應用變換矩陣搜变,圖層矩形內(nèi)的每一個點都被相應地做變換,從而形成一個新的四邊形的形狀针炉。CGAffineTransform中的“仿射”的意思是無論變換矩陣用什么值挠他,圖層中平行的兩條線在變換之后任然保持平行,CGAffineTransform可以做出任意符合上述標注的變換篡帕。

創(chuàng)建一個CGAffineTransform

對矩陣數(shù)學做一個全面的闡述就超出本書的討論范圍了殖侵,不過如果你對矩陣完全不熟悉的話,矩陣變換可能會使你感到畏懼镰烧。幸運的是拢军,Core Graphics提供了一系列函數(shù),對完全沒有數(shù)學基礎的開發(fā)者也能夠簡單地做一些變換怔鳖。如下幾個函數(shù)都創(chuàng)建了一個CGAffineTransform實例:

CGAffineTransformMakeRotation(CGFloat angle)

CGAffineTransformMakeScale(CGFloat sx, CGFloat sy)

CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty)

旋轉(zhuǎn)和縮放變換都可以很好解釋--分別旋轉(zhuǎn)或者縮放一個向量的值茉唉。平移變換是指每個點都移動了向量指定的x或者y值--所以如果向量代表了一個點,那它就平移了這個點的距離结执。

UIView可以通過設置transform屬性做變換度陆,但實際上它只是封裝了內(nèi)部圖層的變換。

CALayer同樣也有一個transform屬性献幔,但它的類型是CATransform3D懂傀,而不是CGAffineTransform,本章后續(xù)將會詳細解釋斜姥。CALayer對應于UIView的transform屬性叫做affineTransform鸿竖。

混合變換

Core Graphics提供了一系列的函數(shù)可以在一個變換的基礎上做更深層次的變換沧竟,如果做一個既要縮放又要旋轉(zhuǎn)的變換,這就會非常有用了缚忧。例如下面幾個函數(shù):

CGAffineTransformRotate(CGAffineTransform t, CGFloat angle)

CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy)

CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty)

當操縱一個變換的時候悟泵,初始生成一個什么都不做的變換很重要--也就是創(chuàng)建一個CGAffineTransform類型的空值,矩陣論中稱作單位矩陣闪水,Core Graphics同樣也提供了一個方便的常量:

CGAffineTransformIdentity

最后糕非,如果需要混合兩個已經(jīng)存在的變換矩陣,就可以使用如下方法球榆,在兩個變換的基礎上創(chuàng)建一個新的變換:

CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2);

我們來用這些函數(shù)組合一個更加復雜的變換朽肥,先縮小50%,再旋轉(zhuǎn)30度持钉,最后向右移動200個像素衡招。

- (void)viewDidLoad

{

[super viewDidLoad];?

CGAffineTransform transform = CGAffineTransformIdentity;

transform = CGAffineTransformScale(transform, 0.5, 0.5);?

transform = CGAffineTransformRotate(transform, M_PI / 180.0 * 30.0);?

transform = CGAffineTransformTranslate(transform, 200, 0);

self.layerView.layer.affineTransform = transform;

}

變換的順序會影響最終的結果,也就是說旋轉(zhuǎn)之后的平移和平移之后的旋轉(zhuǎn)結果可能不同每强。

剪切變換

Core Graphics為你提供了計算變換矩陣的一些方法始腾,所以很少需要直接設置CGAffineTransform的值。除非需要創(chuàng)建一個斜切的變換空执,Core Graphics并沒有提供直接的函數(shù)浪箭。

斜切變換是放射變換的第四種類型,較于平移辨绊,旋轉(zhuǎn)和縮放并不常用(這也是Core Graphics沒有提供相應函數(shù)的原因)奶栖,但有些時候也會很有用。我們用一張圖片可以很直接的說明效果门坷。也許用“傾斜”描述更加恰當宣鄙,具體做變換的代碼。

@implementation ViewController

CGAffineTransform CGAffineTransformMakeShear(CGFloat x, CGFloat y)

{

CGAffineTransform transform = CGAffineTransformIdentity;

transform.c = -x;

transform.b = y;

return transform;

}

- (void)viewDidLoad

{

[super viewDidLoad];

//shear the layer at a 45-degree angle

self.layerView.layer.affineTransform = CGAffineTransformMakeShear(1, 0);

}

@end

3D變換

CG的前綴告訴我們拜鹤,CGAffineTransform類型屬于Core Graphics框架框冀,Core Graphics實際上是一個嚴格意義上的2D繪圖API流椒,并且CGAffineTransform僅僅對2D變換有效敏簿。

在第三章中,我們提到了zPosition屬性宣虾,可以用來讓圖層靠近或者遠離相機(用戶視角)惯裕,transform屬性(CATransform3D類型)可以真正做到這點,即讓圖層在3D空間內(nèi)移動或者旋轉(zhuǎn)绣硝。

和CGAffineTransform類似蜻势,CATransform3D也是一個矩陣,但是和2x3的矩陣不同鹉胖,CATransform3D是一個可以在3維空間內(nèi)做變換的4x4的矩陣握玛。

和CGAffineTransform矩陣類似够傍,Core Animation提供了一系列的方法用來創(chuàng)建和組合CATransform3D類型的矩陣,和Core Graphics的函數(shù)類似挠铲,但是3D的平移和旋轉(zhuǎn)多處了一個z參數(shù)冕屯,并且旋轉(zhuǎn)函數(shù)除了angle之外多出了x,y,z三個參數(shù),分別決定了每個坐標軸方向上的旋轉(zhuǎn):

CATransform3DMakeRotation(CGFloat angle, CGFloat x, CGFloat y, CGFloat z)

CATransform3DMakeScale(CGFloat sx, CGFloat sy, CGFloat sz)

CATransform3DMakeTranslation(Gloat tx, CGFloat ty, CGFloat tz)

你應該對X軸和Y軸比較熟悉了拂苹,分別以右和下為正方向(回憶第三章安聘,這是iOS上的標準結構,在Mac OS瓢棒,Y軸朝上為正方向)浴韭,Z軸和這兩個軸分別垂直,指向視角外為正方向脯宿。

由圖所見念颈,繞Z軸的旋轉(zhuǎn)等同于之前二維空間的仿射旋轉(zhuǎn),但是繞X軸和Y軸的旋轉(zhuǎn)就突破了屏幕的二維空間连霉,并且在用戶視角看來發(fā)生了傾斜舍肠。

舉個例子:清單5.4的代碼使用了CATransform3DMakeRotation對視圖內(nèi)的圖層繞Y軸做了45度角的旋轉(zhuǎn),我們可以把視圖向右傾斜窘面,這樣會看得更清晰翠语。

結果并不像我們期待的那樣。

@implementation ViewController

- (void)viewDidLoad

{

[super viewDidLoad];

//rotate the layer 45 degrees along the Y axis

CATransform3D transform = CATransform3DMakeRotation(M_PI_4, 0, 1, 0);

self.layerView.layer.transform = transform;

}

@end

看起來圖層并沒有被旋轉(zhuǎn)财边,而是僅僅在水平方向上的一個壓縮肌括,是哪里出了問題呢?

其實完全沒錯酣难,視圖看起來更窄實際上是因為我們在用一個斜向的視角看它谍夭,而不是透視。

透視投影

在真實世界中憨募,當物體原理我們的時候紧索,由于視角的原因看起來會變小,理論上說遠離我們的視圖的邊要比靠近視角的邊跟短菜谣,但實際上并沒有發(fā)生珠漂,而我們當前的視角是等距離的,也就是在3D變換中任然保持平行尾膊,和之前提到的仿射變換類似媳危。

在等距投影中,遠處的物體和近處的物體保持同樣的縮放比例冈敛,這種投影也有它自己的用處(例如建筑繪圖待笑,顛倒,和偽3D視頻)抓谴,但當前我們并不需要暮蹂。

為了做一些修正寞缝,我們需要引入投影變換(又稱作z變換)來對除了旋轉(zhuǎn)之外的變換矩陣做一些修改,Core Animation并沒有給我們提供設置透視變換的函數(shù)仰泻,因此我們需要手動修改矩陣值第租,幸運的是,很簡單:

CATransform3D的透視效果通過一個矩陣中一個很簡單的元素來控制:m34我纪。m34用于按比例縮放X和Y的值來計算到底要離視角多遠慎宾。

m34的默認值是0,我們可以通過設置m34為-1.0 / d來應用透視效果浅悉,d代表了想象中視角相機和屏幕之間的距離趟据,以像素為單位,那應該如何計算這個距離呢术健?實際上并不需要汹碱,大概估算一個就好了。

因為視角相機實際上并不存在荞估,所以可以根據(jù)屏幕上的顯示效果自由決定它的防止的位置咳促。通常500-1000就已經(jīng)很好了,但對于特定的圖層有時候更小后者更大的值會看起來更舒服勘伺,減少距離的值會增強透視效果跪腹,所以一個非常微小的值會讓它看起來更加失真,然而一個非常大的值會讓它基本失去透視效果飞醉,@implementation ViewController

- (void)viewDidLoad

{

[super viewDidLoad];

CATransform3D transform = CATransform3DIdentity;

transform.m34 = - 1.0 / 500.0;

transform = CATransform3DRotate(transform, M_PI_4, 0, 1, 0);

self.layerView.layer.transform = transform;

}

@end

消亡點

當在透視角度繪圖的時候冲茸,遠離相機視角的物體將會變小變遠,當遠離到一個極限距離缅帘,它們可能就縮成了一個點轴术,于是所有的物體最后都匯聚消失在同一個點。

在現(xiàn)實中钦无,這個點通常是視圖的中心逗栽,于是為了在應用中創(chuàng)建擬真效果的透視,這個店應該聚在屏幕中點失暂,或者至少是包含所有3D對象的視圖中點彼宠。

Core Animation定義了這個點位于變換圖層的anchorPoint。這就是說趣席,當圖層發(fā)生變換時兵志,這個點永遠位于圖層變換之前anchorPoint的位置醇蝴。

當改變一個圖層的position宣肚,你也改變了它的消亡點,做3D變換的時候要時刻記住這一點悠栓,當你視圖通過調(diào)整m34來讓它更加有3D效果霉涨,應該首先把它放置于屏幕中央按价,然后通過平移來把它移動到指定位置(而不是直接改變它的position),這樣所有的3D圖層都共享一個消亡點笙瑟。

sublayerTransform屬性

如果有多個視圖或者圖層楼镐,每個都做3D變換,那就需要分別設置相同的m34值往枷,并且確保在變換之前都在屏幕中央共享同一個position框产,如果用一個函數(shù)封裝這些操作的確會更加方便,但仍然有限制错洁,這里有一個更好的方法秉宿。

CALayer有一個屬性叫做sublayerTransform。它也是CATransform3D類型屯碴,但和對一個圖層的變換不同描睦,它影響到所有的子圖層。這意味著你可以一次性對包含這些圖層的容器做變換导而,于是所有的子圖層都自動繼承了這個變換方法忱叭。

相較而言,通過在一個地方設置透視變換會很方便今艺,同時它會帶來另一個顯著的優(yōu)勢:消亡點被設置在容器圖層的中點韵丑,從而不需要再對子圖層分別設置了。這意味著你可以隨意使用position和frame來放置子圖層虚缎,而不需要把它們放置在屏幕中點埂息,然后為了保證統(tǒng)一的消亡點用變換來做平移。

我們來用一個demo舉例說明遥巴。這里用Interface Builder并排放置兩個視圖千康,然后通過設置它們?nèi)萜饕晥D的透視變換,我們可以保證它們有相同的透視和消亡點铲掐。

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *containerView;

@property (nonatomic, weak) IBOutlet UIView *layerView1;

@property (nonatomic, weak) IBOutlet UIView *layerView2;

@end

@implementation ViewController

- (void)viewDidLoad

{

[super viewDidLoad];

//apply perspective transform to container

CATransform3D perspective = CATransform3DIdentity;

perspective.m34 = - 1.0 / 500.0;

self.containerView.layer.sublayerTransform = perspective;

//rotate layerView1 by 45 degrees along the Y axis

CATransform3D transform1 = CATransform3DMakeRotation(M_PI_4, 0, 1, 0);

self.layerView1.layer.transform = transform1;

//rotate layerView2 by 45 degrees along the Y axis

CATransform3D transform2 = CATransform3DMakeRotation(-M_PI_4, 0, 1, 0);

self.layerView2.layer.transform = transform2;

}

這個方法意思就是所設置效果對選中視圖層都有效拾弃。

背面

我們既然可以在3D場景下旋轉(zhuǎn)圖層,那么也可以從背面去觀察它摆霉。如果我們在清單5.4中把角度修改為M_PI(180度)而不是當前的M_PI_4(45度)豪椿,那么將會把圖層完全旋轉(zhuǎn)一個半圈,于是完全背對了相機視角携栋。

如你所見搭盾,圖層是雙面繪制的,反面顯示的是正面的一個鏡像圖片婉支。

但這并不是一個很好的特性鸯隅,因為如果圖層包含文本或者其他控件,那用戶看到這些內(nèi)容的鏡像圖片當然會感到困惑。另外也有可能造成資源的浪費:想象用這些圖層形成一個不透明的固態(tài)立方體蝌以,既然永遠都看不見這些圖層的背面炕舵,那為什么浪費GPU來繪制它們呢?

CALayer有一個叫做doubleSided的屬性來控制圖層的背面是否要被繪制跟畅。這是一個BOOL類型咽筋,默認為YES,如果設置為NO徊件,那么當圖層正面從相機視角消失的時候奸攻,它將不會被繪制。

設置doubleSided = NO虱痕;對于圖像優(yōu)化有幫助舞箍;

扁平化圖層

如果對包含已經(jīng)做過變換的圖層的圖層做反方向的變換將會發(fā)什么什么呢?是不是有點困惑皆疹?

注意做了-45度旋轉(zhuǎn)的內(nèi)部圖層是怎樣抵消旋轉(zhuǎn)45度的圖層疏橄,從而恢復正常狀態(tài)的。

如果內(nèi)部圖層相對外部圖層做了相反的變換(這里是繞Z軸的旋轉(zhuǎn))略就,那么按照邏輯這兩個變換將被相互抵消捎迫。

運行結果和我們預期的一致。現(xiàn)在在3D情況下再試一次表牢。修改代碼窄绒,讓內(nèi)外兩個視圖繞Y軸旋轉(zhuǎn)而不是Z軸,再加上透視效果崔兴,以便我們觀察彰导。注意不能用sublayerTransform屬性,因為內(nèi)部的圖層并不直接是容器圖層的子圖層敲茄,所以這里分別對圖層設置透視變換位谋。

但其實這并不是我們所看到的,相反堰燎,我們看到的結果呢掏父?內(nèi)部的圖層仍然向左側旋轉(zhuǎn),并且發(fā)生了扭曲秆剪,但按道理說它應該保持正面朝上赊淑,并且顯示正常的方塊。

這是由于盡管Core Animation圖層存在于3D空間之內(nèi)仅讽,但它們并不都存在同一個3D空間陶缺。每個圖層的3D場景其實是扁平化的,當你從正面觀察一個圖層洁灵,看到的實際上由子圖層創(chuàng)建的想象出來的3D場景饱岸,但當你傾斜這個圖層,你會發(fā)現(xiàn)實際上這個3D場景僅僅是被繪制在圖層的表面。

類似的伶贰,當你在玩一個3D游戲蛛砰,實際上僅僅是把屏幕做了一次傾斜罐栈,或許在游戲中可以看見有一面墻在你面前黍衙,但是傾斜屏幕并不能夠看見墻里面的東西。所有場景里面繪制的東西并不會隨著你觀察它的角度改變而發(fā)生變化荠诬;圖層也是同樣的道理琅翻。

這使得用Core Animation創(chuàng)建非常復雜的3D場景變得十分困難。你不能夠使用圖層樹去創(chuàng)建一個3D結構的層級關系--在相同場景下的任何3D表面必須和同樣的圖層保持一致柑贞,這是因為每個的父視圖都把它的子視圖扁平化了方椎。

至少當你用正常的CALayer的時候是這樣,CALayer有一個叫做CATransformLayer的子類來解決這個問題钧嘶。

固體對象

現(xiàn)在你懂得了在3D空間的一些圖層布局的基礎棠众,我們來試著創(chuàng)建一個固態(tài)的3D對象(實際上是一個技術上所謂的空洞對象,但它以固態(tài)呈現(xiàn))有决。我們用六個獨立的視圖來構建一個立方體的各個面闸拿。

在這個例子中,我們用Interface Builder來構建立方體的面书幕,我們當然可以用代碼來寫新荤,但是用Interface Builder的好處是可以方便的在每一個面上添加子視圖。記住這些面僅僅是包含視圖和控件的普通的用戶界面元素台汇,它們完全是我們界面交互的部分苛骨,并且當把它折成一個立方體之后也不會改變這個性質(zhì)。

這些面視圖并沒有放置在主視圖當中苟呐,而是松散地排列在根nib文件里面痒芝。我們并不關心在這個容器中如何擺放它們的位置,因為后續(xù)將會用圖層的transform對它們進行重新布局牵素,并且用Interface Builder在容器視圖之外擺放他們可以讓我們?nèi)菀卓辞宄鼈兊膬?nèi)容吼野,如果把它們一個疊著一個都塞進主視圖,將會變得很難看两波。

我們把一個有顏色的UILabel放置在視圖內(nèi)部瞳步,是為了清楚的辨別它們之間的關系,并且UIButton被放置在第三個面視圖里面腰奋,后面會做簡單的解釋单起。

從這個角度看立方體并不是很明顯;看起來只是一個方塊劣坊,為了更好地欣賞它嘀倒,我們將更換一個不同的視角。

旋轉(zhuǎn)這個立方體將會顯得很笨重,因為我們要單獨對每個面做旋轉(zhuǎn)测蘑。另一個簡單的方案是通過調(diào)整容器視圖的sublayerTransform去旋轉(zhuǎn)照相機灌危。

添加如下幾行去旋轉(zhuǎn)containerView圖層的perspective變換矩陣:

perspective = CATransform3DRotate(perspective, -M_PI_4, 1, 0, 0);

perspective = CATransform3DRotate(perspective, -M_PI_4, 0, 1, 0);

這就對相機(或者相對相機的整個場景,你也可以這么認為)繞Y軸旋轉(zhuǎn)45度碳胳,并且繞X軸旋轉(zhuǎn)45度∮买現(xiàn)在從另一個角度去觀察立方體,就能看出它的真實面貌挨约。

光亮和陰影

現(xiàn)在它看起來更像是一個立方體沒錯了味混,但是對每個面之間的連接還是很難分辨。Core Animation可以用3D顯示圖層诫惭,但是它對光線并沒有概念翁锡。如果想讓立方體看起來更加真實,需要自己做一個陰影效果夕土。你可以通過改變每個面的背景顏色或者直接用帶光亮效果的圖片來調(diào)整馆衔。

如果需要動態(tài)地創(chuàng)建光線效果,你可以根據(jù)每個視圖的方向應用不同的alpha值做出半透明的陰影圖層怨绣,但為了計算陰影圖層的不透明度角溃,你需要得到每個面的正太向量(垂直于表面的向量),然后根據(jù)一個想象的光源計算出兩個向量叉乘結果梨熙。叉乘代表了光源和圖層之間的角度开镣,從而決定了它有多大程度上的光亮。

我們用GLKit框架來做向量的計算(你需要引入GLKit庫來運行代碼)咽扇,每個面的CATransform3D都被轉(zhuǎn)換成GLKMatrix4邪财,然后通過GLKMatrix4GetMatrix3函數(shù)得出一個3×3的旋轉(zhuǎn)矩陣。這個旋轉(zhuǎn)矩陣指定了圖層的方向质欲,然后可以用它來得到正太向量的值树埠。

試著調(diào)整LIGHT_DIRECTION和AMBIENT_LIGHT的值來切換光線效果

(具體實現(xiàn)效果和代碼請點擊這里)

點擊事件

你應該能注意到現(xiàn)在可以在第三個表面的頂部看見按鈕了,點擊它嘶伟,什么都沒發(fā)生盈电,為什么呢诵盼?

這并不是因為iOS在3D場景下正確地處理響應事件埃难,實際上是可以做到的叠蝇。問題在于視圖順序。在第三章中我們簡要提到過铸鹰,點擊事件的處理由視圖在父視圖中的順序決定的癌别,并不是3D空間中的Z軸順序。當給立方體添加視圖的時候蹋笼,我們實際上是按照一個順序添加展姐,所以按照視圖/圖層順序來說躁垛,4,5圾笨,6在3的前面教馆。

即使我們看不見4,5擂达,6的表面(因為被1土铺,2,3遮住了)谍婉,iOS在事件響應上仍然保持之前的順序舒憾。當試圖點擊表面3上的按鈕镀钓,表面4穗熬,5,6截斷了點擊事件(取決于點擊的位置)丁溅,這就和普通的2D布局在按鈕上覆蓋物體一樣唤蔗。

你也許認為把doubleSided設置成NO可以解決這個問題,因為它不再渲染視圖后面的內(nèi)容窟赏,但實際上并不起作用妓柜。因為背對相機而隱藏的視圖仍然會響應點擊事件(這和通過設置hidden屬性或者設置alpha為0而隱藏的視圖不同,那兩種方式將不會響應事件)涯穷。所以即使禁止了雙面渲染仍然不能解決這個問題(雖然由于性能問題棍掐,還是需要把它設置成NO)。

這里有幾種正確的方案:把除了表面3的其他視圖userInteractionEnabled屬性都設置成NO來禁止事件傳遞拷况∽骰停或者簡單通過代碼把視圖3覆蓋在視圖6上。無論怎樣都可以點擊按鈕了赚瘦。

今天涉及了一些2D和3D的變換粟誓。學習了一些矩陣計算的基礎,以及如何用Core Animation創(chuàng)建3D場景起意∮シ看到了圖層背后到底是如何呈現(xiàn)的,并且知道了不能把扁平的圖片做成真實的立體效果揽咕,最后我們用demo說明了觸摸事件的處理悲酷,視圖中圖層添加的層級順序會比屏幕上顯示的順序更有意義。

課程原文在此http://www.cocoachina.com/ios/20150104/10816.html

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末亲善,一起剝皮案震驚了整個濱河市设易,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌逗爹,老刑警劉巖亡嫌,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嚎于,死亡現(xiàn)場離奇詭異,居然都是意外死亡挟冠,警方通過查閱死者的電腦和手機于购,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來知染,“玉大人肋僧,你說我怎么就攤上這事】氐” “怎么了嫌吠?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長掺炭。 經(jīng)常有香客問我辫诅,道長,這世上最難降的妖魔是什么涧狮? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任炕矮,我火速辦了婚禮,結果婚禮上者冤,老公的妹妹穿的比我還像新娘肤视。我一直安慰自己,他們只是感情好涉枫,可當我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布邢滑。 她就那樣靜靜地躺著,像睡著了一般愿汰。 火紅的嫁衣襯著肌膚如雪困后。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天尼桶,我揣著相機與錄音操灿,去河邊找鬼。 笑死泵督,一個胖子當著我的面吹牛趾盐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播小腊,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼救鲤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了秩冈?” 一聲冷哼從身側響起本缠,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎入问,沒想到半個月后丹锹,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體稀颁,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年楣黍,在試婚紗的時候發(fā)現(xiàn)自己被綠了匾灶。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡租漂,死狀恐怖阶女,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情哩治,我是刑警寧澤秃踩,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站业筏,受9級特大地震影響憔杨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜驾孔,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一芍秆、第九天 我趴在偏房一處隱蔽的房頂上張望惯疙。 院中可真熱鬧翠勉,春花似錦、人聲如沸霉颠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蒿偎。三九已至朽们,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間诉位,已是汗流浹背骑脱。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留苍糠,地道東北人叁丧。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像岳瞭,于是被迫代替她去往敵國和親拥娄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,515評論 2 359

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