objective-c – 如何在Cocoa中绘制锥形椭圆形阴影

前端之家收集整理的这篇文章主要介绍了objective-c – 如何在Cocoa中绘制锥形椭圆形阴影前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
背景:

下面的镜头是OS X Lion中的Mail.app.当源列表过长时,源列表底部的按钮上方出现一个很好的阴影线.当您滚动时,源列表将在该阴影线下移动.当您展开窗口时,源列表中的所有内容都适合不滚动,阴影线消失.

问题:

如何使用@L_404_0@绘制阴影线?我知道NSShadow等等,但在我看来,这里还有更多的只是一个阴影.有一条线微妙地消失到点上(就像您在Photoshop中的每一端应用了一个渐变蒙版).同样的,阴影是椭圆形的,随着接近线条的渐变.那么它不只是一个常规的NSShadow,是吗? (这绝对不是一个图像,因为当扩展源视图的宽度时它会很好地扩展.)

任何关于如何绘制这种形状的技巧将不胜感激.

而对于那些粘贴者来说,不,这并不违反NDA,因为Mail.app已被苹果公开显示.

解决方法

大概的概念:

.

>创建一个尺寸为150px×10px的图层“Layer A”
并用渐变填充:

>较低的颜色:#535e71不透明度:33%
>上部颜色:#535e71不透明度:0%

>创建一个尺寸为150px×1px的图层“Layer B”
并填写固体#535e71不透明度:50%
>将“层A”和“层B”组合成“层C”.
>将反射的渐变掩码从#ffffff应用到#000000到“Layer C”.

视觉步骤:

功能代码

MyView.h:

  1. #import <Cocoa/Cocoa.h>
  2.  
  3. @interface MyView : NSView {
  4. @private
  5.  
  6. }
  7.  
  8. @end

MyView.m:

  1. #import "MyView.h"
  2.  
  3. @implementation MyView
  4.  
  5. - (CGImageRef)maskForRect:(NSRect)dirtyRect {
  6. NSSize size = [self bounds].size;
  7. CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  8. CGContextRef context = CGBitmapContextCreate(NULL,size.width,size.height,8,colorSpace,kCGImageAlphaPremultipliedLast);
  9.  
  10. CGContextClipToRect(context,*(CGRect*)&dirtyRect);
  11.  
  12. CGRect rect = CGRectMake(0.0,0.0,size.height);
  13.  
  14. size_t num_locations = 3;
  15. CGFloat locations[3] = { 0.0,0.5,1.0 };
  16. CGFloat components[12] = {
  17. 1.0,1.0,// Start color
  18. 0.0,// Middle color
  19. 1.0,// End color
  20. };
  21.  
  22. CGGradientRef myGradient = CGGradientCreateWithColorComponents(colorSpace,components,locations,num_locations);
  23.  
  24. CGPoint myStartPoint = CGPointMake(CGRectGetMinX(rect),CGRectGetMinY(rect));
  25. CGPoint myEndPoint = CGPointMake(CGRectGetMaxX(rect),CGRectGetMinY(rect));
  26.  
  27. CGContextDrawLinearGradient(context,myGradient,myStartPoint,myEndPoint,0);
  28.  
  29. CGImageRef theImage = CGBitmapContextCreateImage(context);
  30. CGImageRef theMask = CGImageMaskCreate(CGImageGetWidth(theImage),CGImageGetHeight(theImage),CGImageGetBitsPerComponent(theImage),CGImageGetBitsPerPixel(theImage),CGImageGetBytesPerRow(theImage),CGImageGetDataProvider(theImage),NULL,YES);
  31.  
  32. [(id)theMask autorelease];
  33.  
  34. CGColorSpaceRelease(colorSpace);
  35. CGContextRelease(context);
  36.  
  37. return theMask;
  38. }
  39.  
  40. - (void)drawRect:(NSRect)dirtyRect {
  41. NSRect nsRect = [self bounds];
  42. CGRect rect = *(CGRect*)&nsRect;
  43. CGRect lineRect = CGRectMake(rect.origin.x,rect.origin.y,rect.size.width,(CGFloat)1.0);
  44.  
  45. CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  46.  
  47. CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
  48. CGContextClipToRect(context,*(CGRect*)&dirtyRect);
  49. CGContextClipToMask(context,rect,[self maskForRect:dirtyRect]);
  50.  
  51. size_t num_locations = 2;
  52. CGFloat locations[2] = { 0.0,1.0 };
  53. CGFloat components[8] = {
  54. 0.315,0.371,0.450,0.3,// Bottom color
  55. 0.315,0.0 // Top color
  56. };
  57.  
  58. CGGradientRef myGradient = CGGradientCreateWithColorComponents(colorSpace,CGRectGetMinY(rect));
  59. CGPoint myEndPoint = CGPointMake(CGRectGetMinX(rect),CGRectGetMaxY(rect));
  60.  
  61. CGContextDrawLinearGradient(context,0);
  62.  
  63. CGContextSetRGBFillColor(context,0.315,0.5 );
  64. CGContextFillRect(context,lineRect);
  65.  
  66. CGColorSpaceRelease(colorSpace);
  67. }
  68.  
  69. @end

(我的第一次使用纯粹的低级CoreGraphics,因此可能是次级最优,开放改进.)

这是上面代码产生的实际截图:

绘图延伸到视图的尺寸.

(我以前有两种技术在这里显示:“技术A”和“技术B”.“技术B”提供了优异的效果,并且实现起来也更简单,所以我放弃了“技术A”.有些评论可能还是指“技术A”.只要忽略它们并享受功能完整的代码段.)

猜你在找的C&C++相关文章