iOS動畫集錦(Core Animation)

iOS 動畫主要是指 Core Animation 框架, Core AnimationiOSOS X 平臺上負(fù)責(zé)圖形渲染與動畫的基礎(chǔ)框架。Core Animation 可以作用于動畫視圖或者其他可視元素,可以完成動畫所需的大部分繪幀工作。Core Animation 系統(tǒng)已經(jīng)進行了封裝, 所以在使用的時候你只需要配置少量的動畫參數(shù)(如開始點的位置和結(jié)束點的位置)即可使用 Core Animation 的多種動畫效果。Core Animation 將大部分實際的繪圖任務(wù)交給了圖形硬件(GPU)來處理,圖形硬件會加速圖形渲染的速度。這種自動化的圖形加速技術(shù)讓動畫擁有更高的幀率并且顯示效果更加平滑,不會加重CPU的負(fù)擔(dān)而影響程序的運行速度。

本文主要總結(jié)下平時常用的動畫, 如: 基礎(chǔ)動畫(CABasicAnimation)、關(guān)鍵幀動畫(CAKeyframeAnimation)、組動畫(CAAnimationGroup)、過渡動畫(CATransition), 最后也擴展了下, 做了進度條、貝塞爾曲線畫心??、彈球、釘釘效果、點贊等動畫,希望對大家有所幫助.
github: https://github.com/YTiOSer/YTAnimation

Core Animation.jpeg

一、Core Animation類簡介

  1. 首先通過官方的 Core Animation 類圖了解下各個類之間的關(guān)系. 官網(wǎng)鏈接:Core Animation

    Core Animation.png

    建議詳細(xì)看下上圖, 這里對 CAAnimation 的子類和相互關(guān)系及屬性介紹的比較詳細(xì), 看完后會對各個動畫類型有個大概的了解.

  2. 接下來詳細(xì)介紹下動畫的各個屬性及作用

  • fromValue: 動畫的開始值(Any類型, 根據(jù)動畫不同可以是CGPoint、NSNumber等)
  • toValue: 動畫的結(jié)束值, 和fromValue類似
  • beginTime: 動畫的開始時間
  • duration : 動畫的持續(xù)時間
  • repeatCount : 動畫的重復(fù)次數(shù)
  • fillMode: 動畫的運行場景
  • isRemovedOnCompletion: 完成后是否刪除動畫
  • autoreverses: 執(zhí)行的動畫按照原動畫返回執(zhí)行
  • path:關(guān)鍵幀動畫中的執(zhí)行路徑
  • values: 關(guān)鍵幀動畫中的關(guān)鍵點數(shù)組
  • animations: 組動畫中的動畫數(shù)組
  • delegate : 動畫代理, 封裝了動畫的執(zhí)行和結(jié)束方法
  • timingFunction: 控制動畫的顯示節(jié)奏, 系統(tǒng)提供五種值選擇,分別是:
    1.kCAMediaTimingFunctionDefault( 默認(rèn),中間快)
    2.kCAMediaTimingFunctionLinear (線性動畫)
    3.kCAMediaTimingFunctionEaseIn (先慢后快 慢進快出)
    4.kCAMediaTimingFunctionEaseOut (先塊后慢快進慢出)
    5.kCAMediaTimingFunctionEaseInEaseOut (先慢后快再慢)
  • type: 過渡動畫的動畫類型,系統(tǒng)提供了多種過渡動畫, 分別是:
    1: fade (淡出 默認(rèn))
    2: moveIn (覆蓋原圖)
    3: push (推出)
    4: fade (淡出 默認(rèn))
    5: reveal (底部顯示出來)
    6: cube (立方旋轉(zhuǎn))
    7: suck (吸走)
    8: oglFlip (水平翻轉(zhuǎn) 沿y軸)
    9: ripple (滴水效果)
    10: curl (卷曲翻頁 向上翻頁)
    11: unCurl (卷曲翻頁返回 向下翻頁)
    12: caOpen (相機開啟)
    13: caClose (相機關(guān)閉)
  • subtype : 過渡動畫的動畫方向, 系統(tǒng)提供了四種,分別是:
    1.fromLeft( 從左側(cè))
    2.fromRight (從右側(cè))
    3.fromTop (有上面)
    4.fromBottom (從下面)

二、Core Animation的使用

1. 基礎(chǔ)動畫( CABasicAnimation )

基礎(chǔ)動畫主要提供了對于CALayer對象中的可變屬性進行簡單動畫的操作。比如:位移、旋轉(zhuǎn)、縮放、透明度、背景色等。
基礎(chǔ)動畫根據(jù) keyPath 來區(qū)分不同的動畫,, 系統(tǒng)提供了多個類型,如: transform.scale (比例轉(zhuǎn)換)、transform.scale.xtransform.scale.ytransform.rotation(旋轉(zhuǎn)) 、transform.rotation.x(繞x軸旋轉(zhuǎn))、transform.rotation.y(繞y軸旋轉(zhuǎn))、transform.rotation.z(繞z軸旋轉(zhuǎn))、opacity (透明度)、marginbackgroundColor(背景色)、cornerRadius(圓角)、borderWidth(邊框?qū)?、boundscontentscontentsRectcornerRadiusframehiddenmaskmasksToBoundsshadowColor(陰影色)、shadowOffsetshadowOpacityshadowOpacity, 在使用時候, 需要根據(jù)具體的需求選擇合適的.

效果圖如下:


旋轉(zhuǎn).gif
  • 位移動畫
 func positionAnimation() {
        
        let animation = CABasicAnimation.init(keyPath: "position") //keyPath為系統(tǒng)提供
        animation.fromValue = CGPoint.init(x: margin_ViewMidPosition, y: kScreenH / 2 - margin_Top)
        animation.toValue = CGPoint.init(x: kScreenW - margin_ViewMidPosition, y: kScreenH / 2 - margin_Top)
        animation.duration = 1.0
        view_Body.layer.add(animation, forKey: "positionAnimation") //key自定義
    }
  • 旋轉(zhuǎn)動畫:
    func rotateAnimation() {
        
        let animation = CABasicAnimation.init(keyPath: "transform.rotation.z")
        animation.toValue = NSNumber.init(value: Double.pi)
        animation.duration = 0.1
        animation.repeatCount = 1e100 //無限大重復(fù)次數(shù)
        view_Body.layer.add(animation, forKey: "rotateAnimation")
    }
  • 縮放動畫
 func scaleAnimation() {
        
        let animation = CABasicAnimation.init(keyPath: "transform.scale")
        animation.toValue = NSNumber.init(value: 2.0)
        animation.duration = 1.0
        view_Body.layer.add(animation, forKey: "scaleAnimation")
    }
  • 透明度動畫
func opacityAnimation() {
        
        let animation = CABasicAnimation.init(keyPath: "opacity")
        animation.fromValue = NSNumber.init(value: 1.0)
        animation.toValue = NSNumber.init(value: 0.0)
        animation.duration = 1.0
        view_Body.layer.add(animation, forKey: "opacityAnimation")
    }
  • 背景色動畫
 func backgroundColorAnimation() {
        
        let animation = CABasicAnimation.init(keyPath: "backgroundColor")
        animation.toValue = UIColor.green.cgColor //因為layer層動畫, 所以需要使用cgColor
        animation.duration = 1.0
        view_Body.layer.add(animation, forKey: "backgroundColorAnimation")
    }

2. 關(guān)鍵幀動畫( CAKeyframeAnimation )

CAKeyframeAnimationCABasicAnimation 都屬于CAPropertyAnimatin 的子類。不同的是 CABasicAnimation 只能從一個數(shù)值(fromValue)變換成另一個數(shù)值(toValue),而 CAKeyframeAnimation 則會使用一個數(shù)組(values) 保存一組關(guān)鍵幀, 也可以給定一個路徑(path)制作動畫。

CAKeyframeAnimation主要有 三個 重要屬性:

  • values:存放關(guān)鍵幀(keyframe)的數(shù)組,動畫對象會在指定的時間(duration)內(nèi),依次顯示values數(shù)組中的每一個關(guān)鍵幀 .
  • path:可以設(shè)置一個 CGPathRefCGMutablePathRef,讓層跟著路徑移動. path 只對 CALayeranchorPointposition 起作用, 如果設(shè)置了path,那么values將被忽略.
  • keyTimes:可以為對應(yīng)的關(guān)鍵幀指定對應(yīng)的時間點,其取值范圍為0到1.0, keyTimes 中的每一個時間值都對應(yīng) values 中的每一幀.當(dāng) keyTimes 沒有設(shè)置的時候,各個關(guān)鍵幀的時間是根據(jù) duration 平分的。

以抖動截圖為例, 效果圖如下:


抖動.gif

動畫代碼如下:

  • 關(guān)鍵幀動畫
func keyFrameAnimation() {
        
        let animation = CAKeyframeAnimation.init(keyPath: "position")
        let value_0 = CGPoint.init(x: margin_ViewMidPosition, y: kScreenH / 2 - margin_ViewWidthHeight)
        let value_1 = CGPoint.init(x: kScreenW / 3, y: kScreenH / 2 - margin_ViewWidthHeight)
        let value_2 = CGPoint.init(x: kScreenW / 3, y: kScreenH / 2 + margin_ViewMidPosition)
        let value_3 = CGPoint.init(x: kScreenW * 2 / 3, y: kScreenH / 2 + margin_ViewMidPosition)
        let value_4 = CGPoint.init(x: kScreenW * 2 / 3, y: kScreenH / 2 - margin_ViewWidthHeight)
        let value_5 = CGPoint.init(x: kScreenW - margin_ViewMidPosition, y: kScreenH / 2 - margin_ViewWidthHeight)
        animation.values = [value_0, value_1, value_2, value_3, value_4, value_5]
        animation.duration = 2.0
        view_Body.layer.add(animation, forKey: "keyFrameAnimation")
    }
  • 路徑動畫
func pathAnimation() {
        
        let animation = CAKeyframeAnimation.init(keyPath: "position")
        let path = UIBezierPath.init(arcCenter: CGPoint.init(x: kScreenW / 2, y: kScreenH / 2), radius: 60, startAngle: 0.0, endAngle: .pi * 2, clockwise: true)
        animation.duration = 2.0
        animation.path = path.cgPath
        view_Body.layer.add(animation, forKey: "pathAnimation")
    }
  • 抖動動畫
func shakeAnimation() {
        
        let animation = CAKeyframeAnimation.init(keyPath: "transform.rotation")
        let value_0 = NSNumber.init(value: -Double.pi / 180 * 8)
        let value_1 = NSNumber.init(value: Double.pi / 180 * 8)
        animation.values = [value_0, value_1, value_0]
        animation.duration = 1.0
        animation.repeatCount = 1e100
        view_Body.layer.add(animation, forKey: "shakeAnimation")
    }

3. 組動畫( CAAnimationGroup )

CAAnimationGroupCAAnimation 的子類,可以保存一組動畫對象,可以保存基礎(chǔ)動畫、關(guān)鍵幀動畫等,數(shù)組中所有動畫對象可以同時并發(fā)運行, 也可以通過實踐設(shè)置為串行連續(xù)動畫.

效果截圖如下:


組動畫2.gif

動畫代碼如下:

  • 同時
   //同時
    func sameTimeAnimation() {
        
        let animation_Position = CAKeyframeAnimation.init(keyPath: "position")
        let value_0 = CGPoint.init(x: margin_ViewMidPosition, y: kScreenH / 2 - margin_ViewMidPosition)
        let value_1 = CGPoint.init(x: kScreenW / 3, y: kScreenH / 2 - margin_ViewMidPosition)
        let value_2 = CGPoint.init(x: kScreenW / 3, y: kScreenH / 2 + margin_ViewMidPosition)
        let value_3 = CGPoint.init(x: kScreenW / 3 * 2, y: kScreenH / 2 + margin_ViewMidPosition)
        let value_4 = CGPoint.init(x: kScreenW / 3 * 2, y: kScreenH / 2 - margin_ViewMidPosition)
        let value_5 = CGPoint.init(x: kScreenW - margin_ViewMidPosition, y: kScreenH / 2 - margin_ViewMidPosition)
        animation_Position.values = [value_0, value_1, value_2, value_3, value_4, value_5]
        
        let animation_BGColor = CABasicAnimation.init(keyPath: "backgroundColor")
        animation_BGColor.toValue = UIColor.green.cgColor
        
        let animation_Rotate = CABasicAnimation.init(keyPath: "transform.rotation")
        animation_Rotate.toValue = NSNumber.init(value: Double.pi * 4)
        
        let animation_Group = CAAnimationGroup()
        animation_Group.animations = [animation_Position, animation_BGColor, animation_Rotate]
        animation_Group.duration = 4.0
        view_Body.layer.add(animation_Group, forKey: "groupAnimation")
    }
  • 連續(xù)
 //連續(xù)動畫 最主要的是處理好各個動畫時間的銜接
    func goOnAnimation() {
        
        //定義一個動畫開始的時間
        let currentTime = CACurrentMediaTime()
        
        let animation_Position = CABasicAnimation.init(keyPath: "position")
        animation_Position.fromValue = CGPoint.init(x: margin_ViewMidPosition, y: kScreenH / 2)
        animation_Position.toValue = CGPoint.init(x: kScreenW / 2, y: kScreenH / 2)
        animation_Position.duration = 1.0
        animation_Position.fillMode = "forwards" //只在前臺
        animation_Position.isRemovedOnCompletion = false //切出界面再回來動畫不會停止
        animation_Position.beginTime = currentTime
        view_Body.layer.add(animation_Position, forKey: "positionAnimation")
        
        let animation_Scale = CABasicAnimation.init(keyPath: "transform.scale")
        animation_Scale.fromValue = NSNumber.init(value: 0.7)
        animation_Scale.toValue = NSNumber.init(value: 2.0)
        animation_Scale.duration = 1.0
        animation_Scale.fillMode = "forwards"
        animation_Scale.isRemovedOnCompletion = false
        animation_Scale.beginTime = currentTime + 1.0
        view_Body.layer.add(animation_Scale, forKey: "scaleAnimation")
        
        let animation_Rotate = CABasicAnimation.init(keyPath: "transform.rotation")
        animation_Rotate.toValue = NSNumber.init(value: Double.pi * 4)
        animation_Rotate.duration = 1.0
        animation_Rotate.fillMode = "forwards"
        animation_Rotate.isRemovedOnCompletion = false
        animation_Rotate.beginTime = currentTime + 2.0
        view_Body.layer.add(animation_Rotate, forKey: "rotateAnimation")
    }

4. 過渡動畫( CATransition )

CATransitionCAAnimation 的子類,用于做過渡動畫或者 轉(zhuǎn)場 動畫,能夠為層提供移出屏幕和移入屏幕的動畫效果。

過渡動畫通過 type 設(shè)置不同的動畫效果, CATransition 有多種過渡效果, 但其實 Apple 官方的SDK只提供了種:

  • fade 淡出 默認(rèn)
  • moveIn 覆蓋原圖
  • push 推出
  • reveal 底部顯示出來

私有API提供了其他很多非常炫的過渡動畫,如 cube(立方旋轉(zhuǎn))、suckEffect(吸走)、oglFlip(水平翻轉(zhuǎn) 沿y軸)、 rippleEffect(滴水效果)、pageCurl(卷曲翻頁 向上翻頁)、pageUnCurl(卷曲翻頁 向下翻頁)、cameraIrisHollowOpen(相機開啟)、cameraIrisHollowClose(相機關(guān)閉)等。

: 因 Apple 不提供維護,并且有可能造成你的app審核不通過, 所以不建議開發(fā)者們使用這些私有API.

效果如下:


過渡動畫.gif

翻頁動畫代碼如下:

 func curlAnimation() {
        
        let animation_Curl = CATransition()
        animation_Curl.type = "pageCurl"
        animation_Curl.subtype = "fromRight"
        animation_Curl.duration = 1.0
        view_Body.layer.add(animation_Curl, forKey: "curlAnimation")
    }

5. 項目案例

  1. 進度條
    效果如下:
    進度條.gif

    這里主要用到了 CAShapeLayer + CAGradientLayer, 使用 CAGradientLayer 畫進度圈(GPU執(zhí)行, 高效), 然后使用 CAGradientLayer 漸變色layer, 結(jié)合動畫顯示進度條.
    代碼如下:
  • UI視圖
func createView() {
        
        label_Progress = UILabel()
        label_Progress.text = ""
        label_Progress.textAlignment = .center
        label_Progress.font = UIFont.systemFont(ofSize: 25)
        addSubview(label_Progress)
        label_Progress.snp.makeConstraints { (make) in
            make.centerX.centerY.equalTo(self)
            make.width.equalTo(kScreenW)
            make.height.equalTo(30)
        }
        
        layer_BackPath = CAShapeLayer()
        layer_BackPath.fillColor = UIColor.clear.cgColor //填充顏色
        layer_BackPath.strokeColor = UIColor.white.withAlphaComponent(0.5).cgColor //劃線顏色
        layer_BackPath.lineWidth = width_MainPath
        layer.addSublayer(layer_BackPath)
        
        layer_MainPathLayer = CAShapeLayer()
        layer_MainPathLayer.fillColor = UIColor.clear.cgColor
        layer_MainPathLayer.strokeColor = UIColor.white.cgColor
        layer_MainPathLayer.lineWidth = width_MainPath
        layer.addSublayer(layer_MainPathLayer)
        
        //漸變色
        layer_Gradient = CAGradientLayer()
        layer_Gradient.frame = CGRect.init(x: 0, y: 0, width: kScreenW, height: kScreenH)
        layer_Gradient.type = "axial" //線性變化  默認(rèn)目前只有這一個type
        layer_Gradient.colors = [UIColor.init(hex: 0xf31414).cgColor, UIColor.init(hex: 0xf27200).cgColor, UIColor.init(hex: 0xffff00).cgColor, UIColor.init(hex: 0x2bee22).cgColor, UIColor.init(hex: 0x32a7eb).cgColor]
        layer_Gradient.locations = [0, 0.3, 0.5, 0.7, 1] //每個漸變顏色的終止位置,這些值必須是遞增的,數(shù)組的長度和colors的長度最好一致
        //startPoint endPoint 分別表示漸變層的起始位置和終止位置,這兩個點被定義在一個單元坐標(biāo)空間,[0,0]表示左上角位置,[1,1]表示右下角位置,默認(rèn)值分別是[.5,0] and [.5,1];
        layer_Gradient.startPoint = CGPoint.init(x: 0, y: 0)
        layer_Gradient.endPoint = CGPoint.init(x: 1, y: 0)
        layer.addSublayer(layer_Gradient)
        
    }
  • 進度
func drawCircle(){
        
        //貝塞爾曲線畫圓
        let path_Back = UIBezierPath.init(arcCenter: CGPoint.init(x: kScreenW / 2, y: kScreenH / 2), radius: kScreenW / 5 - width_MainPath, startAngle: CGFloat.pi, endAngle: CGFloat.pi * 3, clockwise: true)
        let path_Main = UIBezierPath.init(arcCenter: CGPoint.init(x: kScreenW / 2, y: kScreenH / 2), radius: kScreenW / 5 - width_MainPath + 3, startAngle: CGFloat.pi, endAngle: CGFloat.pi * 3, clockwise: true)
        
        layer_BackPath.path = path_Back.cgPath
        layer_MainPathLayer.path = path_Main.cgPath
        
        layer_Gradient.mask = layer_MainPathLayer //用 layer_MainPathLayer 截取漸變層
        
        //動畫 顯示路徑
        let animation = CABasicAnimation.init(keyPath: "strokeEnd")
        animation.duration = CFTimeInterval(Double(progress) * 0.01)
        animation.fromValue = NSNumber.init(value: 0)
        animation.toValue = NSNumber.init(value: Double(progress) * 0.01)
        animation.fillMode = "forwards"
        animation.isRemovedOnCompletion = false //完成后不刪除動畫
        layer_MainPathLayer.add(animation, forKey: "strokeEndAnimation")
        
        if progress > 0{
            DispatchQueue.global().async {
                self.timer_ProgressLabel = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(YTProgressView.progressLabelTimerAction), userInfo: nil, repeats: true)
                RunLoop.current.run()
            }
        }else{
            label_Progress.text = "0%"
        }
        
    }
    
    func progressLabelTimerAction() {
        
        DispatchQueue.main.async {
            self.label_Progress.text = String(self.num_Progress) + "%"
        }
        
        if num_Progress >= progress{ //銷毀計時器
            timer_ProgressLabel.invalidate()
            timer_ProgressLabel = nil
        }else{
            num_Progress += 1
        }
        
    }

這里只展示了核心代碼, 詳細(xì)代碼可到github下載完整代碼: https://github.com/YTiOSer/YTAnimation

  1. 彈球, 仿Path菜單效果
  • 點擊紅色按鈕,紅色按鈕旋轉(zhuǎn)。(旋轉(zhuǎn)動畫
  • 黑色小按鈕依次彈出,并且?guī)в行D(zhuǎn)效果。(位移動畫、旋轉(zhuǎn)動畫、組動畫
  • 點擊黑色小按鈕,其他按鈕消失,被點擊的黑色按鈕變大變淡消失。(縮放動畫、alpha動畫、組動畫
    tanqiu.gif
  1. 仿釘釘菜單效果


    dingding.png

    動畫實現(xiàn)用到了位移動畫和縮放動畫, 其實不難.

  2. 點贊


    點贊.gif

三、總結(jié)

看完整篇文章相信你對 iOS 中的動畫有了一個詳細(xì)的了解, 其實單個動畫都是比較簡單的, 而復(fù)雜的動畫其實都是由一個個簡單的動畫組裝而成的,所以遇到比較難得動畫需求, 我們只要充分組裝不同的動畫,就能實現(xiàn)出滿意的效果.

好記性不如爛筆頭, 光說不練假把戲, 建議大家結(jié)合我的代碼, 自己邊看邊練習(xí), 這樣才能記得牢, 才能轉(zhuǎn)換成自己的知識.

github: https://github.com/YTiOSer/YTAnimation

如果覺得對你還有些用,給個喜歡關(guān)注吧。你的支持是我繼續(xù)的動力。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,179評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,444評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,948評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,185評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,717評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,794評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,414評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,750評論 2 370

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