溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

IOS CGContextSetLineWidth無法設置1像素線寬?

發(fā)布時間:2020-10-13 16:21:12 來源:網絡 閱讀:669 作者:李遠超0317 欄目:移動開發(fā)

前段時間美術在驗收界面時提了問題:為啥要求1像素寬的一個矩形框似乎卻變成了2,3個像素寬。仔細檢查過代碼后發(fā)現,的確設置了LineWidth為1,但繪制效果卻并不如人愿。似乎在ios上繪制最低要2個像素的線寬。

       查看文檔后發(fā)現造成這個問題的原因是Quartz的抗鋸齒機制。一種粗暴的解決方案是不采用抗鋸齒,即:CGContextSetShouldAntialias(context, NO)。但是顯而易見的問題是取消抗鋸齒會導致繪制效果變差。而另外一種方案則比較取巧:將繪制調整到半像素坐標系上:

比如 CGContextMoveToPoint(context, 100.0, 100.0); CGContextAddLineToPoint(context, 100.0, 200.0);改為 CGContextMoveToPoint(context, 100.5, 100.5); CGContextAddLineToPoint(context,100.5, 200.5);

這是因為:所謂的線寬指的是給定路徑的中心到兩邊的粗細,換句話是在路徑的兩邊各繪制一半。如圖

IOS CGContextSetLineWidth無法設置1像素線寬?

在繪制線寬為1的直線(3,1)到(3,5)時,實際上是占據了左右兩個像素各半個像素,而真正繪制時當然是以一個像素為標準單位,所以淺藍色區(qū)域就會以相近的方式進行渲染。這也是寬為1.0的線繪制并不準確的原因。而當將繪制中心調整到半個像素上就不會有這個問題,見右圖:(3.5,1)到(3.5,5)。詳細可以參考mozilla canvas繪制的文檔。

       最后上一個在ios上繪制帶圓角矩形的代碼:


if (radius <= 0)
{
    CGContextAddRect(context, rect);
    return;
}
       
CGContextSaveGState(context);
CGContextTranslateCTM(context, CGRectGetMinX(rect), CGRectGetMinY(rect));
CGContextScaleCTM(context, radius, radius);
NSInteger width     = CGRectGetWidth(rect) / radius;
NSInteger height    = CGRectGetHeight(rect) / radius;
NSInteger halfWidth = width / 2;
NSInteger halfHeight= height / 2;
       
CGContextMoveToPoint  (context, width + 0.5, halfHeight + 0.5);
CGContextAddArcToPoint(context, width + 0.5, height + 0.5, halfWidth + 0.5, height + 0.5, 1); 
CGContextAddArcToPoint(context, 0 + 0.5, height + 0.5, 0 + 0.5, halfHeight + 0.5, 1);
CGContextAddArcToPoint(context, 0 + 0.5, 0 + 0.5, halfWidth + 0.5, 0 + 0.5, 1);
CGContextAddArcToPoint(context, width + 0.5, 0 + 0.5, width + 0.5, halfHeight + 0.5, 1);
       
CGContextClosePath(context);
CGContextRestoreGState(context);

原文轉載:http://xiangwangfeng.com/2012/03/24/為啥cgcontextsetlinewidth設置不了1pixel線框?/

以下是自己測試得出的結論,如有異意請各位老師不吝賜教,謝謝!

由于retina屏幕是640像素,而非retina是320,所以,分兩種情況,在retina屏幕下和非retina屏幕下。

畫一條從點(10.0, 10.0)到點(10.0, 100.0)的直線和點(10.5, 10.5)到點(10.5, 100.5)的直線,產生的樣式,上面都解釋了。

我想說的是從點(10.3, 10.3)到點(10.3, 100.3)的黑色一個像素的直線,CGContextSetShouldAntialias(context, YES)。

一、在retina屏幕下

   ==IOS CGContextSetLineWidth無法設置1像素線寬?==這個圖片是我畫出的線放大后的效果,我計算了,它繪制的是20、21、22這三個像素值,也就是說10.3 * 2 = 20.6;那么它會將第21個像素值繪制黑色,兩邊的繪制暗色。

二、在非retina屏幕下

   ==IOS CGContextSetLineWidth無法設置1像素線寬?==這個圖片是我畫出的線放大后的效果,計算后,它繪制的是10、11這兩個像素值,那么它會將第11個像素值繪制黑色,10的繪制成暗色。

我還要說從點(10.7, 10.7)到點(10.7, 100.7)的黑色一個像素的直線,CGContextSetShouldAntialias(context, YES)。

一、在retina屏幕下

   圖片樣式還是一樣的,但是位置變了,這次畫的是21、22、23這三個像素值,也就是說10.7 * 2 = 21.4;那么他是將第22個像素值繪制黑色,兩邊的繪制暗色。

二、在非retina屏幕下    

   ==IOS CGContextSetLineWidth無法設置1像素線寬?==這個圖片是我畫出的線放大后的效果,計算后,它繪制的是11、12這兩個像素值,那么它會將第11個像素值繪制黑色,12的繪制成暗色。

在說一說CGContextSetShouldAntialias(context, NO)。10.3和10.7的結果如下

一、在retina屏幕下

   繪制位置都一樣,但是樣式變了,變成沒有暗色全是黑色。

二、在非retina屏幕下

   位置樣式都變了,顏色只是黑色,并且都只畫了第11個像素

總結-----

   其實就一句話,“所謂的線寬指的是給定路徑的中心到兩邊的粗細,換句話是在路徑的兩邊各繪制一半”。這個原理明白了,啥都沒問題了。


向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI