1. 程式人生 > >動態計算選中路徑,畫虛線框

動態計算選中路徑,畫虛線框

我大哥說過,【沒有一種演算法是脫離實際問題而存在的。】
於是,當我遇到這個問題時候,我知道計算機理論上學的演算法都不能解決這個問題,我需要靈活運用。
這裡寫圖片描述
例1
這裡寫圖片描述
例2

專案中遇到這麼一個棘手的問題,要根據網路獲取的實時資料,把同一工序的狀態畫虛線框起來。
也不算是個很困難的問題,但是還是有一定的複雜度,經過一晚上思考,找到了一種比較好的演算法。

相信看完了圖片,大家發現了這個演算法的核心所在——就是每一行上面的4個輔助點。所包含的範圍起始分解一下就是n個矩形,然後根據矩形的4個角的點,連線即可。

所以,步驟就有了:
第一步:根據給定的起始圓圈和終止圓圈,找出所有選中的圓圈 放在selectedArr中
第二部:便利selectedArr,找出每一行的最左邊和最右邊的圓圈,分別放進leftProviews和rightProviews陣列中,為了取四角的座標值用
第三部:左邊的座標依次連線,右邊的座標依次連線,最有把最頂上和最底下兩個座標相連,一個虛線框就出來了。

【圓圈是ProcessView:UIButton】
為了方便我判斷行列,我繼承UIButton,給button添加了row和count兩個屬性
@row:行
@count:順序(這裡之所以不用cow列來表示,是因為隔行的圓圈順序排列是相反的,有的從左到右,有的從右到左)

/**
 給定起始圓圈和結束圓圈 找圓圈陣列,找矩形,最後畫線框
 @param start 開始圓圈
 @param end   結束圓圈
 */
-(void)DrawDashLineRectStart:(ProcessView *)start end:(ProcessView *)end{

    // 畫之前先清除之前的虛線
NSArray *sublayers = [NSArray arrayWithArray:self.contentView.layer.sublayers]; for (CALayer *ly in sublayers) { if ([ly isKindOfClass:[XLShapeLayer class]]) { XLShapeLayer *xlL = (XLShapeLayer *)ly; if (xlL.tag == 999) { [xlL removeFromSuperlayer]; } } } NSMutableArray *selectedArr = [NSMutableArray new
]; for (short i = start.row; i<=end.row; i++) { for (short j = 0; j<6; j++) { if(i == start.row && j < start.count) continue; if (i == end.row && j > end.count) break; ProcessView *pro = (ProcessView *)[self.contentView viewWithTag:60+(i*6+j)]; [selectedArr addObject:pro]; //DLog(@"pro:%ld %ld", pro.row, pro.count); //DLog(@"%@",pro.titleLabel.text); } } // 列印該被選中的陣列 //DLog(@"Pro:%@",selectedArr); // 分出左右陣列 左陣列存放左邊的點依賴的圓圈 右陣列同理。 NSMutableArray *leftPros = [NSMutableArray new]; NSMutableArray *rightPros = [NSMutableArray new]; for (ProcessView *pro in selectedArr) { if (end.row > start.row) { if (pro.row%2==0) { if ((pro.count==0) || pro==start) { [leftPros addObject:pro]; } if (pro.count == 5 || pro==end) { [rightPros addObject:pro]; } } if (pro.row%2==1) { if ((pro.count==0 || pro == start)) { [rightPros addObject:pro]; } if (pro.count==5 || pro==end) { [leftPros addObject:pro]; } } }else{ if (end.row%2==0) { [leftPros addObject:start]; [rightPros addObject:end]; }else{ [leftPros addObject:end]; [rightPros addObject:start]; } break; } } /* // 左右陣列資訊列印 for (short i =0; i<leftPros.count; i++) { ProcessView *p = leftPros[i]; DLog(@"L:%@",p.titleLabel.text); } for (short i =0; i<rightPros.count; i++) { ProcessView *p = rightPros[i]; DLog(@"R:%@",p.titleLabel.text); } */ // 根據左右陣列,找到左邊的所有點 和右邊的所有點 然後依次相連 // spc是實際的點與圓圈frame的偏移量,因為虛線要離開圓圈一段距離 NSMutableArray *leftPoints = [NSMutableArray new]; NSMutableArray *rightPoints = [NSMutableArray new]; CGAffineTransform lastTransform; for (ProcessView *pro in leftPros) { lastTransform = pro.layer.affineTransform; pro.layer.affineTransform = pro->affineTransform; CGPoint start = CGPointMake(pro.frame.origin.x-spc/2., pro.frame.origin.y-spc/2.); CGPoint end = CGPointMake(start.x, CGRectGetMaxY(pro.frame)+spc/2.); [leftPoints addObject:NSStringFromCGPoint(start)]; [leftPoints addObject:NSStringFromCGPoint(end)]; pro.layer.affineTransform = lastTransform; } for (ProcessView *pro in rightPros) { lastTransform = pro.layer.affineTransform; pro.layer.affineTransform = pro->affineTransform; CGPoint start = CGPointMake(CGRectGetMaxX(pro.frame)+spc/2., pro.frame.origin.y-spc/2.); CGPoint end = CGPointMake(start.x, CGRectGetMaxY(pro.frame)+spc/2.); [rightPoints addObject:NSStringFromCGPoint(start)]; [rightPoints addObject:NSStringFromCGPoint(end)]; pro.layer.affineTransform = lastTransform; } //左邊的點連線 for (short i=leftPoints.count-1; i>0; i--) { CGPoint start = CGPointFromString(leftPoints[i]); CGPoint end = CGPointFromString(leftPoints[i-1]); [self drawDashLineStart:start end:end]; } //右邊的點連線 for (short i=rightPoints.count-1; i>0; i--) { CGPoint start = CGPointFromString(rightPoints[i]); CGPoint end = CGPointFromString(rightPoints[i-1]); [self drawDashLineStart:start end:end]; } // 頂上和地下的點連線 CGPoint topL = CGPointFromString(leftPoints[0]); CGPoint topR = CGPointFromString(rightPoints[0]); CGPoint btmL = CGPointFromString([leftPoints lastObject]); CGPoint btmR = CGPointFromString([rightPoints lastObject]); [self drawDashLineStart:topL end:topR]; [self drawDashLineStart:btmL end:btmR]; }

畫虛線的方法,用CAShapeLayer即可

/**
 給定起點 重點畫虛線

 @param start 起點座標
 @param end   終點座標
 */
- (void)drawDashLineStart:(CGPoint)start end:(CGPoint)end{
    //NSLog(@"%@",NSStringFromCGRect(lineView.frame));

    XLShapeLayer *shapeLayer = [XLShapeLayer layer];
    shapeLayer.tag = 999;
    [shapeLayer setBounds:self.contentView.bounds];
    [shapeLayer setPosition:CGPointMake(CGRectGetWidth(self.contentView.frame)/2.f, CGRectGetHeight(self.contentView.frame)/2.f)];
    [shapeLayer setFillColor:[[UIColor clearColor] CGColor]];
    // 設定虛線顏色為blackColor [shapeLayer setStrokeColor:[[UIColor blackColor] CGColor]];
    [shapeLayer setStrokeColor:KLIGHTGRAYCOLOR.CGColor];
    // 3.0f設定虛線的寬度 [shapeLayer setLineWidth:1.0f];
    [shapeLayer setLineJoin:kCALineJoinRound];
    // 3=線的寬度 1=每條線的間距 [shapeLayer setLineDashPattern:
    [shapeLayer setLineDashPattern:[NSArray arrayWithObjects:[NSNumber numberWithInt:1],[NSNumber numberWithInt:3],nil]];
    // Setup the path CGMutablePathRef path = CGPathCreateMutable();
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, start.x, start.y);
    CGPathAddLineToPoint(path, NULL, end.x,end.y);

    [shapeLayer setPath:path];
    CGPathRelease(path);
    [self.contentView.layer addSublayer:shapeLayer];
}