最近接到需求,要做一個(gè)可以用slider控制長(zhǎng)寬高侨颈,并且支持自適應(yīng)畫布大小的立方體盒子。
先上效果圖
需要自己建立一個(gè)立方體芯义,然后給八個(gè)頂點(diǎn)命名哈垢。
我們分析一下,需要畫出來(lái)的一共有8個(gè)頂點(diǎn)扛拨,3個(gè)面(里面的面如因?yàn)楸粨踝×嗽欧郑圆恍枰嫞?2根邊。
為此绑警,建立一個(gè)立方體對(duì)應(yīng)的Model求泰,在Model中把傳入的長(zhǎng)寬高轉(zhuǎn)化為立方體的八個(gè)頂點(diǎn)的坐標(biāo)值。
側(cè)邊的邊長(zhǎng)是w的話计盒,那么y0的值就是w/√2渴频,y1就是長(zhǎng)L+ w/√2,然后依次算出y2北启、y3卜朗、z0-z3。
-(void)updateL:(CGFloat )L w:(CGFloat)w h:(CGFloat)h canvas:(CGRect)canvas {
CGFloat geng = 0.707;// 根號(hào)2分之一
self.y0 = CGPointMake(w*geng, 0); //newy0;
self.y1 = CGPointMake(L + w *geng, 0);// newy1;
self.y2 = CGPointMake(L, w * geng);// newy2;
self.y3 = CGPointMake(0, w * geng);// newy3;
self.z0 = CGPointMake( w * geng, h);// newz0;
self.z1 = CGPointMake(L + w * geng, h) ;//newz1;
self.z2 = CGPointMake(L, h + w * geng);// newz2;
self.z3 = CGPointMake(0, h + w * geng);// newz3;
}
給畫筆設(shè)置顏色
[color set];
然后先畫前面一個(gè)面:
//畫前面
CGPoint sPoints0[4];
sPoints0[0] = box.y3;
sPoints0[1] = box.y2;
sPoints0[2] = box.z2;
sPoints0[3] = box.z3;
CGContextAddLines(context, sPoints0, 4);//添加線
[[UIColor clearColor] setStroke];//避免影響方格線
CGContextClosePath(context);//封起來(lái)
CGContextDrawPath(context, kCGPathFillStroke); //根據(jù)坐標(biāo)繪制路徑
然后同理依次畫右邊咕村,上邊的面:
//畫右邊
CGPoint sPoints[4];//坐標(biāo)點(diǎn)
sPoints[0] =box.y1;//坐標(biāo)1
sPoints[1] =box.z1;
sPoints[2] = box.z2;
sPoints[3] = box.y2;
CGContextAddLines(context, sPoints, 4);//添加線
CGContextClosePath(context);//封起來(lái)
CGContextDrawPath(context, kCGPathFillStroke); //根據(jù)坐標(biāo)繪制路徑
//畫上邊
CGPoint sPoints2[4];//坐標(biāo)點(diǎn)
sPoints2[0] = box.y0;
sPoints2[1] = box.y1;
sPoints2[2] = box.y2;
sPoints2[3] = box.y3;
CGContextAddLines(context, sPoints2, 4);//添加線
CGContextClosePath(context);//封起來(lái)
CGContextDrawPath(context, kCGPathFillStroke); //根據(jù)坐標(biāo)繪制路徑
然后再畫12條邊:
首先設(shè)置虛線的樣式
//畫虛線
CGFloat dashArray[] = {2, 4}; // 表示先繪制2個(gè)點(diǎn)场钉,再跳過(guò)4個(gè)點(diǎn)
CGContextSetLineDash(context, 0, dashArray, 2); // 畫虛線
//指定直線樣式
CGContextSetLineCap(context, kCGLineCapSquare);
//直線寬度
CGContextSetLineWidth(context, 1);
//設(shè)置顏色
CGContextSetStrokeColorWithColor(context, lineColor.CGColor);
然后依次繪制12條邊:
//開(kāi)始繪制
CGContextBeginPath(context);
//上邊
CGContextMoveToPoint(context, box.y0.x, box.y0.y);
CGContextAddLineToPoint(context, box.y1.x, box.y1.y);
CGContextAddLineToPoint(context, box.y2.x, box.y2.y);
CGContextAddLineToPoint(context, box.y3.x, box.y3.y);
CGContextAddLineToPoint(context, box.y0.x, box.y0.y);
//左邊
CGContextAddLineToPoint(context, box.z0.x, box.z0.y);
CGContextAddLineToPoint(context, box.z3.x, box.z3.y);
CGContextAddLineToPoint(context, box.y3.x, box.y3.y);
//下邊
CGContextMoveToPoint(context, box.z0.x, box.z0.y);
CGContextAddLineToPoint(context, box.z1.x, box.z1.y);
CGContextAddLineToPoint(context, box.z2.x, box.z2.y);
CGContextAddLineToPoint(context, box.z3.x, box.z3.y);
//剩余的兩根
CGContextMoveToPoint(context, box.y2.x, box.y2.y);
CGContextAddLineToPoint(context, box.z2.x, box.z2.y);
CGContextMoveToPoint(context, box.y1.x, box.y1.y);
CGContextAddLineToPoint(context, box.z1.x, box.z1.y);
//繪制完成
CGContextStrokePath(context);
以上,就是一個(gè)立方體的繪制過(guò)程懈涛。
滑動(dòng)slider時(shí)逛万,只需要把對(duì)應(yīng)的slider的value乘以長(zhǎng)寬高的最大值,就得到每條邊的實(shí)際值批钠。
CGFloat l = self.maxL * self.sliderL.value;
CGFloat w = self.maxW * self.sliderW.value;
CGFloat h = self.maxH * self.sliderH.value;
然后更新立方體
[self.boxView updateL:l w:w h: h];
我們還有一個(gè)要求就是宇植,如果立方體的任意一邊超出畫布后得封,需要把畫布進(jìn)行縮放以適應(yīng)整個(gè)立方體全部顯示在畫布內(nèi)。
因?yàn)槲覀兊牧⒎襟w始終在畫布的左下角当纱,所以只需要判斷右上角有沒(méi)有超出畫布范圍就好了呛每。(如果你們沒(méi)有要求在左下角,那只需要判斷右下角即可坡氯,總之需要把所有頂點(diǎn)都顯示出來(lái))
if (self.y1.x > canvas.size.width || self.y1.y < 0) {
//超出畫布區(qū)域晨横,實(shí)行縮放畫布
CGFloat ratioX = self.y1.x / canvas.size.width;
CGFloat ratioY = (canvas.size.height - self.y1.y) / canvas.size.height;
CGFloat ratio = MAX(ratioX, ratioY);
//畫布縮小到 ratio
if (self.ratioBlock) {
self.ratioBlock(ratio);
}
}
以上,基本就是全部?jī)?nèi)容箫柳。
附上代碼地址:
https://github.com/zgsddzwj/SSAnimatedBox
喜歡的話給個(gè)star吧~