iOS可以拖動(dòng)控制大小的立方體盒子

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

先上效果圖

截屏2021-07-01 上午11.07.08.png

需要自己建立一個(gè)立方體芯义,然后給八個(gè)頂點(diǎn)命名哈垢。

37D5E690-FF15-4BBF-A509-B15DDE3A401B.png

我們分析一下,需要畫出來(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吧~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末手形,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子悯恍,更是在濱河造成了極大的恐慌库糠,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涮毫,死亡現(xiàn)場(chǎng)離奇詭異瞬欧,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)罢防,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門艘虎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人咒吐,你說(shuō)我怎么就攤上這事野建。” “怎么了恬叹?”我有些...
    開(kāi)封第一講書人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵候生,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我绽昼,道長(zhǎng)唯鸭,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任硅确,我火速辦了婚禮肿孵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘疏魏。我一直安慰自己,他們只是感情好晤愧,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布大莫。 她就那樣靜靜地躺著,像睡著了一般官份。 火紅的嫁衣襯著肌膚如雪只厘。 梳的紋絲不亂的頭發(fā)上烙丛,一...
    開(kāi)封第一講書人閱讀 49,785評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音羔味,去河邊找鬼河咽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛赋元,可吹牛的內(nèi)容都是我干的忘蟹。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼搁凸,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼媚值!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起护糖,我...
    開(kāi)封第一講書人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤褥芒,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后嫡良,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體锰扶,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年寝受,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了坷牛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡羡蛾,死狀恐怖漓帅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情痴怨,我是刑警寧澤忙干,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站浪藻,受9級(jí)特大地震影響捐迫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜爱葵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一施戴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧萌丈,春花似錦赞哗、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春藤乙,著一層夾襖步出監(jiān)牢的瞬間猜揪,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工坛梁, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留而姐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓划咐,卻偏偏與公主長(zhǎng)得像拴念,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子尖殃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348

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