Android Matrix 方法詳解(另類)

一悄谐、簡介

Android android.graphics.Matrix 類是一個3 x 3的矩陣(方陣)侦啸,上一張幾乎所有介紹Matrix的文章都會引用的Matrix內(nèi)容圖:

android.graphics.Matrix.png
Matrix使用非常廣泛屿储,平時我們使用的補間動畫、圖像變換函匕、畫布的變換仙粱、大名鼎鼎的MPAndroidChart圖表庫等都使用了Matrix。在平時的開發(fā)當(dāng)中帜篇,Matrix的使用有時可以起到事半功倍的效果糙捺。

二、相關(guān)方法

1坠狡、equals

比較兩個矩陣是否相等继找。

    Matrix matrix1 = new Matrix();
    Matrix matrix2 = new Matrix();
    matrix1.setTranslate(1,2);
    matrix2.setTranslate(2,2);
    // 輸出:matrix1 == matrix2:false
    System.out.println("matrix1 == matrix2:" + matrix1.equals(matrix2));

2、+號相連/toString/toShortString

將矩陣轉(zhuǎn)換為字符串逃沿。

    Matrix matrix = new Matrix();
    
    // 輸出:+號相連:Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
    System.out.println("+號相連:" + matrix);
    // 輸出:Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
    System.out.println("toString:" + matrix.toString());
    // 輸出:[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]
    System.out.println("toShortString:" + matrix.toShortString());

3婴渡、getValues()、setValues()

當(dāng)我們調(diào)用Matrix類的getValues(float[] values)凯亮、setValues(float[] values)方法時边臼,可以將這個矩陣轉(zhuǎn)換成一個數(shù)組進(jìn)行操作。轉(zhuǎn)換后的數(shù)組為:
[ MSCALE_X, MSKEW_X, MTRANS_X, MSKEW_Y, MSCALE_Y, MTRANS_Y, MPERSP_0, MPERSP_1, MPERSP_2]
為了方便操作這個數(shù)組假消,在android.graphics.Matrix類中柠并,定義了MSCALE_X、MSKEW_X...變量富拗,分別代表各自功能在數(shù)組中對應(yīng)的下標(biāo)臼予,具體內(nèi)容如下:

public static final int MSCALE_X = 0;   //!< use with getValues/setValues
public static final int MSKEW_X  = 1;   //!< use with getValues/setValues
public static final int MTRANS_X = 2;   //!< use with getValues/setValues
public static final int MSKEW_Y  = 3;   //!< use with getValues/setValues
public static final int MSCALE_Y = 4;   //!< use with getValues/setValues
public static final int MTRANS_Y = 5;   //!< use with getValues/setValues
public static final int MPERSP_0 = 6;   //!< use with getValues/setValues
public static final int MPERSP_1 = 7;   //!< use with getValues/setValues
public static final int MPERSP_2 = 8;   //!< use with getValues/setValues

方法示例:

    Matrix matrix = new Matrix();
    
    // matrix = [1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]
    System.out.println("matrix = " + matrix.toShortString());

    float[] values = new float[9];
    matrix.getValues(values);
    
    // matrix轉(zhuǎn)換成數(shù)組后 = [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]
    System.out.println("matrix轉(zhuǎn)換成數(shù)組后 = " + Arrays.toString(values));

    // 為matrix賦值
    values [Matrix.MTRANS_X] = 2;
    values [Matrix.MTRANS_Y] = 3;
    matrix.setValues(values);

    // matrix = [1.0, 0.0, 2.0][0.0, 1.0, 3.0][0.0, 0.0, 1.0]
    System.out.println("matrix = " + matrix.toShortString());

4、setXXX/preXXX/postXXX

XXX可以是Translate啃沪、Scale粘拾、Rotate、Skew和Concat创千。其中Concat參數(shù)為Matrix缰雇,表示直接操作Matrix入偷。由于縮放、旋轉(zhuǎn)械哟、錯切可以繞中心操作疏之,如果指定了中心,則變換步驟為:

  1. 將原點平移到該點暇咆。
  2. 做縮放锋爪、錯切、旋轉(zhuǎn)操作糯崎。
  3. 原點平移到原來的原點處几缭。

方法參數(shù)轉(zhuǎn)換成了一個怎樣的矩陣河泳?

// 下面代碼中參數(shù)(2,2) 轉(zhuǎn)換后的矩陣為
// [2.0, 0.0, 0.0]
// [0.0, 2.0, 0.0]
// [0.0, 0.0, 1.0]
// 即根據(jù)XXX代表的功能修改矩陣中對應(yīng)功能位置的值即可
matrix.postScale(2,2);

setXXX

首先會將該Matrix重置為單位矩陣沃呢,即相當(dāng)于首先會調(diào)用reset()方法,然后再設(shè)置該Matrix中對應(yīng)功能的值拆挥。例:

    // [1.0, 0.0, 0.0]
    // [0.0, 1.0, 0.0]
    // [0.0, 0.0, 1.0]
    Matrix matrix = new Matrix();

    // [1.0, 0.0, 0.0]    [2.0, 3.0, 4.0]
    // [0.0, 1.0, 0.0] -> [2.0, 0.0, 0.0]
    // [0.0, 0.0, 1.0]    [1.0, 1.0, 1.0]
    matrix.setValues(new float[]{2.0f,3.0f, 4.0f,
                                 2.0f,0.0f, 0.0f,
                                 1.0f,1.0f,1.0f});

    // [2.0, 3.0, 4.0]    [1.0, 0.0, 0.0]    [2.0, 0.0, 0.0]
    // [2.0, 2.0, 0.0] -> [0.0, 1.0, 0.0] -> [0.0, 2.0, 0.0]
    // [1.0, 1.0, 1.0]    [0.0, 0.0, 1.0]    [0.0, 0.0, 1.0]
    matrix.setScale(2,2);

preXXX

不會重置Matrix薄霜,相當(dāng)于當(dāng)前操作矩陣(A)左乘參數(shù)矩陣(B),即AB纸兔。例:

    // [1.0, 0.0, 0.0]
    // [0.0, 1.0, 0.0]
    // [0.0, 0.0, 1.0]
    Matrix matrix = new Matrix();
    
    // [1.0, 0.0, 0.0]    [2.0, 3.0, 4.0]
    // [0.0, 1.0, 0.0] -> [2.0, 0.0, 0.0]
    // [0.0, 0.0, 1.0]    [1.0, 1.0, 1.0]
    matrix.setValues(new float[]{2.0f,3.0f, 4.0f,
                                 2.0f,0.0f, 0.0f,
                                 1.0f,1.0f,1.0f});
    
    // [2.0, 3.0, 4.0]           [2.0, 0.0, 0.0]   [4.0, 6.0, 4.0]
    // [2.0, 0.0, 0.0](matrix) * [0.0, 2.0, 0.0] = [4.0, 0.0, 0.0](matrix)
    // [1.0, 1.0, 1.0]           [0.0, 0.0, 1.0]   [2.0, 2.0, 1.0]
    matrix.preScale(2,2);

postXXX

不會重置Matrix惰瓜,相當(dāng)于當(dāng)前操作矩陣(A)右乘參數(shù)矩陣(B),即BA汉矿,例:

    // [1.0, 0.0, 0.0]
    // [0.0, 1.0, 0.0]
    // [0.0, 0.0, 1.0]
    Matrix matrix = new Matrix();
    
    // [1.0, 0.0, 0.0]    [2.0, 3.0, 4.0]
    // [0.0, 1.0, 0.0] -> [2.0, 0.0, 0.0]
    // [0.0, 0.0, 1.0]    [1.0, 1.0, 1.0]
    matrix.setValues(new float[]{2.0f,3.0f, 4.0f,
                                 2.0f,0.0f, 0.0f,
                                 1.0f,1.0f,1.0f});
    
    // [2.0, 0.0, 0.0]   [2.0, 3.0, 4.0]            [4.0, 6.0, 8.0]
    // [0.0, 2.0, 0.0] * [2.0, 0.0, 0.0] (matrix) = [4.0, 0.0, 0.0](matrix)
    // [0.0, 0.0, 1.0]   [1.0, 1.0, 1.0]            [1.0, 1.0, 1.0]
    matrix.postScale(2,2);

setContact

關(guān)于setContact(Matrix m1,Matrix m2)方法崎坊,需要單獨說下,它的參數(shù)為兩個Matrix對象洲拇,計算規(guī)則為:當(dāng)前操作的Matrix對象 = m1 * m2;
例:

    // [1.0, 0.0, 0.0]
    // [0.0, 1.0, 0.0]
    // [0.0, 0.0, 1.0]
    Matrix matrix = new Matrix();
    Matrix matrix1 = new Matrix();
    Matrix matrix2 = new Matrix();

    // [1.0, 0.0, 0.0]    [2.0, 3.0, 4.0]
    // [0.0, 1.0, 0.0] -> [2.0, 0.0, 0.0]
    // [0.0, 0.0, 1.0]    [1.0, 1.0, 1.0]
    matrix1.setValues(new float[]{2.0f,3.0f, 4.0f,
                                 2.0f,0.0f, 0.0f,
                                 1.0f,1.0f,1.0f});

    // [1.0, 0.0, 0.0]    [2.0, 5.0, 4.0]
    // [0.0, 1.0, 0.0] -> [3.0, 0.0, 0.0]
    // [0.0, 0.0, 1.0]    [1.0, 2.0, 1.0]
    matrix2.setValues(new float[]{2.0f,5.0f, 4.0f,
                                 3.0f,0.0f, 0.0f,
                                 1.0f,2.0f,1.0f});

    // [2.0, 3.0, 4.0]            [2.0, 5.0, 4.0]            [17.0, 18.0, 12.0]
    // [2.0, 2.0, 0.0](matrix1) * [3.0, 0.0, 0.0](matrix2) = [4.0,  10.0, 8.0 ] (matrix)
    // [1.0, 1.0, 1.0]            [1.0, 2.0, 1.0]            [6.0,  7.0,  5.0 ]
    matrix.setConcat(matrix1,matrix2);

5奈揍、mapRadius/mapPoints/mapRect/mapVectors

可翻譯為將矩陣映射到(作用于)點、矩形赋续、半徑男翰、向量。

mapRadius

半徑的計算纽乱。例:

    // 一個半徑為100.0f的圓蛾绎,放大1倍后,半徑也將增大一倍鸦列。據(jù)說用在畫布中的圓隨畫布大小變化時
    float radius = 100.0f;
    float radiusAfterMatrix;
    Matrix matrixRadius = new Matrix();
    matrixRadius.setScale(2,2);
    radiusAfterMatrix = matrixRadius.mapRadius(radius);
    // 輸出:radius=200.0
    System.out.println("radius=" + radiusAfterMatrix);

mapPoints

此方法有3個重載方法租冠。點數(shù)組各值分別代表pts[x0,y0,x1,y1 ... xn,yn],因為一個點的確定需要x坐標(biāo)和y坐標(biāo)兩個值,所以薯嗤,pts數(shù)組的長度一般為偶數(shù)顽爹,如果為奇數(shù),則最后一個值不參與計算(長度為1將不計算)应民。下面給出具體例子话原,例子中將會詳細(xì)說明mapPoints方法夕吻。

    // =======================
    // mapPoints(float[] pts)
    // =======================
    // 運算后的結(jié)果會保存在pts數(shù)組中,原pts數(shù)組中的內(nèi)容會被覆蓋

    // 1.《點的移動》,對于任意點(Xn,Yn),x軸方向平移dx,y軸方向平移dy后有:
    //  Xn = Xn + dx
    //  Yn = Yn + dy
    float[] ptsTrans = {6,2};
    Matrix matrixTrans = new Matrix();
    matrixTrans.setTranslate(-2,2);
    matrixTrans.mapPoints(ptsTrans);
    // 輸出:trans=[4.0, 4.0]
    System.out.println("trans=" + Arrays.toString(ptsTrans));

    // 2.《點的放大》繁仁,對于任意點(Xn,Yn),繞點(px,py)x軸涉馅、y軸方向分別放大sx倍、sy倍后黄虱,有:
    //  Xn = Xn * sx + (px - px * sx)
    //  Yn = Yn * sy + (py - sy * py)
    float[] ptsScale = {2,3};
    Matrix matrixScale = new Matrix();
    matrixScale.setScale(3,6,2,2);
    matrixScale.mapPoints(ptsScale);
    // 輸出:scale=[2.0, 8.0]
    System.out.println("scale=" + Arrays.toString(ptsScale));

    // 3.《點的旋轉(zhuǎn)》稚矿,對于任意點(Xn,Yn),繞點(px,py)旋轉(zhuǎn)a度后,有:
    //  Xn = (Xn - px) * cos(a) - (Yn - py) * sin(a) + px
    //  Yn = (Xn - px) * sin(a) + (Yn - py) * cos(a) + py
    float[] ptsRotate = {6,6};
    Matrix matrixRotate = new Matrix();
    matrixRotate.preRotate(90,2,3);
    matrixRotate.mapPoints(ptsRotate);
    // 輸出:rotate=[-1.0,7.0]
    System.out.println("rotate=" + Arrays.toString(ptsRotate));

    // 4.《點的錯切》,對于任意點(Xn,Yn),繞點(px,py)x軸捻浦、y軸方向分別錯切kx晤揣、ky后,有:
    //  Xn = Xn + kx(Yn - py)
    //  Yn = Yn + ky(Xn - px)
    float[] ptsSkew = {3,2};
    Matrix matrixSkew = new Matrix();
    matrixSkew.setSkew(2,3,6,8);
    matrixSkew.mapPoints(ptsSkew);
    // 輸出:skew=[-9.0,-7.0]
    System.out.println("skew=" + Arrays.toString(ptsSkew));

    // ===================================
    // mapPoints(float[] dst, float[] src)
    // ===================================
    // 運算后的結(jié)果保存在dst數(shù)組中朱灿,原src數(shù)組中的內(nèi)容會保留

    float[] src = {2,3,3,3};
    float[] dst = new float[src.length];
    Matrix matrixDstSrc = new Matrix();
    matrixDstSrc.setTranslate(2,3);
    matrixDstSrc.mapPoints(dst,src);

    // 輸出:dst=[4.0,6.0,5.0,6.0]
    System.out.println("dst=" + Arrays.toString(dst));
    // 輸出:src=[2.0,3.0,3.0,3.0]
    System.out.println("src=" + Arrays.toString(src));

    // ==============================================================================
    // mapPoints(float[] dst,   ---- 計算結(jié)果存放數(shù)組
    //           int dstIndex,  ---- dst數(shù)組存放計算結(jié)果時起始下標(biāo)
    //           float[] src,   ---- 計算的源數(shù)組
    //           int srcIndex,  ---- 源數(shù)組計算時起始下標(biāo)
    //           int pointCount ---- 從起始下標(biāo)開始一共要計算多少個點
    //           )
    // ==============================================================================
    // 運算后的結(jié)果保存在dst數(shù)組中

    float[] src1 = {2,3,3,3,2,3};
    float[] dst1 = new float[]{6,6,6,6,6,6};
    Matrix matrixDstSrc1 = new Matrix();
    matrixDstSrc1.setTranslate(1,1);

    // 1)從src1下標(biāo)為2的位置開始計算昧识,計算1個點,注意盗扒,是一個點跪楞,不是一個長度;計算的結(jié)果只保存計算的點侣灶,未計算的點將舍棄甸祭,即結(jié)果為:[4.0,4.0]
    // 2)將src1計算后的結(jié)果,從dst1下標(biāo)為2的位置開始放置
    // 注意褥影,從存放數(shù)組開始的位置存放計算結(jié)果時池户,如果長度不夠,將拋出 ArrayIndexOutOfBoundsException 異常
    matrixDstSrc1.mapPoints(dst1,5,src1,2,1);

    // 輸出:dst=[0.0,0.0,2.0,3.0,4.0,4.0]
    System.out.println("dst1=" + Arrays.toString(dst1));
    // 輸出:src=[2.0,3.0,3.0,3.0,2.0,3.0]
    System.out.println("src1=" + Arrays.toString(src1));

mapRect

將矩形的4個點按Matrix中設(shè)定的值變換凡怎,返回值為變換后是否還為一個矩形校焦。此方法有2個重載方法。

    // ============================================
    // mapRect(RectF rect)
    // ============================================
    // 結(jié)果存放在rect中栅贴,原rect將被覆蓋
    RectF rectF = new RectF(100,100,200,200);
    // 輸出:rectFbefore = RectF(100.0, 100.0, 200.0, 200.0)
    System.out.println("rectFbefore = " + rectF);
    Matrix matrixRectF = new Matrix();
    matrixRectF.setScale(2,2);
    matrixRectF.mapRect(rectF);
    // 輸出:rectFafter = RectF(200.0, 200.0, 400.0, 400.0)
    System.out.println("rectFafter = " + rectF);

    // ============================================
    // mapRect(RectF dst,RectF src)
    // ============================================
    // 結(jié)果存放在dst中斟湃,原src會保留。其它與mapRect(RectF rect)方法相同

mapVectors

用法和mapPoints方法類似檐薯,此方法有3個重載方法凝赛,唯一不同的是mapVectors不受位移影響。例:

    float[] vector = {2,3};
    float[] point = {2,3};
    Matrix matrixTranslate = new Matrix();
    matrixTranslate.setTranslate(2,3);
    matrixTranslate.mapVectors(vector);
    matrixTranslate.mapPoints(point);

    // 輸出:vector = [2.0,3.0]
    System.out.println("vector = " + Arrays.toString(vector));
    // 輸出:point = [4.0,6.0]
    System.out.println("point = " + Arrays.toString(point));

6坛缕、invert

做相反的運算墓猎。得到變化前的狀態(tài)。例:圖形旋轉(zhuǎn)一定角度后再恢復(fù)旋轉(zhuǎn)前的狀態(tài)赚楚。matrixOri.invert(matrixInvert)方法可翻譯為:將matrixOri這個矩陣反轉(zhuǎn)后存放在matrixInvert這個矩陣中毙沾, matrixInvert這個矩陣中原來的值將被覆蓋。

    // ==========================================
    // 移動
    // ==========================================
    // [1.0, 0.0, Δx]            [1.0, 0.0, -Δx]
    // [0.0, 1.0, Δy]  invert -> [0.0, 1.0, -Δy]
    // [0.0, 0.0, 1.0]           [0.0, 0.0, 1.0]

    Matrix matrixTrans = new Matrix();
    matrixTrans.setTranslate(2,3);

    // [1.0, 0.0, 2.0]
    // [0.0, 1.0, 3.0]
    // [0.0, 0.0, 1.0]
    System.out.println("matrixTrans = " + matrixTrans);

    matrixTrans.invert(matrixTrans);

    // [1.0, 0.0, -2.0]
    // [0.0, 1.0, -3.0]
    // [0.0, 0.0,  1.0]
    System.out.println("matrixTrans = " + matrixTrans);

    // ==========================================
    // 縮放
    // ==========================================
    // [sx,   0,  -px]             [1/sx,    0,  px/2]
    // [0,   sy,  -py]  invert ->  [0,    1/sy,  py/2]
    // [0.0, 0.0, 1.0]             [0.0,   0.0,   1.0]

    Matrix matrixScale = new Matrix();
    matrixScale.setScale(2,2,12,7);

    // [2.0, 0.0, -12.0]
    // [0.0, 2.0, -7.0]
    // [0.0, 0.0, 1.0]
    System.out.println("matrixScale = " + matrixScale);

    matrixScale.invert(matrixScale);

    // [0.5, 0.0, 6.0]
    // [0.0, 0.5, 3.5]
    // [0.0, 0.0, 1.0]
    System.out.println("matrixScale = " + matrixScale);

7宠页、isIdentity

判斷一個矩陣是否為單位矩陣

    Matrix matrix = new Matrix();

    // 輸出:matrix is identity:true
    System.out.println("matrix is identity:" + matrix.isIdentity());

    matrix.setTranslate(1,2);

    // 輸出:matrix is identity:false
    System.out.println("matrix is identity:" + matrix.isIdentity());

8左胞、setPolyToPoly

根據(jù)src坐標(biāo)到dst坐標(biāo)的變換關(guān)系寇仓,生成對應(yīng)的Matrix矩陣。

    // ==================================================================================================
    // setPolyToPoly(float[] src,     變換前的點數(shù)組烤宙,內(nèi)容為[x0, y0, x1, y1, ...]
    //               int srcIndex,    第一個變化的點在src數(shù)組中的下標(biāo)
    //               float[] dst,     src變換后的點數(shù)組遍烦,內(nèi)容為[x0‘, y0’, x1’, y1’, ...],與src數(shù)組一一對應(yīng)
    //               int dstIndex,    變化后的第一個點在dst數(shù)組中存儲的位置
    //               int pointCount   一次一共需要變換多少個點躺枕,取值范圍[0,4]
    //               )
    // ==================================================================================================

    float[] src = {1,2};
    float[] dst = {2,4};

    //          [1.0, 0.0, 0.0]
    // matrix = [0.0, 1.0, 0.0]
    //          [0.0, 0.0, 1.0]
    Matrix matrix = new Matrix();
    System.out.println("matrix = " + matrix.toShortString());

    matrix.setPolyToPoly(src,0,dst,0,1);

    //          [1.0, 0.0, 1.0]
    // matrix = [0.0, 1.0, 2.0]
    //          [0.0, 0.0, 1.0]
    System.out.println("matrix = " + matrix.toShortString());

    // 驗證這個生成的matrix是否正確
    // [1.0, 0.0, 1.0]   [1]   [2.0]
    // [0.0, 1.0, 2.0] * [2] = [4.0]
    // [0.0, 0.0, 1.0]   [1]   [1.0]

9服猪、setRectToRect

將矩形填充到矩形中。其中在填充時可以指定4種填充模式拐云,這4種模式用Matrix.ScaleToFit枚舉類型表示罢猪,關(guān)于這4種填充模式,借用一張官方demo圖:

ScaleToFit.png

    Matrix matrix = new Matrix();
    RectF rectFSrc = new RectF(100,100,200,400);
    RectF rectFDst = new RectF(100,100,400,200);
    matrix.setRectToRect(rectFSrc,rectFDst, Matrix.ScaleToFit.FILL);

三叉瘩、總結(jié)

Matrix可以運用到很多地方膳帕,但基本的原理都是通過Matrix提供的API對Matrix中值的更改,然后再將這個Matrix作用于不同的對象(圖片房揭、畫布等)备闲。

本篇文章主要是對android.graphics.Matrix類中常用方法的講解,與網(wǎng)上其它講解Matrix的文章方向可能有所不同捅暴。由于文章很多細(xì)致的講解都在代碼的注釋中,請各位一定要關(guān)注文章中的代碼示例咧纠。文章中的代碼示例均可復(fù)制>>粘貼>>運行蓬痒,可自行測試。

由于本人功力有限漆羔,文章中可能會有出錯的地方梧奢。如果各位發(fā)現(xiàn)有誤的地方請指證。當(dāng)然演痒,如果有什么地方不理解亲轨,也可以提出來。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鸟顺,一起剝皮案震驚了整個濱河市惦蚊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌讯嫂,老刑警劉巖蹦锋,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異欧芽,居然都是意外死亡莉掂,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進(jìn)店門千扔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來憎妙,“玉大人库正,你說我怎么就攤上這事±逋伲” “怎么了诀诊?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長阅嘶。 經(jīng)常有香客問我属瓣,道長,這世上最難降的妖魔是什么讯柔? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任抡蛙,我火速辦了婚禮,結(jié)果婚禮上魂迄,老公的妹妹穿的比我還像新娘粗截。我一直安慰自己,他們只是感情好捣炬,可當(dāng)我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布熊昌。 她就那樣靜靜地躺著,像睡著了一般湿酸。 火紅的嫁衣襯著肌膚如雪婿屹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天推溃,我揣著相機與錄音昂利,去河邊找鬼。 笑死铁坎,一個胖子當(dāng)著我的面吹牛蜂奸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播硬萍,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼扩所,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了朴乖?” 一聲冷哼從身側(cè)響起祖屏,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎寒砖,沒想到半個月后赐劣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡哩都,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年魁兼,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡咐汞,死狀恐怖盖呼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情化撕,我是刑警寧澤几晤,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站植阴,受9級特大地震影響蟹瘾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜掠手,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一憾朴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧喷鸽,春花似錦众雷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至混槐,卻和暖如春编兄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纵隔。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工翻诉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人捌刮。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像舒岸,于是被迫代替她去往敵國和親绅作。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,452評論 2 348

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