系統(tǒng)截取頭像偏移問(wèn)題

背景

不知道你們是否曾經(jīng)遇到過(guò)苞氮,在做頭像上傳的時(shí)候,使用系統(tǒng)的默認(rèn)裁剪圖片的方法瓤逼,會(huì)出現(xiàn)圖片跟裁剪框發(fā)生一定的偏移笼吟。經(jīng)過(guò)我的搜索和調(diào)查,發(fā)現(xiàn)網(wǎng)上很多的方法都不適用霸旗。這個(gè)問(wèn)題就純粹是系統(tǒng)相冊(cè)的一個(gè) bug 贷帮。也不知道蘋(píng)果什么時(shí)候能夠修復(fù)好。于是就有想法诱告,自己重寫(xiě)一個(gè)裁剪圖片的控制器撵枢。

問(wèn)題展示

關(guān)于圖片跟裁剪框偏移的問(wèn)題,在 iPhoneX 上因?yàn)榇嬖诎踩嚯x精居,所以導(dǎo)致這個(gè)偏移更為明顯锄禽。先給大家看一下不同手機(jī)(模擬器)上的差異情況。 PS : iPhoneX 上已經(jīng)做了適配靴姿。


iPhone7上裁剪圖片偏移展示圖.png
iPhoneX上裁剪圖片偏移展示圖.png

重寫(xiě)思想

一開(kāi)始沃但,以為自己要重寫(xiě)的東西包括:圖片選擇,圖片裁剪佛吓,圖片預(yù)覽宵晚,拍照這一整套東西。其實(shí)维雇,仔細(xì)觀察系統(tǒng) UIImagePickerController 淤刃,會(huì)發(fā)現(xiàn),其實(shí)真正要修改的也僅僅是圖片裁剪這個(gè)控制器谆沃。

源碼及構(gòu)建思維

1钝凶、修改 UIImagePickerController 的 allowsEditing 屬性為 NO ,令它不回自動(dòng)跳入它本身的裁剪控制器。

 [self.imagePickerViewController setAllowsEditing:NO];

2耕陷、修改選擇圖片之后的代理方法 -imagePickerController:didFinishPickingMediaWithInfo:掂名,在這里,我們控制其跳入自己的控制器哟沫。

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
    if (image && picker) {
        ZKRAccountAvatarCropController *cropVC = [[ZKRAccountAvatarCropController alloc] initWithImage:image];
        cropVC.delegate = self;
        [picker pushViewController:cropVC animated:YES];
    } else {
        [ZKRUtilities showStatusBarMsg:@"獲取圖片失敗饺蔑,請(qǐng)重新選擇" success:NO];
        _editIcon = NO;
    }
}

3、搭建自己的裁剪控制器嗜诀。

現(xiàn)在外部的條件基本準(zhǔn)備好了猾警,所以就是單純的搭建自己的圖片裁剪控制器了。

(1).h 文件:

主要使用代理來(lái)進(jìn)行回調(diào)操作隆敢。
并創(chuàng)建公有屬性发皿,裁剪區(qū)域,圖片最大縮放比例拂蝎,是否隱藏導(dǎo)航欄穴墅。
初始化方法。

#import <UIKit/UIKit.h>

@class ZKRAccountAvatarCropController;

@protocol ZKRAccountAvatarCropControllerDelegate <NSObject>

- (void)avatarCropController:(ZKRAccountAvatarCropController *)cropController didFinishCropWithImage:(UIImage *)image;

- (void)avatarCropControllerDidCancel:(ZKRAccountAvatarCropController *)cropController;

@end

@interface ZKRAccountAvatarCropController : UIViewController

@property (nonatomic, weak) id<ZKRAccountAvatarCropControllerDelegate>delegate;

/**
 *  裁剪區(qū)域  默認(rèn) 屏幕寬度顯示屏幕中心位置
 */
@property (nonatomic, assign) CGRect cropRect;

/**
 *  最大縮放比例  默認(rèn)2
 */
@property (nonatomic, assign) CGFloat maxScale;

/**
 *  是否隱藏導(dǎo)航欄  默認(rèn)隱藏
 */
@property (nonatomic, assign) BOOL navigationBarHidden;

/**
 *  初始化方法
 *
 *  @param image 待裁剪圖片
 *
 *  @return ZKRAccountAvatarCropController
 */
- (instancetype)initWithImage:(UIImage *)image NS_DESIGNATED_INITIALIZER;

- (instancetype)init NS_UNAVAILABLE;

- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE;

@end

(2) .m 文件

主要思想:
1温自、對(duì) image 的處理 -fixOrientation: 玄货。因?yàn)閷?duì)于 2M 以上的圖片進(jìn)行截取處理,會(huì)造成旋轉(zhuǎn) 90 度的結(jié)果悼泌。而這個(gè)原因是因?yàn)橛檬謾C(jī)拍攝出來(lái)的照片含有 EXIF 信息松捉,這就是 UIImage 的 imageOrientation 屬性。而我們對(duì) image 進(jìn)行截取或者 - drawRect 等操作的時(shí)候馆里,會(huì)下意識(shí)的忽略 imageOrientation 這個(gè)屬性對(duì)我們?cè)斐傻挠绊懓馈K晕覀儗?duì) image 處理之前,需要根據(jù) imageOrientation 屬性鸠踪,進(jìn)行 transform 的確定以舒。并對(duì)圖片進(jìn)行重繪。

    // 判斷當(dāng)前旋轉(zhuǎn)方向慢哈,取最后的修正transform
    switch (aImage.imageOrientation) {
        case UIImageOrientationDown:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, aImage.size.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;

        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
            transform = CGAffineTransformRotate(transform, M_PI_2);
            break;

        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, aImage.size.height);
            transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;
        default:
            break;
    }

2蔓钟、對(duì)于不同的 image 來(lái)說(shuō),它們的大小也是不一樣的卵贱。我們需要在一開(kāi)始進(jìn)入我們裁剪界面的時(shí)候?qū)?image 的 frame 進(jìn)行判斷操作滥沫,來(lái)獲取 imageView 的大小。 imageView 的寬度默認(rèn)是固定 self.view.frame.size.widht键俱。

3兰绣、裁剪圖片需要放到多線程中去。

看代碼:

//
//  ZKRAccountAvatarCropController.m
//
//  Created by zhengqiankun on 2018/5/30.
//  Copyright ? 2018年 ZAKER. All rights reserved.
//

#import "ZKRAccountAvatarCropController.h"
#import "ZKRAccountAvatarMaskView.h"

#define PADDING_BUTTON_LEFT   15
#define PADDING_BUTTON_RIGHT  15
#define PADDING_BUTTON_BOTTOM 15
#define WIDTH_BUTTON          60
#define HEIGHT_BUTTON         40

#define HEIGHT_BUTTONVIEW     70

@interface ZKRAccountAvatarCropController ()<UIScrollViewDelegate>

@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) ZKRAccountAvatarMaskView *maskView;
@property (nonatomic, strong) UIView *buttonView;
@property (nonatomic, strong) UIButton *cancelButton;
@property (nonatomic, strong) UIButton *cropButton;
@property (nonatomic, strong) UIImage *image; // 待裁剪的圖片

@property (nonatomic, assign) BOOL originalNaviBarHidden;

@end

@implementation ZKRAccountAvatarCropController

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    return [self initWithImage:nil];
}

- (instancetype)initWithImage:(UIImage *)image
{
    self = [super initWithNibName:nil bundle:nil];
    if (self) {
        _image = image;
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor blackColor];

    CGRect bounds = self.view.bounds;
    CGFloat currentWidth = bounds.size.width;
    CGFloat currentHeight = bounds.size.height;

    _navigationBarHidden = YES;

    _maxScale = 1.5f;
    _cropRect = CGRectMake(0, (currentHeight - currentWidth) / 2, currentWidth, currentWidth);

    if (_image) {
        _image = [self fixOrientation:_image];
    }

    [self initSubviews];
}

- (CGRect)imageViewRectWithImage:(UIImage *)image
{
    CGRect bounds = self.view.bounds;
    CGFloat currentWidth = bounds.size.width;

    CGFloat width = 0;
    CGFloat height = 0;

    width = currentWidth;
    height = image.size.height / image.size.width * width;
    if (height < currentWidth) {
        height = currentWidth;
        width = image.size.width / image.size.height * height;
    }

    return CGRectMake(0, 0, width, height);
}

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    [self layoutSubViews];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    _originalNaviBarHidden = self.navigationController.navigationBar.isHidden;
    self.navigationController.navigationBar.hidden = _navigationBarHidden;

    [_maskView setMaskRect:self.cropRect];
    [self refreshScrollView];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    self.navigationController.navigationBar.hidden = _originalNaviBarHidden;
}

- (void)setNavigationBarHidden:(BOOL)navigationBarHidden
{
    _navigationBarHidden = navigationBarHidden;
    if (self.navigationController) {
        self.navigationController.navigationBar.hidden = navigationBarHidden;
    }
}

- (void)initSubviews
{
    _scrollView = [[UIScrollView alloc] init];
    _scrollView.delegate = self;
    _scrollView.alwaysBounceVertical = YES;
    _scrollView.alwaysBounceHorizontal = YES;
    _scrollView.showsVerticalScrollIndicator = NO;
    _scrollView.showsHorizontalScrollIndicator = NO;
    [self.view addSubview:_scrollView];

    _maskView = [[ZKRAccountAvatarMaskView alloc] init];
    _maskView.userInteractionEnabled = NO;
    [self.view addSubview:_maskView];

    _buttonView = [[UIView alloc] init];
    _buttonView.backgroundColor = [UIColor colorWithRed:20 / 255.0 green:20 / 255.0 blue:20 / 255.0 alpha:0.8];
    [self.view addSubview:_buttonView];

    _cropButton = [[UIButton alloc] init];
    [_cropButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [_cropButton.titleLabel setFont:[UIFont systemFontOfSize:17]];
    [_cropButton setTitle:@"選取" forState:UIControlStateNormal];
    [_cropButton addTarget:self action:@selector(cropImageAction) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_cropButton];

    _cancelButton = [[UIButton alloc] init];
    [_cancelButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [_cancelButton.titleLabel setFont:[UIFont systemFontOfSize:17]];
    [_cancelButton setTitle:@"取消" forState:UIControlStateNormal];
    [_cancelButton addTarget:self action:@selector(cancelAction) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_cancelButton];

    [self layoutSubViews];
}

- (void)layoutSubViews
{
    CGRect bounds = self.view.bounds;
    CGFloat currentWidth = bounds.size.width;
    CGFloat currentHeight = bounds.size.height;

    _cropRect = CGRectMake(0, (currentHeight - currentWidth) / 2, currentWidth, currentWidth);

    _scrollView.frame = bounds;

    if (!_imageView) {
        _imageView = [[UIImageView alloc] initWithImage:_image];
        _imageView.frame = [self imageViewRectWithImage:_image];
        [_scrollView addSubview:_imageView];
    } else {
        _imageView.frame = [self imageViewRectWithImage:_image];
        _imageView.image = _image;
    }

    _scrollView.contentSize = _imageView.frame.size;
    CGRect scrollViewFrame = _scrollView.frame;
    _maskView.frame = scrollViewFrame;
    CGFloat buttonViewY = bounds.size.height - HEIGHT_BUTTONVIEW;
    if ([UIScreen whl_isIPhoneX]) {
        buttonViewY = bounds.size.height - HEIGHT_BUTTONVIEW - WHL_IPHONEX_BOTTOM_INSET;
    }
    _buttonView.frame = CGRectMake(0, buttonViewY, bounds.size.width, HEIGHT_BUTTONVIEW);

    CGFloat buttonY = [UIScreen whl_isIPhoneX] ? currentHeight - HEIGHT_BUTTON - PADDING_BUTTON_BOTTOM - WHL_IPHONEX_BOTTOM_INSET : currentHeight - HEIGHT_BUTTON - PADDING_BUTTON_BOTTOM;
    _cropButton.frame = CGRectMake(currentWidth - WIDTH_BUTTON - PADDING_BUTTON_RIGHT, buttonY, WIDTH_BUTTON, HEIGHT_BUTTON);
    _cancelButton.frame = CGRectMake(PADDING_BUTTON_LEFT, buttonY, WIDTH_BUTTON, HEIGHT_BUTTON);
}

- (void)cropImageAction
{
    [self cropImage];
}

- (void)cancelAction
{
    if ([self.delegate respondsToSelector:@selector(avatarCropControllerDidCancel:)]) {
        [self.delegate avatarCropControllerDidCancel:self];
    }
}

#pragma mark - 裁剪圖片
- (void)cropImage
{
    // 計(jì)算縮放比例
    CGFloat scale = _imageView.image.size.height / _imageView.frame.size.height;
    CGFloat imageScale = _imageView.image.scale;

    CGFloat width = self.cropRect.size.width * scale * imageScale;
    CGFloat height = self.cropRect.size.height * scale * imageScale;
    CGFloat x = (self.cropRect.origin.x + _scrollView.contentOffset.x) * scale * imageScale;
    CGFloat y = (self.cropRect.origin.y + _scrollView.contentOffset.y) * scale * imageScale;

    // 設(shè)置裁剪圖片的區(qū)域
    CGRect rect = CGRectMake(x, y, width, height);

    CGImageRef imageRef = CGImageCreateWithImageInRect(self.imageView.image.CGImage, rect);
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 截取區(qū)域圖片
        UIImage *image = [UIImage imageWithCGImage:imageRef];
        CGImageRelease(imageRef);
        
        dispatch_async(dispatch_get_main_queue(), ^{
            if ([self.delegate respondsToSelector:@selector(avatarCropController:didFinishCropWithImage:)]) {
                [self.delegate avatarCropController:self didFinishCropWithImage:image];
            }
        });
    });
}

#pragma mark - UIScrollViewDelegate 返回縮放的view
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return _imageView;
}

#pragma mark - 處理scrollView的最小縮放比例 和 滾動(dòng)范圍
- (void)refreshScrollView
{
    CGFloat top = self.cropRect.origin.y - 20;

    CGFloat minScale = 0.f;
    if (_imageView.image.size.height > _imageView.image.size.width) {
        minScale = self.cropRect.size.width / _imageView.bounds.size.width;
    } else {
        minScale = self.cropRect.size.height / _imageView.bounds.size.height;
    }
    CGFloat bottom = self.cropRect.origin.y;
    if ([UIScreen whl_isIPhoneX]) {
        top = self.cropRect.origin.y - WHL_IPHONEX_TOP_INSET;
        bottom = bottom - WHL_IPHONEX_BOTTOM_INSET;
    }

    _scrollView.maximumZoomScale = self.maxScale;
    _scrollView.minimumZoomScale = minScale;
    _scrollView.contentInset = UIEdgeInsetsMake(top, 0, bottom, 0);

    [self scrollToCenter];
}

#pragma mark - 滾動(dòng)圖片到中間位置
- (void)scrollToCenter
{
    CGRect bounds = self.view.bounds;
    CGFloat currentWidth = bounds.size.width;
    CGFloat currentHeight = bounds.size.height;

    CGFloat x = (_imageView.frame.size.width - currentWidth) / 2;
    CGFloat y = (_imageView.frame.size.height - currentHeight) / 2 + 20;
    if ([UIScreen whl_isIPhoneX]) {
        y = (_imageView.frame.size.height - currentHeight) / 2  + WHL_IPHONEX_TOP_INSET;
    }
    _scrollView.contentOffset = CGPointMake(x, y);
}

- (UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}

#pragma mark -- 圖片旋轉(zhuǎn)
- (UIImage *)fixOrientation:(UIImage *)aImage
{
    // 圖片為正向
    if (aImage.imageOrientation == UIImageOrientationUp) {
        return aImage;
    }

    CGAffineTransform transform = CGAffineTransformIdentity;

    // 判斷當(dāng)前旋轉(zhuǎn)方向编振,取最后的修正transform
    switch (aImage.imageOrientation) {
        case UIImageOrientationDown:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, aImage.size.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;

        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
            transform = CGAffineTransformRotate(transform, M_PI_2);
            break;

        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, aImage.size.height);
            transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;
        default:
            break;
    }

    switch (aImage.imageOrientation) {
        case UIImageOrientationUpMirrored:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;

        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.height, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
        default:
            break;
    }

    CGContextRef ctx = CGBitmapContextCreate(NULL, aImage.size.width, aImage.size.height,
                                             CGImageGetBitsPerComponent(aImage.CGImage), 0,
                                             CGImageGetColorSpace(aImage.CGImage),
                                             CGImageGetBitmapInfo(aImage.CGImage));
    CGContextConcatCTM(ctx, transform);
    switch (aImage.imageOrientation) {
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            CGContextDrawImage(ctx, CGRectMake(0, 0, aImage.size.height, aImage.size.width), aImage.CGImage);
            break;
        default:
            CGContextDrawImage(ctx, CGRectMake(0, 0, aImage.size.width, aImage.size.height), aImage.CGImage);
            break;
    }

    CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
    UIImage *img = [UIImage imageWithCGImage:cgimg];
    CGContextRelease(ctx);
    CGImageRelease(cgimg);
    return img;
}

@end

4缀辩、配套 maskView ,裁剪框

.h 代碼:

//
//  ZKRAccountAvatarMaskView.h
//
//  Created by zhengqiankun on 2018/5/30.
//  Copyright ? 2018年 ZAKER. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ZKRAccountAvatarMaskView : UIView

@property (nonatomic, assign) CGRect maskRect;

- (void)setMaskRect:(CGRect)rect;

@end

.m 代碼

//
//  ZKRAccountAvatarMaskView.m
//
//  Created by zhengqiankun on 2018/5/30.
//  Copyright ? 2018年 ZAKER. All rights reserved.
//

#import "ZKRAccountAvatarMaskView.h"

@interface ZKRAccountAvatarMaskView ()

@property (nonatomic, strong) UIView *rectView;

@end

@implementation ZKRAccountAvatarMaskView

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        self.backgroundColor = [UIColor clearColor];
        _rectView = [[UIView alloc] init];
        _rectView.clipsToBounds = YES;
        _rectView.layer.borderColor = [UIColor whiteColor].CGColor;
        _rectView.layer.borderWidth = 2;
        [self addSubview:_rectView];
    }
    return self;
}

- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextAddRect(context, self.maskRect);
    CGContextAddRect(context, rect);
    [[UIColor colorWithRed:0 green:0 blue:0 alpha:0.4] setFill];
    CGContextDrawPath(context, kCGPathEOFill);
}

- (void)setMaskRect:(CGRect)rect
{
    if (!CGRectEqualToRect(_maskRect, rect)) {
        _maskRect = rect;
        _rectView.frame = rect;
        [self setNeedsDisplay];
    }
}

@end

如果有錯(cuò)誤的地方,希望大家多多指正臀玄。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末瓢阴,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子健无,更是在濱河造成了極大的恐慌荣恐,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件累贤,死亡現(xiàn)場(chǎng)離奇詭異叠穆,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)臼膏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)硼被,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人渗磅,你說(shuō)我怎么就攤上這事祷嘶。” “怎么了夺溢?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)烛谊。 經(jīng)常有香客問(wèn)我风响,道長(zhǎng),這世上最難降的妖魔是什么丹禀? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任状勤,我火速辦了婚禮,結(jié)果婚禮上双泪,老公的妹妹穿的比我還像新娘持搜。我一直安慰自己,他們只是感情好焙矛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布葫盼。 她就那樣靜靜地躺著,像睡著了一般村斟。 火紅的嫁衣襯著肌膚如雪贫导。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天蟆盹,我揣著相機(jī)與錄音孩灯,去河邊找鬼。 笑死逾滥,一個(gè)胖子當(dāng)著我的面吹牛峰档,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼讥巡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼掀亩!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起尚卫,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤归榕,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后吱涉,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體刹泄,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年怎爵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了特石。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鳖链,死狀恐怖姆蘸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情芙委,我是刑警寧澤逞敷,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站灌侣,受9級(jí)特大地震影響推捐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜侧啼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一牛柒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧痊乾,春花似錦皮壁、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至湿滓,卻和暖如春畏腕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背茉稠。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工描馅, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人而线。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓铭污,卻偏偏與公主長(zhǎng)得像恋日,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嘹狞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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