CoreAnimation基本介紹

CoreAnimationXmind.png

這是 Core Animation 的系列文章圾叼,介紹了 Core Animation 的用法,以及如何進行性能優(yōu)化瘫拣。

  1. CoreAnimation基本介紹
  2. CGAffineTransform和CATransform3D
  3. CALayer及其各種子類
  4. CAAnimation:屬性動畫CABasicAnimation损合、CAKeyframeAnimation以及過渡動畫卵蛉、動畫組
  5. 圖層時間CAMediaTiming
  6. 計時器CADisplayLink
  7. 影響動畫性能的因素及如何使用 Instruments 檢測
  8. 圖像IO之圖片加載、解碼盹廷,緩存
  9. 圖層性能之離屏渲染征绸、柵格化、回收池

Core Animation 是一個令人誤解的名字俄占,會被誤認為只能用來做動畫管怠。實際上,Core Animation 是 iOS颠放、macOS上的圖形渲染和動畫的基礎設施排惨,是一個合成引擎(Compositing Engine),以盡可能快的速度將屏幕上的不同視覺內(nèi)容進行合成碰凶。不同內(nèi)容存儲在不同圖層(layer)暮芭,層次結構中的 layer 構成圖層樹(layer tree)。Layer tree 構成UIKit及屏幕上所有內(nèi)容的基礎欲低。

使用 Core Animation 創(chuàng)建動畫時辕宏,只需配置一些動畫參數(shù)(如起點、終點)砾莱,并告訴 Core Animation 開始執(zhí)行瑞筐,其余工作由 Core Animation 完成。動畫過程中每一幀的繪制都由 Core Animation 完成腊瑟,Core Animation 將繪制工作交由 GPU 以實現(xiàn)硬件加速聚假。這種自動借助硬件加速功能可以實現(xiàn)高幀率、流暢的動畫效果闰非,不會給 CPU 造成負擔或影響 app 運行速度膘格。

如果你在開發(fā) iOS app,那么你就在使用 Core Animation财松。如果你在開發(fā) macOS app瘪贱,你也可以很方便的使用 Core Animation纱控。Core Animation 位于AppKitUIKit之下菜秦,集成于 Cocoa甜害、CocoaTouch 工作流中。Core Animation 具有擴展 app 視圖功能的接口球昨,并為動畫提供更精細化控制尔店。

CAArchitecture.png

1. 基礎信息

Core Animation 是對 app 視圖和其它視覺元素進行動畫處理的通用系統(tǒng)。Core Animation 不是為了替代 view主慰,而是與 view 集成闹获,提供更好的性能和動畫效果。Core Animation 通過將 view 內(nèi)容緩存為位圖河哑,以便 GPU 可以直接管理避诽。在某些情況下,由于 Core Animation 的緩存特性璃谨,你可能需要重新考慮如何展示沙庐、管理 app 內(nèi)容,但多數(shù)情況下佳吞,你在沒有意識到的情況時就已在使用 Core Animation 了拱雏。除了緩存視圖內(nèi)容,Core Animation 還提供了指定視覺內(nèi)容底扳,將該內(nèi)容與視圖集成铸抑,并應用動畫的方法。

使用 Core Animation 為 app 的視圖和視覺對象進行動畫處理衷模,大多數(shù)修改與視覺對象的屬性有關鹊汛。例如,可以使用 Core Animation 為視圖的位置阱冶、大小刁憋、不透明度進行動畫處理。當進行此類更改時木蹬,Core Animation 將在屬性當前值和指定值之間進行動畫處理至耻。

如果你為 iOS、macOS 開發(fā)過app镊叁,你就會熟悉 view 的概念尘颓。view 是一個用以展示內(nèi)容(如圖片、文本晦譬、視頻)的矩形對象疤苹,可以截取用戶輸入(如鼠標點擊、手勢觸摸)蛔添。view 可以嵌套使用構建復雜層級痰催,每個 view 管理子視圖的位置。下面是一個常見的視圖層級:

CAHierarchy.jpg

在 iOS 中迎瞧,view 都繼承自同一個基類UIView夸溶,UIView可以處理觸摸事件,支持 Core Graphics 繪制凶硅、仿射變換缝裁、淡入淡出動畫等。

UIView本身并未處理多數(shù)這些任務足绅。渲染、動畫都由 Core Animation 的CALayer類處理。

1.1 CALayer

CALayer在概念上和UIView很像绰咽,也是矩形對象嚷掠,可以排布為層級樹、包含內(nèi)容首量、管理子圖層的位置壮吩。CALayer的屬性、方法提供了執(zhí)行動畫加缘、仿射變換的功能鸭叙。與UIView相比,CALayer缺少的主要功能是響應用戶交互事件拣宏。

CALayer盡管提供了判斷點擊位置是否在 layer 內(nèi)的方法沈贝,但其并不清楚具體的響應鏈。

1.2 平行層級關系

每個UIView有一個CALayer類型的layer屬性勋乾,被稱為backing layer宋下。View 負責創(chuàng)建、管理 layer辑莫,以確保子視圖添加杨凑、移除時,其關聯(lián)的圖層也在相應層級中進行同樣操作摆昧。

屏幕內(nèi)容的顯示和動畫都是由 backing layer 負責的撩满,UIView僅僅是它的封裝,提供一些針對 iOS 的功能(如響應手勢事件)和核心動畫底層功能的高級封裝绅你。

為什么 iOS 有兩個平行層級的UIViewCALayer伺帘?為什么不使用一個層級處理所有事件?同時使用UIViewCALayer是為了職責分離忌锯,避免代碼重復伪嫁。iOS 和 macOS 中事件和用戶交互的處理邏輯有很多不同。多點觸摸的觸控屏與鼠標偶垮、鍵盤控制的完全不同张咳,這也是 iOS 使用UIKitUIView帝洪,macOS 使用AppKitNSView的原因,它們功能相同脚猾,但實現(xiàn)方式不同葱峡。

在 iOS 和 macOS 中,都有渲染龙助、布局砰奕、動畫這些共同概念,將這些基礎功能獨立到 Core Animation framework提鸟,可以在 iOS军援、macOS 間共享代碼,方便 Apple 系統(tǒng)開發(fā)人員開發(fā)系統(tǒng)称勋,以及第三方開發(fā)者開發(fā)跨平臺應用胸哥。

實際中,這里不是兩個平行層級赡鲜,而是四個平行層級烘嘱,各自執(zhí)行不同功能。層級如下:

  • 視圖層級(View tree)蝗蛙。
  • 圖層樹(Layer tree)蝇庭。
  • 呈現(xiàn)樹(Presentation Tree)。
  • 渲染樹(Render Tree)捡硅。

2. 圖層動畫

2.1 Layer 提供了繪制哮内、動畫基礎功能

Layer 對象是在3D空間中組織的2D畫面,是核心動畫的核心壮韭。與 view 類似北发,layer 管理幾何坐標、內(nèi)容和視覺屬性信息喷屋。

2.1.1 基于圖層的繪圖模型

大部分 layer 并不執(zhí)行繪制工作琳拨。相反,layer 捕獲 app 提供的內(nèi)容屯曹,并緩存為位圖狱庇。隨后修改 layer 屬性時,只需修改該 layer 對象的狀態(tài)信息恶耽。當修改會觸發(fā)動畫時密任,Core Animation 將 layer 的位圖和狀態(tài)信息傳遞給 GPU,GPU 根據(jù)傳入信息渲染位圖偷俭。使用硬件操控位圖比使用軟件快很多浪讳。

Core Animation 繪制內(nèi)容流程如下:

CAbasics_layer_rendering.png

這里操縱的是靜態(tài)位圖,基于 layer 繪制與基于 view 繪制技術有著明顯不同涌萤。使用基于 view 的繪制時淹遵,改變 view 屬性會導致調(diào)用draw(_:)方法重繪視圖口猜,這種重繪在主線程使用 CPU 進行,因此非常昂貴透揣。Core Animation 通過在硬件中操控緩存的位圖避免這些昂貴開銷济炎。

2.1.2 基于圖層的動畫

Layer 的數(shù)據(jù)和狀態(tài)信息與該 layer 在屏幕上的視覺呈現(xiàn)是分離的。這種解耦可以讓 Core Animation 將動畫從原來狀態(tài)逐步變更為新狀態(tài)淌实。

下圖顯示了部分類型動畫:

CAbasics_animation_types.png

動畫過程中,核心動畫自動在硬件中完成每一幀的繪制猖腕。你只需指定開始拆祈、結束位置,Core Animation 負責其他所有工作倘感。也可以指定動畫時間信息或其他參數(shù)放坏,如果你沒有提供這些信息,Core Animation 會采用默認值老玛。

2.2 可動畫屬性

CALayer中的某些可動畫屬性與UIView中可動畫屬性對應淤年,如frameposition蜡豹、opacity麸粮。

2.2.1 Position and size
CAPositionAndSize.png

修改 layer 的positionsize镜廉、transform弄诲,會同等修改關聯(lián)的 view,與直接修改 view 中這些屬性動畫一樣娇唯。

  • bounds:以動畫形式修改邊框齐遵。
  • position:在父圖層中,以動畫形式修改圖層位置塔插。也可以通過position.x梗摇、position.y只修改一個維度位置。
  • transform:移動想许、縮放伶授、旋轉(zhuǎn)圖層。使用 layer 的transform可以在3D空間使用動畫流纹,view 屬性動畫不能使用3D動畫谎砾。

CALayer可以單獨使用,使用以下方法添加到 view:

        let layer = CALayer()
        layer.position = view.layer.position
        layer.bounds = CGRect(x: 0, y: 0, width: width * 2, height: width * 2)
        layer.backgroundColor = UIColor.darkGray.cgColor
        view.layer.addSublayer(layer)

使用以下代碼修改 layer 的bounds捧颅、position.y景图、transform

            layer.bounds = CGRect(x: 0, y: 0, width: width * 2, height: width * 2)
            layer.position.y = layer.position.y + width
            layer.transform = CATransform3DMakeRotation(.pi / 4.0, 0, 0, 1)

修改后效果如下:

CABoundsPositionTransform.gif

雖然boundsposition類型都是CGFloat碉哑,但使用時應盡可能使用整數(shù)挚币。因為不能把邊界放到一個像素的中間或者三分之一等位置亮蒋,也就是像素不能再被分割。遇到小數(shù)時妆毕,設備會盡量模擬這種效果慎玖,但會耗費性能。

2.2.2 Border
CABorder.png

通過修改圖層的 border笛粘,可以實現(xiàn)動畫修改顏色趁怔、寬度、拐角半徑薪前。

  • borderColor:修改 border 顏色润努。
  • borderWidth:當值大于0時,layer 使用borderColor繪制邊框示括。繪制時铺浇,從bounds向內(nèi)偏移borderWith寬度繪制。邊框覆蓋在contents和子圖層之上垛膝,包含cornerRadius屬性效果鳍侣。borderWidth默認值為0.0。
  • cornerRadius:當值大于0時吼拥,layer 開始使用圓角裁剪背景倚聚。默認情況下,cornerRadius不裁剪contents凿可,只對backgroundColor和 border有效秉沼。當masksToBounds屬性為true時,contents會被裁減為圓角矿酵。cornerRadius默認值為0.0唬复。

cornerRadius效果如下:

CAlayer_corner_radius.png

修改方法如下:

            layer.borderColor = UIColor.orange.cgColor
            layer.borderWidth = 5
            layer.cornerRadius = 15

效果如下:

CABorder.gif

Border 是跟隨著圖層邊界變化的,而不是圖層里面的內(nèi)容全肮。如果子圖層超過了邊界敞咧,邊框仍然會沿著圖層的邊界繪制出來。超出圖層邊框的content和子圖層辜腺,會顯示在 border 之下:

CAOutsideBorder.png
2.2.3 Shadow
CAShadow.png

可以修改shadow的以下屬性:

  • shadowOffset:layer 陰影偏移量休建。默認為(0.0, -3.0)。
  • shadowOpacity:陰影的不透明度评疗。shadowOpacity值范圍是0.0(透明测砂,即不顯示陰影)至1.0(不透明)。該值默認為0.0百匆。
  • shadowPath:修改 layer 的陰影形狀砌些。shadowPath屬性默認值為nil,這時采用標準的陰影形狀。如果為shadowPath屬性指定了值存璃,layer 會采用該值生成陰影仑荐。path 定義了陰影的邊框,內(nèi)容采用shadowOpacity纵东、shadowColor粘招、shadowRadius合成。
  • shadowRadius:渲染 layer 陰影的模糊半徑偎球。默認值為3.0洒扎。

使用shadowOffset方法如下:

            layer.shadowOffset = CGSize(width: 15, height: 20)
            layer.shadowOpacity = 0.5

效果如下:

CAShadowOffset.gif

如果沒有設置backgroundColor,shadow 會顯示到content上衰絮;如果有backgroundColor袍冷,shadow 顯示到content下,也就是 border 內(nèi)不顯示岂傲,只在邊框外顯示陰影难裆。

使用shadowPath不會觸發(fā)離屏渲染子檀,性能更好镊掖。方法如下:

            layer.shadowOpacity = 0.8
            
            let shadowHeight: CGFloat = 20
            let shadowPath = CGPath(ellipseIn: CGRect(x: -shadowHeight,
                                                      y: layer.bounds.size.height,
                                                      width: layer.bounds.width + shadowHeight * 2,
                                                      height: shadowHeight),
                                    transform: nil)
            layer.shadowPath = shadowPath

效果如下:

CAShadowPath.gif

使用masksToBounds會裁剪掉超出邊框所有內(nèi)容,包含陰影褂痰∧督可以使用兩個疊加的 layer 實現(xiàn)陰影效果。

2.2.4 Contents
CAContents.png

以下屬性影響 layer contents 渲染:

  • contents:將 TIFF 或 PNG 數(shù)據(jù)賦值給contents屬性缩歪。
  • mask:用于遮蓋圖層可見內(nèi)容的形狀或圖像归薛。
  • opacity:不透明度。值范圍是0.0(透明的)至1.0(不透明的)匪蝙。超出范圍的值會被限制為最小值或最大值主籍。opacity屬性默認值為1.0。

contents屬性用法如下:

            layer.contents = UIImage(named: "Ball")?.cgImage
            layer.cornerRadius = 20
            layer.masksToBounds = true

效果如下:

CAContentsMaskToBounds.gif

上述這些屬性只是部分可動畫屬性逛球,CALayer的子類可能有額外可動畫屬性千元。Animatable Properties列出了所有可以使用動畫效果的屬性。

直接修改 layer 的屬性颤绕,會使用隱式動畫(implicit animation)幸海。隱式動畫采用默認時間信息和其他屬性執(zhí)行動畫。UIView默認禁用了 layer 動畫奥务,只在 animation block 內(nèi)開啟了動畫物独。因此,直接修改單獨 layer 的上述屬性氯葬,會以動畫形式執(zhí)行挡篓。只有在 animation block 中修改視圖屬性,才會開啟動畫帚称。

3. Layer 定義了自身的幾何信息

Layer 的功能之一就是管理其內(nèi)容的幾何信息瞻凤。幾何信息包含bounds憨攒、position、旋轉(zhuǎn)阀参、縮放和變換等肝集。與 view 類似,layer 也使用bounds蛛壳、position信息決定內(nèi)容位置杏瞻。此外,Layer 還具有 view 沒有的屬性衙荐,如anchorPoint捞挥。anchorPoint定義了 layer 的錨點。

3.1 Layer 使用兩種坐標系統(tǒng)

Layer 同時使用點坐標系(point-based coordinate system)和單位坐標系(unit coordinate system)指定內(nèi)容位置忧吟。根據(jù)位置信息類型決定使用哪種坐標系砌函。當映射到屏幕或相對于其他圖層時(如position),使用點坐標系溜族。當值不應綁定到屏幕時(如anchorPoint屬性)讹俊,即相對于其它值的,使用單位坐標系煌抒。

Point-based coordinate 最常見用途是指定 layer 的大小和位置仍劈,bounds屬性指定 layer 在屏幕上的大小,position屬性指定 layer 相對父圖層的位置寡壮。雖然 layer 也有frame屬性贩疙,但frame是從boundsposition派生而來,很少使用况既。

boundsframe的方向因平臺而已这溅。在 iOS 中,bounds原點在左上角棒仍;在 macOS 中悲靴,bounds原點在左下角。

CAlayer_coords_bounds.png

在上圖中降狠,position位于 layer 的中心对竣,position屬性隨anchorPoint而變。anchorPoint默認值是(0.5, 0.5)榜配,表示 layer 矩形的中心否纬。所有對 view 的操作均以該點為中心執(zhí)行。例如蛋褥,anchorPoint為默認值時临燃,旋轉(zhuǎn)圍繞中心進行。改變anchorPoint后,旋轉(zhuǎn)以新設置點為中心進行膜廊。

Anchor point 是少數(shù)幾個使用單位坐標系的屬性之一乏沸。單位坐標系值范圍是0.0至1.0。例如爪瓜,在x軸上蹬跃,左側為0.0,右側為1.0铆铆。在y軸上蝶缀,單位坐標系的方向因平臺而異。

CAGradientLayerstartPoint薄货、stopPoint也使用單位坐標系翁都。

CAlayer_coords_unit.png

3.2 Anchor point 影響操作幾何信息

對幾何信息的操作都以 anchor point 為中心進行,使用anchorPoint屬性獲取 layer 的 anchor point谅猾。當操作position柄慰、transform時,anchor point 的影響尤為明顯税娜。

對 layer 添加旋轉(zhuǎn)變換后坐搔,旋轉(zhuǎn)以 anchor point 為中心執(zhí)行。因為anchorPoint默認位于圖層中心巧涧,旋轉(zhuǎn)圍繞中心進行薯蝎,但可以通過修改anchorPoint改變旋轉(zhuǎn)的中心遥倦,如下圖所示:

CAlayer_coords_anchorpoint_transform.png

設置 layer 的anchorPoint為(0.0, 0.0)谤绳,并進行旋轉(zhuǎn):

        layer.anchorPoint = CGPoint(x: 0.0, y: 0.0)
        layer.transform = CATransform3DMakeRotation(.pi / 4.0, 0, 0, 1)

效果如下:

CAAnchorPointTransform.gif

可以指定anchorPoint的x、y值小于0袒哥、大于1缩筛,使anchorPoint置于圖層之外。

視圖的frame堡称、boundscenter屬性僅僅是存取方法瞎抛。操縱視圖的frame時,實際上是在改變位于視圖下方CALayerframe却紧,不能夠獨立于圖層之外改變視圖的frame桐臊。

對于視圖或圖層來說,frame并不是一個非常清晰的屬性晓殊,它其實是一個虛擬屬性断凶,由boundspositiontransform計算得出巫俺。任何一個值變化认烁,frame都可能發(fā)生變化。改變frame同樣可能會影響到它們的值。

對圖層做變換的時候(如旋轉(zhuǎn)却嗡、縮放)舶沛,frame實際上代表了覆蓋在圖層旋轉(zhuǎn)之后整個軸對齊的矩形區(qū)域。此時窗价,frame的寬高可能和bounds的寬高不一致如庭。

CATransformFrame.jpeg

3.3 從三個維度操縱圖層

每個 layer 有兩個變換矩陣(Transform Matrices),變換矩陣可以用以操縱 layer 和 contents撼港。CALayertransform屬性指定圖層及其子圖層的變換矩陣柱彻。通常使用transform對圖層進行臨時縮放、旋轉(zhuǎn)餐胀、偏移哟楷。sublayerTransform定義子圖層額外的變換矩陣。

Transform 通過將坐標乘以矩陣值否灾,得出變換后的坐標卖擅。因為 Core Animation 的值由三個維度指定,每個坐標點有四個值墨技,這些點需乘以4*4矩陣惩阶。Core Animation 提供了縮放、偏移扣汪、旋轉(zhuǎn)的矩陣断楷。

CAtransform_basic_math.png

下圖顯示了一些常見變換矩陣配置。任何矩陣乘以 transform identify崭别,都會返回相同坐標冬筒。對于其他轉(zhuǎn)換,根據(jù)改變類型選取矩陣茅主。例如舞痰,要偏移x軸,提供非零的tx诀姚,值為0的ty响牛、yz矩陣。對于旋轉(zhuǎn)赫段,提供合適的 sine 和 cosine 值和旋轉(zhuǎn)角度呀打。

CAtransform_manipulations.png

4. 圖層樹反應不同方面的動畫狀態(tài)

使用 Core Animation 的 app 具有三組圖層對象,每組對象具有不同作用糯笙。

  • Model layer tree:app 與 model layer tree 交互最為頻繁贬丛,存儲了動畫的目標值。
  • Presentation tree:動畫進行過程中此刻的值炬丸,不要嘗試修改 presentation tree 中的值瘫寝。用該對象讀取動畫當前位置的值蜒蕾,可以用以從當前位置開啟新的動畫。
  • Render tree:真正執(zhí)行動畫的圖層焕阿,為 Core Animation 私有咪啡。

每一組圖層都組織為一個層次結構。對于所有圖層都關聯(lián)視圖的應用暮屡,圖層和視圖的初始層次結構相同撤摸。想要避免視圖相關開銷,且確定不需要視圖相關功能時褒纲,可以單獨創(chuàng)建准夷、添加圖層。下圖顯示了一個 iOS app 分解圖莺掠。窗口包含一個 content view衫嵌,content view 包含 button view 和兩個 layer 對象。layer 層級如下:

CAsublayer_hierarchy.png

Layer tree 中的對象彻秆,在 presentation tree 和 render tree 中有對應對象楔绞。App 主要使用 layer tree 中圖層,有時使用 presentation tree 中對象唇兑。通過 layer tree 對象的presentation()屬性獲取 presentation tree 中對應的 layer酒朵,這樣可以獲取到動畫此刻的值。如下所示:

CAsublayer_hierarchies.png

只有動畫正在進行時扎附,才可以使用presentation()屬性獲取 presentation tree 中對象蔫耽。其他時刻調(diào)用presentation()可能產(chǎn)生無法預期的結果。Layer tree 對象的值代表最后一次用代碼設置的值留夜。

5. Layer 和 View 關系

在 iOS 中匙铡,每個UIView都由 Core Animation 的CALayer支持。因此香伴,使用UIView時就在使用CALayer慰枕。這一點與 macOS 上的NSView不同具则,NSView在 Core Animation 之前就已存在即纲。UIView是對NSView的輕量級包裝。

View 特點如下:

  • 復雜層級結構博肋,自動布局低斋。
  • 與用戶交互,響應鏈匪凡。
  • 在主線程的 CPU 中執(zhí)行自定義繪制邏輯膊畴。
  • 靈活、強大病游,有很多子類唇跨。

Layer 特點如下:

  • 層級結構簡單稠通,渲染速度快,不支持自動布局买猖。
  • 沒有響應鏈的開銷改橘。
  • 在 GPU 中渲染。
  • 不太靈活玉控,子類偏少飞主。

直接使用CALayer并不能獲得明顯性能提升。相比使用UIView高诺,使用CALayer可以開發(fā)同時在 iOS碌识、macOS 上運行的app。UIViewNSView有很多不同虱而,但CALayer在 iOS筏餐、macOS 上幾乎相同。

UIView的 animation 可以滿足大部分動畫需求牡拇,遇到UIView不能實現(xiàn)的復雜動畫時胖烛,需要借助 Core Animation實現(xiàn)。在 iOS 10 中诅迷,Apple在UIKit中增加了UIViewPropertyAnimator類佩番,使用該類實現(xiàn)的動畫可以在結束前進行暫停、恢復罢杉、停止等操作趟畏。UIViewPropertyAnimator借助物理引擎,實現(xiàn)了碰撞滩租、彈性等效果赋秀。

Demo名稱:CoreAnimation
源碼地址:https://github.com/pro648/BasicDemos-iOS/tree/master/CoreAnimation

下一篇:CGAffineTransform和CATransform3D

參考資料:

  1. What are the differences between a UIView and a CALayer?
  2. iOS Brownbag: View vs. Layers (including Clock Demo)
  3. Core Animation Basics
  4. 圖層幾何學
  5. Always use integral numbers for the width and height of your layer.

歡迎更多指正:https://github.com/pro648/tips

本文地址:https://github.com/pro648/tips/blob/master/sources/CoreAnimation基本介紹.md

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市律想,隨后出現(xiàn)的幾起案子猎莲,更是在濱河造成了極大的恐慌,老刑警劉巖技即,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件著洼,死亡現(xiàn)場離奇詭異,居然都是意外死亡而叼,警方通過查閱死者的電腦和手機身笤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來葵陵,“玉大人液荸,你說我怎么就攤上這事⊥迅荩” “怎么了娇钱?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵伤柄,是天一觀的道長。 經(jīng)常有香客問我文搂,道長响迂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任细疚,我火速辦了婚禮蔗彤,結果婚禮上,老公的妹妹穿的比我還像新娘疯兼。我一直安慰自己然遏,他們只是感情好,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布吧彪。 她就那樣靜靜地躺著待侵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪姨裸。 梳的紋絲不亂的頭發(fā)上秧倾,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機與錄音傀缩,去河邊找鬼那先。 笑死,一個胖子當著我的面吹牛赡艰,可吹牛的內(nèi)容都是我干的漆改。 我是一名探鬼主播徽鼎,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼召廷,長吁一口氣:“原來是場噩夢啊……” “哼句灌!你這毒婦竟也來了?” 一聲冷哼從身側響起料身,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤汤纸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后芹血,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贮泞,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年祟牲,在試婚紗的時候發(fā)現(xiàn)自己被綠了隙畜。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡说贝,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出慎颗,到底是詐尸還是另有隱情乡恕,我是刑警寧澤言询,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站傲宜,受9級特大地震影響运杭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜函卒,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一辆憔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧报嵌,春花似錦虱咧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至血筑,卻和暖如春绘沉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背豺总。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工车伞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人喻喳。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓帖世,卻偏偏與公主長得像,于是被迫代替她去往敵國和親沸枯。 傳聞我的和親對象是個殘疾皇子日矫,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

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