自定義View進(jìn)階篇《六》——Path之貝塞爾曲線

一、Path常用方法表

二.Path詳解

上一次除了一些常用函數(shù)之外啰脚,講解的基本上都是直線殷蛇,本次需要了解其中的曲線部分,說(shuō)到曲線,就不得不提大名鼎鼎的貝塞爾曲線橄浓。

貝塞爾曲線能干什么粒梦?

貝塞爾曲線的運(yùn)用是十分廣泛的,可以說(shuō)貝塞爾曲線奠定了計(jì)算機(jī)繪圖的基礎(chǔ)(因?yàn)樗梢詫⑷魏螐?fù)雜的圖形用精確的數(shù)學(xué)語(yǔ)言進(jìn)行描述)贮配,在你不經(jīng)意間就已經(jīng)使用過(guò)它了谍倦。
你會(huì)使用Photoshop的話,你可能會(huì)注意到里面有一個(gè)鋼筆工具泪勒,這個(gè)鋼筆工具核心就是貝塞爾曲線昼蛀。

你說(shuō)你不會(huì)PS宴猾? 沒(méi)關(guān)系,你如果看過(guò)前面的文章或者用過(guò)2D繪圖叼旋,肯定繪制過(guò)圓仇哆,圓弧,圓角矩形等這些東西夫植。這里面的圓弧部分全部都是貝塞爾曲線的運(yùn)用讹剔。
貝塞爾曲線作用十分廣泛,簡(jiǎn)單舉幾個(gè)的栗子:

  • QQ小紅點(diǎn)拖拽效果
  • 一些炫酷的下拉刷新控件
  • 閱讀軟件的翻書(shū)效果
  • 一些平滑的折線圖的制作
  • 很多炫酷的動(dòng)畫(huà)效果
第一步.理解貝塞爾曲線的原理

此處理解貝塞爾曲線并非是學(xué)會(huì)公式的推導(dǎo)過(guò)程(推倒(?*?ω?)?)详民,而是要了解貝塞爾曲線是如何生成的延欠。
貝塞爾曲線是用一系列點(diǎn)來(lái)控制曲線狀態(tài)的,我將這些點(diǎn)簡(jiǎn)單分為兩類(lèi):


一階曲線原理:

一階曲線是沒(méi)有控制點(diǎn)的沈跨,僅有兩個(gè)數(shù)據(jù)點(diǎn)(A 和 B)由捎,最終效果一個(gè)線段。



上圖表示的是一階曲線生成過(guò)程中的某一個(gè)階段饿凛,動(dòng)態(tài)過(guò)程可以參照下圖(本文中貝塞爾曲線相關(guān)的動(dòng)態(tài)演示圖片來(lái)自維基百科)狞玛。


PS:一階曲線其實(shí)就是前面講解過(guò)的lineTo。

二階曲線原理:

二階曲線由兩個(gè)數(shù)據(jù)點(diǎn)(A 和 C)涧窒,一個(gè)控制點(diǎn)(B)來(lái)描述曲線狀態(tài)心肪,大致如下:



上圖中紅色曲線部分就是傳說(shuō)中的二階貝塞爾曲線,那么這條紅色曲線是如何生成的呢纠吴?接下來(lái)我們就以其中的一個(gè)狀態(tài)分析一下:



連接AB BC硬鞍,并在AB上取點(diǎn)D,BC上取點(diǎn)E呜象,使其滿足條件:


連接DE膳凝,取點(diǎn)F,使得:


這樣獲取到的點(diǎn)F就是貝塞爾曲線上的一個(gè)點(diǎn)恭陡,動(dòng)態(tài)過(guò)程如下:


PS: 二階曲線對(duì)應(yīng)的方法是quadTo
Path path = new Path();
path.moveTo(start.x,start.y);
path.quadTo(control.x,control.y,end.x,end.y);
canvas.drawPath(path, mPaint);

三階曲線原理:

三階曲線由兩個(gè)數(shù)據(jù)點(diǎn)(A 和 D)蹬音,兩個(gè)控制點(diǎn)(B 和 C)來(lái)描述曲線狀態(tài),如下:



三階曲線計(jì)算過(guò)程與二階類(lèi)似休玩,具體可以見(jiàn)下圖動(dòng)態(tài)效果:


PS: 三階曲線對(duì)應(yīng)的方法是cubicTo
Path path = new Path();
path.moveTo(start.x, start.y);
path.cubicTo(control1.x, control1.y, control2.x,control2.y, end.x, end.y);
canvas.drawPath(path, mPaint);

貝塞爾曲線速查表
強(qiáng)烈推薦點(diǎn)擊這里練習(xí)貝塞爾曲線著淆,可以加深對(duì)貝塞爾曲線的理解程度。

第二步.了解貝塞爾曲線相關(guān)函數(shù)使用方法
一階曲線:

一階曲線是一條線段拴疤,非常簡(jiǎn)單永部,可以參見(jiàn)上一篇文章Path之基本操作,此處就不詳細(xì)講解了呐矾。

二階曲線:

通過(guò)上面對(duì)二階曲線的簡(jiǎn)單了解苔埋,我們知道二階曲線是由兩個(gè)數(shù)據(jù)點(diǎn),一個(gè)控制點(diǎn)構(gòu)成蜒犯,接下來(lái)我們就用一個(gè)實(shí)例來(lái)演示二階曲線是如何運(yùn)用的组橄。
首先荞膘,兩個(gè)數(shù)據(jù)點(diǎn)是控制貝塞爾曲線開(kāi)始和結(jié)束的位置,比較容易理解玉工,而控制點(diǎn)則是控制貝塞爾的彎曲狀態(tài)羽资,相對(duì)來(lái)說(shuō)比較難以理解,所以本示例重點(diǎn)在于理解貝塞爾曲線彎曲狀態(tài)與控制點(diǎn)的關(guān)系遵班,廢話不多說(shuō)屠升,先上效果圖:


為了更加容易看出控制點(diǎn)與曲線彎曲程度的關(guān)系,上圖中繪制出了輔助點(diǎn)和輔助線狭郑,從上面的動(dòng)態(tài)圖可以看出腹暖,貝塞爾曲線在動(dòng)態(tài)變化過(guò)程中有類(lèi)似于橡皮筋一樣的彈性效果,因此在制作一些彈性效果的時(shí)候很常用愿阐。

public class Bezier extends View {

    private Paint mPaint;
    private int centerX, centerY;

    private PointF start, end, control;

    public Bessel1(Context context) {
        super(context);
        mPaint = new Paint();
        mPaint.setColor(Color.BLACK);
        mPaint.setStrokeWidth(8);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setTextSize(60);

        start = new PointF(0,0);
        end = new PointF(0,0);
        control = new PointF(0,0);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        centerX = w/2;
        centerY = h/2;

        // 初始化數(shù)據(jù)點(diǎn)和控制點(diǎn)的位置
        start.x = centerX-200;
        start.y = centerY;
        end.x = centerX+200;
        end.y = centerY;
        control.x = centerX;
        control.y = centerY-100;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 根據(jù)觸摸位置更新控制點(diǎn)微服,并提示重繪
        control.x = event.getX();
        control.y = event.getY();
        invalidate();
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // 繪制數(shù)據(jù)點(diǎn)和控制點(diǎn)
        mPaint.setColor(Color.GRAY);
        mPaint.setStrokeWidth(20);
        canvas.drawPoint(start.x,start.y,mPaint);
        canvas.drawPoint(end.x,end.y,mPaint);
        canvas.drawPoint(control.x,control.y,mPaint);

        // 繪制輔助線
        mPaint.setStrokeWidth(4);
        canvas.drawLine(start.x,start.y,control.x,control.y,mPaint);
        canvas.drawLine(end.x,end.y,control.x,control.y,mPaint);

        // 繪制貝塞爾曲線
        mPaint.setColor(Color.RED);
        mPaint.setStrokeWidth(8);

        Path path = new Path();

        path.moveTo(start.x,start.y);
        path.quadTo(control.x,control.y,end.x,end.y);

        canvas.drawPath(path, mPaint);
    }
}
三階曲線:

三階曲線由兩個(gè)數(shù)據(jù)點(diǎn)和兩個(gè)控制點(diǎn)來(lái)控制曲線狀態(tài)。


public class Bezier2 extends View {

    private Paint mPaint;
    private int centerX, centerY;

    private PointF start, end, control1, control2;
    private boolean mode = true;

    public Bezier2(Context context) {
        this(context, null);

    }

    public Bezier2(Context context, AttributeSet attrs) {
        super(context, attrs);

        mPaint = new Paint();
        mPaint.setColor(Color.BLACK);
        mPaint.setStrokeWidth(8);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setTextSize(60);

        start = new PointF(0, 0);
        end = new PointF(0, 0);
        control1 = new PointF(0, 0);
        control2 = new PointF(0, 0);
    }

    public void setMode(boolean mode) {
        this.mode = mode;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        centerX = w / 2;
        centerY = h / 2;

        // 初始化數(shù)據(jù)點(diǎn)和控制點(diǎn)的位置
        start.x = centerX - 200;
        start.y = centerY;
        end.x = centerX + 200;
        end.y = centerY;
        control1.x = centerX;
        control1.y = centerY - 100;
        control2.x = centerX;
        control2.y = centerY - 100;

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 根據(jù)觸摸位置更新控制點(diǎn)缨历,并提示重繪
        if (mode) {
            control1.x = event.getX();
            control1.y = event.getY();
        } else {
            control2.x = event.getX();
            control2.y = event.getY();
        }
        invalidate();
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //drawCoordinateSystem(canvas);

        // 繪制數(shù)據(jù)點(diǎn)和控制點(diǎn)
        mPaint.setColor(Color.GRAY);
        mPaint.setStrokeWidth(20);
        canvas.drawPoint(start.x, start.y, mPaint);
        canvas.drawPoint(end.x, end.y, mPaint);
        canvas.drawPoint(control1.x, control1.y, mPaint);
        canvas.drawPoint(control2.x, control2.y, mPaint);

        // 繪制輔助線
        mPaint.setStrokeWidth(4);
        canvas.drawLine(start.x, start.y, control1.x, control1.y, mPaint);
        canvas.drawLine(control1.x, control1.y,control2.x, control2.y, mPaint);
        canvas.drawLine(control2.x, control2.y,end.x, end.y, mPaint);

        // 繪制貝塞爾曲線
        mPaint.setColor(Color.RED);
        mPaint.setStrokeWidth(8);

        Path path = new Path();

        path.moveTo(start.x, start.y);
        path.cubicTo(control1.x, control1.y, control2.x,control2.y, end.x, end.y);

        canvas.drawPath(path, mPaint);
    }
}

三階曲線相比于二階曲線可以制作更加復(fù)雜的形狀,但是對(duì)于高階的曲線糙麦,用低階的曲線組合也可達(dá)到相同的效果辛孵,就是傳說(shuō)中的降階。因此我們對(duì)貝塞爾曲線的封裝方法一般最高只到三階曲線缠犀。

降階與升階
第三步.貝塞爾曲線使用實(shí)例

在制作這個(gè)實(shí)例之前欧瘪,首先要明確一個(gè)內(nèi)容框往,就是在什么情況下需要使用貝塞爾曲線?



至于只需要一個(gè)靜態(tài)的曲線圖形的情況冶匹,用圖片豈不是更好,大量的計(jì)算會(huì)很不劃算咆瘟。

如果是顯示SVG矢量圖的話嚼隘,已經(jīng)有相關(guān)的解析工具了(內(nèi)部依舊運(yùn)用的有貝塞爾曲線),不需要手動(dòng)計(jì)算袒餐。
貝塞爾曲線的主要優(yōu)點(diǎn)是可以實(shí)時(shí)控制曲線狀態(tài)飞蛹,并可以通過(guò)改變控制點(diǎn)的狀態(tài)實(shí)時(shí)讓曲線進(jìn)行平滑的狀態(tài)變化。
接下來(lái)我們就用一個(gè)簡(jiǎn)單的示例讓一個(gè)圓漸變成為心形:



思路分析:

我們最終的需要的效果是將一個(gè)圓轉(zhuǎn)變成一個(gè)心形灸眼,通過(guò)分析可知卧檐,圓可以由四段三階貝塞爾曲線組合而成,如下:



心形也可以由四段的三階的貝塞爾曲線組成焰宣,如下:



兩者的差別僅僅在于數(shù)據(jù)點(diǎn)和控制點(diǎn)位置不同霉囚,因此只需要調(diào)整數(shù)據(jù)點(diǎn)和控制點(diǎn)的位置,就能將圓形變?yōu)樾男巍?br> 核心難點(diǎn):
1.如何得到數(shù)據(jù)點(diǎn)和控制點(diǎn)的位置匕积?

關(guān)于使用繪制圓形的數(shù)據(jù)點(diǎn)與控制點(diǎn)早就已經(jīng)有人詳細(xì)的計(jì)算好了盈罐,可以參考stackoverflow的一個(gè)回答How to create circle with Bézier curves?其中的數(shù)據(jù)只需要拿來(lái)用即可逻澳。
而對(duì)于心形的數(shù)據(jù)點(diǎn)和控制點(diǎn),可以由圓形的部分?jǐn)?shù)據(jù)點(diǎn)和控制點(diǎn)平移后得到暖呕,具體參數(shù)可以自己慢慢調(diào)整到一個(gè)滿意的效果斜做。

2.如何達(dá)到漸變效果?

漸變其實(shí)就是每次對(duì)數(shù)據(jù)點(diǎn)和控制點(diǎn)稍微移動(dòng)一點(diǎn)湾揽,然后重繪界面瓤逼,在短時(shí)間多次的調(diào)整數(shù)據(jù)點(diǎn)與控制點(diǎn),使其逐漸接近目標(biāo)值库物,通過(guò)不斷的重繪界面達(dá)到一種漸變的效果霸旗。過(guò)程可以參照下圖動(dòng)態(tài)效果:


public class Bezier3 extends View {
    private static final float C = 0.551915024494f;     // 一個(gè)常量,用來(lái)計(jì)算繪制圓形貝塞爾曲線控制點(diǎn)的位置

    private Paint mPaint;
    private int mCenterX, mCenterY;

    private PointF mCenter = new PointF(0,0);
    private float mCircleRadius = 200;                  // 圓的半徑
    private float mDifference = mCircleRadius*C;        // 圓形的控制點(diǎn)與數(shù)據(jù)點(diǎn)的差值

    private float[] mData = new float[8];               // 順時(shí)針記錄繪制圓形的四個(gè)數(shù)據(jù)點(diǎn)
    private float[] mCtrl = new float[16];              // 順時(shí)針記錄繪制圓形的八個(gè)控制點(diǎn)

    private float mDuration = 1000;                     // 變化總時(shí)長(zhǎng)
    private float mCurrent = 0;                         // 當(dāng)前已進(jìn)行時(shí)長(zhǎng)
    private float mCount = 100;                         // 將時(shí)長(zhǎng)總共劃分多少份
    private float mPiece = mDuration/mCount;            // 每一份的時(shí)長(zhǎng)


    public Bezier3(Context context) {
        this(context, null);

    }

    public Bezier3(Context context, AttributeSet attrs) {
        super(context, attrs);

        mPaint = new Paint();
        mPaint.setColor(Color.BLACK);
        mPaint.setStrokeWidth(8);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setTextSize(60);


        // 初始化數(shù)據(jù)點(diǎn)

        mData[0] = 0;
        mData[1] = mCircleRadius;

        mData[2] = mCircleRadius;
        mData[3] = 0;

        mData[4] = 0;
        mData[5] = -mCircleRadius;

        mData[6] = -mCircleRadius;
        mData[7] = 0;

        // 初始化控制點(diǎn)

        mCtrl[0]  = mData[0]+mDifference;
        mCtrl[1]  = mData[1];

        mCtrl[2]  = mData[2];
        mCtrl[3]  = mData[3]+mDifference;

        mCtrl[4]  = mData[2];
        mCtrl[5]  = mData[3]-mDifference;

        mCtrl[6]  = mData[4]+mDifference;
        mCtrl[7]  = mData[5];

        mCtrl[8]  = mData[4]-mDifference;
        mCtrl[9]  = mData[5];

        mCtrl[10] = mData[6];
        mCtrl[11] = mData[7]-mDifference;

        mCtrl[12] = mData[6];
        mCtrl[13] = mData[7]+mDifference;

        mCtrl[14] = mData[0]-mDifference;
        mCtrl[15] = mData[1];
    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mCenterX = w / 2;
        mCenterY = h / 2;
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
         drawCoordinateSystem(canvas);       // 繪制坐標(biāo)系

        canvas.translate(mCenterX, mCenterY); // 將坐標(biāo)系移動(dòng)到畫(huà)布中央
        canvas.scale(1,-1);                 // 翻轉(zhuǎn)Y軸

        drawAuxiliaryLine(canvas);


        // 繪制貝塞爾曲線
        mPaint.setColor(Color.RED);
        mPaint.setStrokeWidth(8);

        Path path = new Path();
        path.moveTo(mData[0],mData[1]);

        path.cubicTo(mCtrl[0],  mCtrl[1],  mCtrl[2],  mCtrl[3],     mData[2], mData[3]);
        path.cubicTo(mCtrl[4],  mCtrl[5],  mCtrl[6],  mCtrl[7],     mData[4], mData[5]);
        path.cubicTo(mCtrl[8],  mCtrl[9],  mCtrl[10], mCtrl[11],    mData[6], mData[7]);
        path.cubicTo(mCtrl[12], mCtrl[13], mCtrl[14], mCtrl[15],    mData[0], mData[1]);

        canvas.drawPath(path, mPaint);

        mCurrent += mPiece;
        if (mCurrent < mDuration){

            mData[1] -= 120/mCount;
            mCtrl[7] += 80/mCount;
            mCtrl[9] += 80/mCount;

            mCtrl[4] -= 20/mCount;
            mCtrl[10] += 20/mCount;

            postInvalidateDelayed((long) mPiece);
        }
    }

    // 繪制輔助線
    private void drawAuxiliaryLine(Canvas canvas) {
        // 繪制數(shù)據(jù)點(diǎn)和控制點(diǎn)
        mPaint.setColor(Color.GRAY);
        mPaint.setStrokeWidth(20);

        for (int i=0; i<8; i+=2){
            canvas.drawPoint(mData[i],mData[i+1], mPaint);
        }

        for (int i=0; i<16; i+=2){
            canvas.drawPoint(mCtrl[i], mCtrl[i+1], mPaint);
        }


        // 繪制輔助線
        mPaint.setStrokeWidth(4);

        for (int i=2, j=2; i<8; i+=2, j+=4){
            canvas.drawLine(mData[i],mData[i+1],mCtrl[j],mCtrl[j+1],mPaint);
            canvas.drawLine(mData[i],mData[i+1],mCtrl[j+2],mCtrl[j+3],mPaint);
        }
        canvas.drawLine(mData[0],mData[1],mCtrl[0],mCtrl[1],mPaint);
        canvas.drawLine(mData[0],mData[1],mCtrl[14],mCtrl[15],mPaint);
    }

    // 繪制坐標(biāo)系
    private void drawCoordinateSystem(Canvas canvas) {
        canvas.save();                      // 繪制做坐標(biāo)系

        canvas.translate(mCenterX, mCenterY); // 將坐標(biāo)系移動(dòng)到畫(huà)布中央
        canvas.scale(1,-1);                 // 翻轉(zhuǎn)Y軸

        Paint fuzhuPaint = new Paint();
        fuzhuPaint.setColor(Color.RED);
        fuzhuPaint.setStrokeWidth(5);
        fuzhuPaint.setStyle(Paint.Style.STROKE);

        canvas.drawLine(0, -2000, 0, 2000, fuzhuPaint);
        canvas.drawLine(-2000, 0, 2000, 0, fuzhuPaint);

        canvas.restore();
    }
}

三戚揭、總結(jié)

其實(shí)關(guān)于貝塞爾曲線最重要的是核心理解貝塞爾曲線的生成方式诱告,只有理解了貝塞爾曲線的生成方式,才能更好的運(yùn)用貝塞爾曲線民晒。在上一篇末尾說(shuō)本篇可能涉及一點(diǎn)圖形渲染問(wèn)題精居,不幸的是,本篇沒(méi)有了潜必,請(qǐng)期待下一篇(可能會(huì)在下一篇中出現(xiàn)o( ̄︶ ̄)o)靴姿,下一篇依舊Path相關(guān)內(nèi)容,教給大家一些更好玩的東西磁滚。
解鎖新的境界之【繪制一個(gè)彈性的圓】

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末佛吓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子垂攘,更是在濱河造成了極大的恐慌维雇,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,888評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晒他,死亡現(xiàn)場(chǎng)離奇詭異吱型,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)仪芒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)唁影,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人掂名,你說(shuō)我怎么就攤上這事据沈。” “怎么了饺蔑?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,386評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵锌介,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng)孔祸,這世上最難降的妖魔是什么隆敢? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,726評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮崔慧,結(jié)果婚禮上拂蝎,老公的妹妹穿的比我還像新娘。我一直安慰自己惶室,他們只是感情好温自,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著皇钞,像睡著了一般悼泌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上夹界,一...
    開(kāi)封第一講書(shū)人閱讀 52,337評(píng)論 1 310
  • 那天馆里,我揣著相機(jī)與錄音,去河邊找鬼可柿。 笑死鸠踪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的趾痘。 我是一名探鬼主播慢哈,決...
    沈念sama閱讀 40,902評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼永票!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起滥沫,我...
    開(kāi)封第一講書(shū)人閱讀 39,807評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤侣集,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后兰绣,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體世分,經(jīng)...
    沈念sama閱讀 46,349評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評(píng)論 3 340
  • 正文 我和宋清朗相戀三年缀辩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了臭埋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,567評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡臀玄,死狀恐怖瓢阴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情健无,我是刑警寧澤荣恐,帶...
    沈念sama閱讀 36,242評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響叠穆,放射性物質(zhì)發(fā)生泄漏少漆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評(píng)論 3 334
  • 文/蒙蒙 一硼被、第九天 我趴在偏房一處隱蔽的房頂上張望示损。 院中可真熱鬧,春花似錦嚷硫、人聲如沸检访。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,420評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)烛谊。三九已至,卻和暖如春嘉汰,著一層夾襖步出監(jiān)牢的瞬間丹禀,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,531評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工鞋怀, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留双泪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,995評(píng)論 3 377
  • 正文 我出身青樓密似,卻偏偏與公主長(zhǎng)得像焙矛,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子残腌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評(píng)論 2 359

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