iOS 手势解锁

定义枚举


项目中用到的手势解锁,网上搜到了一位大神所封装的,用起来很方便

KMNineBoxView是继承UIView的类

KMNineBoxView .h

typedef NS_ENUM(NSInteger, KMNineBoxState) { 

 KMNineBoxStateNormal = 0, 

 KMNineBoxStateTouched = 1<<0,

 KMNineBoxStatePassed = 1<<1, 

 KMNineBoxStateFailed = 1<<2 

}; 

@protocol KMNineBoxViewDelegate<NSObject>

@optional

/**

*  在手势密码绘制完成后,此接口会返回验证信息

*

*  @param state        手势密码的验证结果

*  @param passSequence 用户绘制的手势密码的序列

*/

- (void)nineBoxDidFinishWithState:(KMNineBoxState)state passSequence:(NSString *)passSequence;

@end

@property (weak, nonatomic ) id delegate; /** * 预先设置好正确的密码序列,之后会与用户绘制的手势密码进行比较 */ 

@property (strong, nonatomic) NSString *predefinedPassSeq; 

 @property (assign, nonatomic) BOOL isOnceAgain;//是否是确认密码

 - (instancetype)initWithFrame:(CGRect)frame;

KMNineBoxView .m

typedef NS_ENUM(NSInteger, KMNineBoxIndex) {

    KMNineBoxIndexNone = 0,

    KMNineBoxIndex1 = 1<<0,

    KMNineBoxIndex2 = 1<<1,

    KMNineBoxIndex3 = 1<<2,

    KMNineBoxIndex4 = 1<<3,

    KMNineBoxIndex5 = 1<<4,

    KMNineBoxIndex6 = 1<<5,

    KMNineBoxIndex7 = 1<<6,

    KMNineBoxIndex8 = 1<<7,

    KMNineBoxIndex9 = 1<<8

};

定义变量


{

    CGFloat _selfBoundsX;

    CGFloat _selfBoundsY;


    CGFloat _selfFrameX;

    CGFloat _selfFrameY;

    CGFloat _selfFrameWidth;

    CGFloat _selfFrameHeight;

    CGFloat _selfFrameSquareWidth;          //!< 如果frame不是正方形,则取短边构造内置正方形


    CGFloat _unitLength;                    //!< 计算所需的单位长度,为KMNineBoxView幕宽度的八分之一

    CGFloat _marginWidth;                  //!< 页边距

    CGFloat _boxWidth;                      //!< 九宫格实际正方形底的边长,为页边距地两倍

    CGFloat _circleRadius;                  //!< 圆的半径,为0.7单位长度


    // 九宫格绘图相关

    NSMutableArray *_nineCirclesArr;        //!< 保存9个circleLayer的数组会随frame变化

    NSArray *_boxCentersArr;                //!< 保存9个中心点的位置,会随frame变化


    // 跟踪九宫格状态

    NSMutableArray *_sequenceArr;          //!< 保存九宫格序列的数组,会随触摸手势变化

    KMNineBoxState _nineBoxState;          //!< 九宫格底状态,主要关注普通和失败两种状态

    //连线相关

    NSMutableArray *_connectionLinesArr;    //!< 保存连线的数组,会随触摸手势变化

    CGPoint _currentBoxCenter;              //!< 现在这个中心点,两点确定一条线

    CGPoint _previousBoxCenter;            //!< 之前那个中心点,两点确定一条线

}

 初始化


- (void)initData

{

#if USE_DEBUG

    self.backgroundColor = [UIColor grayColor];

#endif


    _nineCirclesArr = [NSMutableArray arrayWithCapacity:9];

    _sequenceArr = [NSMutableArray arrayWithCapacity:9];// 9个点最多序列长度为9

    _connectionLinesArr = [NSMutableArray arrayWithCapacity:8];// 9个点最多也就8根线

    self.predefinedPassSeq = @"#########";

}

布局


- (void)setupBoundsAndFrame

{

    _selfBoundsX      = self.bounds.origin.x;

    _selfBoundsY      = self.bounds.origin.y;


    _selfFrameX      = self.frame.origin.x;

    _selfFrameY      = self.frame.origin.y;

    _selfFrameWidth  = self.frame.size.width;

    _selfFrameHeight  = self.frame.size.height;

    _selfFrameSquareWidth = (_selfFrameWidth<=_selfFrameHeight)? _selfFrameWidth : _selfFrameHeight;


    _unitLength = _selfFrameSquareWidth /8;

    _marginWidth = _unitLength;

    _boxWidth = _unitLength *2;

    _circleRadius = _unitLength *0.7;


    CGPoint boxCneter0 = CGPointMake(_unitLength+_unitLength *1, _unitLength+_unitLength *1);

    CGPoint boxCneter1 = CGPointMake(_unitLength+_unitLength *3, _unitLength+_unitLength *1);

    CGPoint boxCneter2 = CGPointMake(_unitLength+_unitLength *5, _unitLength+_unitLength *1);

    CGPoint boxCneter3 = CGPointMake(_unitLength+_unitLength *1, _unitLength+_unitLength *3);

    CGPoint boxCneter4 = CGPointMake(_unitLength+_unitLength *3, _unitLength+_unitLength *3);

    CGPoint boxCneter5 = CGPointMake(_unitLength+_unitLength *5, _unitLength+_unitLength *3);

    CGPoint boxCneter6 = CGPointMake(_unitLength+_unitLength *1, _unitLength+_unitLength *5);

    CGPoint boxCneter7 = CGPointMake(_unitLength+_unitLength *3, _unitLength+_unitLength *5);

    CGPoint boxCneter8 = CGPointMake(_unitLength+_unitLength *5, _unitLength+_unitLength *5);

    _boxCentersArr = @[[NSValue valueWithCGPoint:boxCneter0],

                      [NSValue valueWithCGPoint:boxCneter1],

                      [NSValue valueWithCGPoint:boxCneter2],

                      [NSValue valueWithCGPoint:boxCneter3],

                      [NSValue valueWithCGPoint:boxCneter4],

                      [NSValue valueWithCGPoint:boxCneter5],

                      [NSValue valueWithCGPoint:boxCneter6],

                      [NSValue valueWithCGPoint:boxCneter7],

                      [NSValue valueWithCGPoint:boxCneter8]

                      ];

}

- (void)layoutSubviews

{

    //改变frame,subviews,sublayers会跑进来

    [self setupBoundsAndFrame];


#if USE_DRAWRECT

    [self setNeedsDisplay];

#else

    [self reloadNineBox];

#endif

}


绘制按钮


- (void)drawRect:(CGRect)rect

{

    // Drawing code


    //    [[UIColor clearColor] setFill];  // changes are here

    //    UIRectFill(rect);

    [self reloadBaseCircle];

}

#endif

#pragma mark -  Set Nine Box

- (void)drawNineBox

{

    // 消除一切sublayer

    if ([self.layer.sublayers count] > 0) {

        self.layer.sublayers = nil;

    }


    for (NSValue *aValue in _boxCentersArr) {

        CGPoint aBoxCenter = [aValue CGPointValue];

        NSMutableDictionary *aCircleLayerDic = [self drawCircleAtPoint:aBoxCenter withRadius:_circleRadius];

        [_nineCirclesArr addObject:aCircleLayerDic];


        CAShapeLayer *circleLayer = [aCircleLayerDic objectForKey:kCircleLayer];

        CAShapeLayer *pointLayer = [aCircleLayerDic objectForKey:kPointLayer];

        [self.layer addSublayer:circleLayer];

        [self.layer addSublayer:pointLayer];

    }

}

- (void)reloadNineBox

{

    // need improve

//    return;

    // reload sublayers 只需要调整位置

    // 千万不能改变大小,调整层级,或者增删层级!

    // 千万不能改变大小,调整层级,或者增删层级!

    // 千万不能改变大小,调整层级,或者增删层级!

    // 重要的事说三遍


    if ([_nineCirclesArr count] != 9) {

        return;

    }


    for (int i = 0; i < [_nineCirclesArr count]; i++) {

        NSDictionary *aDic = _nineCirclesArr[i];

        CAShapeLayer *circleLayer = [aDic objectForKey:kCircleLayer];

        CAShapeLayer *pointLayer = [aDic objectForKey:kPointLayer];


        CGPoint boxCenter = [_boxCentersArr[i] CGPointValue];

        // 这里及时重设字典中圆心位置的信息

        [_nineCirclesArr[i] setObject:[NSValue valueWithCGPoint:boxCenter] forKey:kBoxCenter];




        // 画圆圈

        CGRect frameCircle = CGRectMake(boxCenter.x-_circleRadius, boxCenter.y-_circleRadius, _circleRadius *2, _circleRadius *2);

        //create a path: 矩形内切圆

        UIBezierPath *bezierPathCircle = [UIBezierPath bezierPathWithOvalInRect:frameCircle];

        //draw the path using a CAShapeLayer

        circleLayer.path = bezierPathCircle.CGPath;



        // 画中心的圆点

        CGRect framePoint = CGRectMake(boxCenter.x-_circleRadius/4, boxCenter.y-_circleRadius/4, _circleRadius /4*2, _circleRadius /4*2);

        //create a path: 矩形内切圆

        UIBezierPath *bezierPathPoint = [UIBezierPath bezierPathWithOvalInRect:framePoint];

        //draw the path using a CAShapeLayer

        pointLayer.path = bezierPathPoint.CGPath;


//////////////////////////////////////////////////////////////////////////////////////////////////////

        //有点迷,这里的position

//        circleLayer.position = CGPointMake(2, 2);

//////////////////////////////////////////////////////////////////////////////////////////////////////

    }

}

- (void)resetNineBox

{

    // 恢复响应用户手势

    self.userInteractionEnabled = YES;


    [self setNineBoxState:KMNineBoxStateNormal];


    // 上一步设置完普通状态后,再销毁这两个数组

    [_sequenceArr removeAllObjects];

    [_connectionLinesArr removeAllObjects];

}

- (NSMutableDictionary *)drawCircleAtPoint:(CGPoint)center withRadius:(CGFloat)radius

{

    // 画圆圈

    CGRect frameCircle = CGRectMake(center.x-_circleRadius, center.y-_circleRadius, _circleRadius *2, _circleRadius *2);

    //create a path: 矩形内切圆

    UIBezierPath *bezierPathCircle = [UIBezierPath bezierPathWithOvalInRect:frameCircle];

    //draw the path using a CAShapeLayer

    CAShapeLayer *circleLayer = [CAShapeLayer layer];

    circleLayer.path = bezierPathCircle.CGPath;

    circleLayer.fillColor = [UIColor clearColor].CGColor;

    circleLayer.strokeColor = kCircleStrokeColorNormal;

    circleLayer.lineWidth = kCircleLineWidthNormal;


    // 画中心的圆点

    CGRect framePoint = CGRectMake(center.x-_circleRadius/4, center.y-_circleRadius/4, _circleRadius /4*2, _circleRadius /4*2);

    //create a path: 矩形内切圆

    UIBezierPath *bezierPathPoint = [UIBezierPath bezierPathWithOvalInRect:framePoint];

    //draw the path using a CAShapeLayer

    CAShapeLayer *pointLayer = [CAShapeLayer layer];

    pointLayer.path = bezierPathPoint.CGPath;


#if USE_DEBUG

    pointLayer.fillColor = [UIColor greenColor].CGColor;

    pointLayer.strokeColor = [UIColor greenColor].CGColor;

#else

    pointLayer.fillColor = kPointFillColorNormal;

    pointLayer.strokeColor = kPointFillColorNormal;

#endif

    pointLayer.lineWidth = kCircleLineWidthNormal;

    // 圆心位置

    NSValue *boxCenter = [NSValue valueWithCGPoint:center];


    //保存圆圈,圆点和圆心位置

    NSMutableDictionary *circleLayerDic = [NSMutableDictionary dictionary];

    [circleLayerDic setObject:circleLayer forKey:kCircleLayer];

    [circleLayerDic setObject:pointLayer forKey:kPointLayer];

    [circleLayerDic setObject:boxCenter forKey:kBoxCenter];


    return circleLayerDic;

}

- (void)setNineBoxState:(KMNineBoxState)nineBoxState

{

    _nineBoxState = nineBoxState;


    switch (nineBoxState) {

        case KMNineBoxStateNormal: {

            // 设置9个圆圈为普通状态

            for (NSDictionary *aDic in _nineCirclesArr) {

                CAShapeLayer *circleLayer = [aDic objectForKey:kCircleLayer];

                CAShapeLayer *pointLayer = [aDic objectForKey:kPointLayer];


                circleLayer.strokeColor = kCircleStrokeColorNormal;

                circleLayer.lineWidth = kCircleLineWidthNormal;


                pointLayer.fillColor = kPointFillColorNormal;

                pointLayer.strokeColor = kPointFillColorNormal;

            }


            //消除红色连线

            for (int i = 0; i < [_connectionLinesArr count]; i++) {

                CAShapeLayer *aLinelayer = _connectionLinesArr[i];

                [aLinelayer removeFromSuperlayer];

            }


            break;

        }


        case KMNineBoxStateTouched: {


            break;

        }


        case KMNineBoxStatePassed: {


            break;

        }


        case KMNineBoxStateFailed: {

            // 设置触摸过的圆圈为红色


            NSLog(@"_sequenceArr  %@",_sequenceArr);


            for (int i = 0; i < [_sequenceArr count]; i++) {

                // 取出序列的每一个单步

                NSInteger circleIndex = [_sequenceArr[i] integerValue];

                // 找出对应的circleLayerDic

                NSDictionary *aDic = _nineCirclesArr[circleIndex];

                CAShapeLayer *circleLayer = [aDic objectForKey:kCircleLayer];

                CAShapeLayer *pointLayer = [aDic objectForKey:kPointLayer];


                circleLayer.strokeColor = kCircleStorkeColorInvalid;

                circleLayer.lineWidth = kCircleLineWidthInvalid;


                pointLayer.fillColor = kPointFillColorInvalid;

                pointLayer.strokeColor = kPointFillColorInvalid;

            }


            //设置连线为红色

            for (int i = 0; i < [_connectionLinesArr count]; i++) {

                CAShapeLayer *aLinelayer = _connectionLinesArr[i];

                aLinelayer.fillColor = kConnectionLineColorInvalid;

                aLinelayer.strokeColor = kConnectionLineColorInvalid;

            }


            break;

        }


        default:

            break;

    }

}

- (void)decorateCircleWithBoxIndex:(KMNineBoxIndex)index

{

    if (index == KMNineBoxIndexNone) {

        return;

    }


    NSInteger circleIndex = log2(index);

//    NSLog(@"circleIndex: %ld", (long)circleIndex);


    NSDictionary *aDic = _nineCirclesArr[circleIndex];

    CAShapeLayer *circleLayer = [aDic objectForKey:kCircleLayer];

    CAShapeLayer *pointLayer = [aDic objectForKey:kPointLayer];


    circleLayer.strokeColor = kCircleStrokeColorTouched;

    circleLayer.lineWidth = kCircleLineWidthTouched;


    pointLayer.fillColor = kPointFillColorTouched;

    pointLayer.strokeColor = kPointFillColorTouched;


    NSString *checkStr = [NSString stringWithFormat:@"%ld", circleIndex];

    if (![self checkString:checkStr isInArray:_sequenceArr]) {

        // 不允许重复添加

        [_sequenceArr addObject:checkStr];

    }


    [self drawConnectionLine];

}

- (void)drawConnectionLine

{

    NSInteger count = [_sequenceArr count];

    if (count > 1) {

        // 只有一个圆被触摸的时候不用画连接线

        NSInteger currentIndex = [[_sequenceArr lastObject] integerValue];

        NSInteger previousIndex = [[_sequenceArr objectAtIndex:(count-2)] integerValue];


        NSDictionary *currentCircleLayerDic = _nineCirclesArr[currentIndex];

        NSDictionary *previousCircleLayerDic = _nineCirclesArr[previousIndex];


        CGPoint currentBoxCenter = [[currentCircleLayerDic objectForKey:kBoxCenter] CGPointValue];

        CGPoint previousBoxCenter = [[previousCircleLayerDic objectForKey:kBoxCenter] CGPointValue];


        // 新的两点连线,才继续画

        if ([KMMathHelper point1:currentBoxCenter EqualToPoint2:_currentBoxCenter] &&

            [KMMathHelper point1:previousBoxCenter EqualToPoint2:_previousBoxCenter]) {

            return;

        }


        // 保存最近的两个点

        _currentBoxCenter = currentBoxCenter;

        _previousBoxCenter = previousBoxCenter;




        // 画线

        CAShapeLayer *lineLayer = [CAShapeLayer layer];

        UIBezierPath *linePath = [UIBezierPath bezierPath];

        [linePath moveToPoint: previousBoxCenter];

        [linePath addLineToPoint: currentBoxCenter];

        lineLayer.path = linePath.CGPath;

        lineLayer.fillColor = kConnectionLineColorTouched;

        lineLayer.strokeColor = kConnectionLineColorTouched;

        lineLayer.lineWidth = kConnectionLineWidth;


        [self.layer addSublayer:lineLayer];


        [_connectionLinesArr addObject:lineLayer];

    }

}

#pragma mark - Support Methods- (KMNineBoxIndex)checkLocationWithTouchPoint:(CGPoint)touchPoint{ 

 // 此处可以优化

 NSMutableArray *distanceArr = [NSMutableArray arrayWithCapacity:9]; for (int i = 0; i < [_nineCirclesArr count]; i++) {

 NSDictionary *aDic = _nineCirclesArr[i]; 

 CGPoint aBoxCenter = [[aDic objectForKey:kBoxCenter] CGPointValue];

 double distance = [KMMathHelper getDistanceBetweenPoint1:touchPoint point2:aBoxCenter]; 

 [distanceArr addObject:[NSNumber numberWithDouble:distance]]; 

 } 

 double minD = [distanceArr[0] doubleValue]; 

// 最短的距离

 int index = 0; 

 // 最短距离对应的序号 for (int i = 0; i<[distanceArr count]; i++) { 

 double d = [distanceArr[i] doubleValue];

 if (d < minD) {

 minD = d; index = i; 

 } 

 }

 if (minD > _circleRadius) {

// 触点在圆外 

 return KMNineBoxIndexNone;

 } else { 

 // 触点在圆内 

 KMNineBoxIndex boxIndex = 1<<index;

return boxIndex;

}

}

- (BOOL)checkString:(NSString *)str isInArray:(NSMutableArray *) arr {

    for (NSString *aStr in arr) {

        if ([aStr isEqualToString:str]) {

            return YES;

        }

    }


    return NO;

}

- (void)touches withEvent:(nullable UIEvent *)event{ 

 //get the touch point 

 CGPoint point = [[touches anyObject] locationInView:self];

// NSLog(@"begin point: (%f,%f)", point.x, point.y);

 KMNineBoxIndex index = [self checkLocationWithTouchPoint:point];

 [self decorateCircleWithBoxIndex:index];

}

- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent *)event{

 CGPoint point = [[touches anyObject] locationInView:self];// NSLog(@"moved point: (%f,%f)", point.x, point.y);

 KMNineBoxIndex index = [self checkLocationWithTouchPoint:point]; 

 [self decorateCircleWithBoxIndex:index];

}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

{

//    CGPoint point = [[touches anyObject] locationInView:self];

//    NSLog(@"ended point: (%f,%f)", point.x, point.y);



    NSString *sequenceStr = @"";

    for (int i = 0; i < [_sequenceArr count]; i++) {


        //程序员从0计数,这里需要转换成用户习惯从1开始,如果不需要考虑这一点,那么直接取出用即可

        NSString *tmp = [NSString stringWithFormat:@"%@", _sequenceArr[i]];


        sequenceStr = [NSString stringWithFormat:@"%@%@", sequenceStr, tmp];

    }

    NSLog(@"Seq: %@", sequenceStr);


    if ([self.predefinedPassSeq isEqualToString:@""]) {

        //本地没存

        [self setNineBoxState:(KMNineBoxStateNormal)];


    }else if ([self.predefinedPassSeq isEqualToString:sequenceStr]) {

        [self setNineBoxState:KMNineBoxStatePassed];

    }

    else {

        [self setNineBoxState:KMNineBoxStateFailed];

    }


    if ([self.delegate respondsToSelector:@selector(nineBoxDidFinishWithState:passSequence:)]) {

        [self.delegate nineBoxDidFinishWithState:_nineBoxState passSequence:sequenceStr];

    }


    // 再重置前不再响应用户触摸

    self.userInteractionEnabled = NO;

    //延迟1秒再重置

    dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));

    dispatch_after(delay, dispatch_get_main_queue(), ^(void){

        [self resetNineBox];

    });

}

KMMathHelper.h


/**

*  求二维空间两点的中点

*

*  @param point1 点1

*  @param point2 点2

*

*  @return 中点

*/

+ (CGPoint)getMiddleFromPoint1:(CGPoint)point1 point2:(CGPoint)point2;

/**

*  求二维空间两点的几何距离

*

*  @param point1 点1

*  @param point2 点2

*

*  @return 距离

*/

+ (double)getDistanceBetweenPoint1:(CGPoint)point1 point2:(CGPoint)point2;

/**

*  根据位移和方向角求新的点

*

*  @param currentPoint 当前点

*  @param offset      位移(位移为负时其实为反方向)

*  @param angle        方向角

*

*  @return 新的点

*/

+ (CGPoint)getNewPointFromCurrentPoint:(CGPoint)currentPoint offset:(double)offset angle:(double)angle;

/**

*  已知直线上起点和终点,根据位移比例求运动点

*

*  @param startPoint 起点

*  @param endPoint  终点

*  @param rate      比例

*

*  @return 运动点

*/

+ (CGPoint)getNewPointFromStartPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint rate:(double)rate;

/**

*  求两点的斜率亦梯度

*

*  @param point1 点1

*  @param point2 点2

*

*  @return 斜率(以点1->点2为正方向),可能会因斜率无限大返回NAN,NAN请用isnan(k)来判断

*/

+(double)getGradientFromPoint1:(CGPoint)point1 point2:(CGPoint)point2;

/**

*  判断两个CGPoint是否相同

*

*  @param point1 点1

*  @param point2 点2

*

*  @return 相同返回YES,不同返回NO

*/

+ (BOOL)point1:(CGPoint)point1 EqualToPoint2:(CGPoint)point2;

KMMathHelper.h


+ (CGPoint)getMiddleFromPoint1:(CGPoint)point1 point2:(CGPoint)point2

{

    CGPoint middle = CGPointMake((point1.x+point2.x)/2,

                                (point1.y+point2.y)/2);

    return middle;

}

+ (double)getDistanceBetweenPoint1:(CGPoint)point1 point2:(CGPoint)point2

{

    double xDiff = point1.x - point2.x;

    double yDiff = point1.y - point2.y;

    double distance = sqrt(xDiff*xDiff + yDiff*yDiff);

    return distance;

}

+ (CGPoint)getNewPointFromCurrentPoint:(CGPoint)currentPoint offset:(double)offset angle:(double)angle

{

    CGPoint newPoint = CGPointMake(currentPoint.x + offset*cos(angle),

                                  currentPoint.y + offset*sin(angle));

    return newPoint;

}

+ (CGPoint)getNewPointFromStartPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint rate:(double)rate

{

    double xDiff = endPoint.x - startPoint.x;

    double yDiff = endPoint.y - startPoint.y;

    double xOffset = xDiff*rate;

    double yOffset = yDiff*rate;


    CGPoint newPoint = CGPointMake(startPoint.x+xOffset, startPoint.y+yOffset);

    return newPoint;

}

+ (double)getGradientFromPoint1:(CGPoint)point1 point2:(CGPoint)point2

{

    double xDiff = point2.x - point1.x;

    double yDiff = point2.y - point1.y;

    if (xDiff == 0) {//斜率无限大咱就不算了

        return NAN;

    }

    else {

        double gradient = yDiff/xDiff;

        if (isnan(gradient)) {//斜率太大超过系统阈值

            return NAN;

        }

        return gradient;

    }

}

+ (BOOL)point1:(CGPoint)point1 EqualToPoint2:(CGPoint)point2

{

    if (point1.x==point2.x && point1.y==point2.y) {

        return YES;

    }

    return NO;

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,128评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,316评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,737评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,283评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,384评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,458评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,467评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,251评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,688评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,980评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,155评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,818评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,492评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,142评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,382评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,020评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,044评论 2 352

推荐阅读更多精彩内容