最近接到需求,要做一個(gè)可以用slider控制長(zhǎng)寬高,并且支持自適應(yīng)畫(huà)布大小的立方體盒子。
先上效果圖

截屏2021-07-01 上午11.07.08.png
需要自己建立一個(gè)立方體,然后給八個(gè)頂點(diǎn)命名。

37D5E690-FF15-4BBF-A509-B15DDE3A401B.png
我們分析一下,需要畫(huà)出來(lái)的一共有8個(gè)頂點(diǎn),3個(gè)面(里面的面如因?yàn)楸粨踝×?,所以不需要?huà)),12根邊。
為此,建立一個(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;
}
給畫(huà)筆設(shè)置顏色
[color set];
然后先畫(huà)前面一個(gè)面:
//畫(huà)前面
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)繪制路徑
然后同理依次畫(huà)右邊,上邊的面:
//畫(huà)右邊
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)繪制路徑
//畫(huà)上邊
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)繪制路徑
然后再畫(huà)12條邊:
首先設(shè)置虛線的樣式
//畫(huà)虛線
CGFloat dashArray[] = {2, 4}; // 表示先繪制2個(gè)點(diǎn),再跳過(guò)4個(gè)點(diǎn)
CGContextSetLineDash(context, 0, dashArray, 2); // 畫(huà)虛線
//指定直線樣式
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è)要求就是,如果立方體的任意一邊超出畫(huà)布后,需要把畫(huà)布進(jìn)行縮放以適應(yīng)整個(gè)立方體全部顯示在畫(huà)布內(nèi)。
因?yàn)槲覀兊牧⒎襟w始終在畫(huà)布的左下角,所以只需要判斷右上角有沒(méi)有超出畫(huà)布范圍就好了。(如果你們沒(méi)有要求在左下角,那只需要判斷右下角即可,總之需要把所有頂點(diǎn)都顯示出來(lái))
if (self.y1.x > canvas.size.width || self.y1.y < 0) {
//超出畫(huà)布區(qū)域,實(shí)行縮放畫(huà)布
CGFloat ratioX = self.y1.x / canvas.size.width;
CGFloat ratioY = (canvas.size.height - self.y1.y) / canvas.size.height;
CGFloat ratio = MAX(ratioX, ratioY);
//畫(huà)布縮小到 ratio
if (self.ratioBlock) {
self.ratioBlock(ratio);
}
}
以上,基本就是全部?jī)?nèi)容。
附上代碼地址:
https://github.com/zgsddzwj/SSAnimatedBox
喜歡的話給個(gè)star吧~