高级渐变?

发布于 2024-10-21 15:55:26 字数 31 浏览 5 评论 0原文

UIView 的每个角都有颜色,是否可能有渐变?

Is it possibly to have a gradient where there's a colour in each corner of a UIView?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

千纸鹤带着心事 2024-10-28 15:55:26

没有内置的方法可以做到这一点,也没有简单的方法可以通过 Quartz 来做到这一点。不过,您可以通过 Quartz 来实现这一点,方法是创建 4 个不同方向的不同 2-D 渐变,并用垂直运行的黑白渐变遮盖每个渐变。

假设您的颜色定义为:tlColor、trColor、blColor、brColor(用于左上角、右上角等)。

  1. 从 tlColor(顶部)到 blColor(底部)的垂直渐变。
  2. 从白色(左)到黑色(右)的水平渐变,转换为图像,用作来自 #1 的图像的图像蒙版。
  3. 从 trColor(顶部)到 brColor(底部)的垂直渐变。
  4. 从黑色(左)到白色(右)的水平渐变,转换为图像,用作来自 #3 的图像的图像蒙版。
  5. 从 blColor(左)到 trColor(右)的水平渐变。
  6. 从白色(顶部)到黑色(底部)的垂直渐变,转换为图像,用作来自 #5 的图像的图像蒙版。
  7. 从 tlColor(左)到 brColor(右)的水平渐变。
  8. 从黑色(顶部)到白色(底部)的垂直渐变,转换为图像,用作来自 #7 的图像的图像蒙版。
  9. 然后将 4 个结果分别绘制到视图中。

您可能想先在 Acorn 或 Photoshop 中尝试一下...因此,在将其转换为代码之前,您应该清楚所涉及的内容。然后 Quartz 参考 @lxt 指出有关于渐变的部分(CGGradientRef 就足够了,不要尝试使用阴影),以及关于图像蒙版的单独部分。

There's no built-in way to do this, and no simple way to do this via Quartz either. However, you can do it via Quartz by creating 4 different 2-D gradients going in different directions, and masking each one with a black-white gradient running perpendicular.

Assuming your colors are defined as: tlColor, trColor, blColor, brColor (for top-left, top-right, etc.).

  1. Vertical gradient from tlColor (top) to blColor (bottom).
  2. Horizontal gradient from white (left) to black (right), convert to image, use as image mask with image from #1.
  3. Vertical gradient from trColor (top) to brColor (bottom).
  4. Horizontal gradient from black (left) to white (right), convert to image, use as image mask with image from #3.
  5. Horizontal gradient from blColor (left) to trColor (right).
  6. Vertical gradient from white (top) to black (bottom), convert to image, use as image mask with image from #5.
  7. Horizontal gradient from tlColor (left) to brColor (right).
  8. Vertical gradient from black (top) to white (bottom), convert to image, use as image mask with image from #7.
  9. Then just draw each of the 4 results to the view.

You might want to try this in Acorn or Photoshop first... so it's clear what's involved before you translate it into code. Then the Quartz reference @lxt pointed you to has sections on gradients (CGGradientRef is sufficient, don't try to use shadings), and a separate section on image masks.

明天过后 2024-10-28 15:55:26

我有 2 个渐变对角线放置。使用覆盖混合

- (void)drawRect:(CGRect)rect 
{
    CGContextRef currentContext = UIGraphicsGetCurrentContext();

    size_t num_locations = 2;
    CGFloat locations[2] = { 0.0, 1.0 };
    CGFloat locations2[2] = { 1.0, 0.0 };
    CGFloat components[8] = { 
        1.0, 1.0, 0.0, 1.0 ,//Yellow
        0.0, 0.0, 1.0, 1.0};//Blue

    CGColorSpaceRef rgbColorspace = CGColorSpaceCreateDeviceRGB();
    CGGradientRef gradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);

    CGPoint point1 = CGPointMake(0, 0);
    CGPoint point2 = CGPointMake(self.bounds.size.width, self.bounds.size.height);
    CGContextDrawLinearGradient(currentContext, gradient, point1, point2, 0);

    CGFloat components1[8]  = { 
        0.0, 1.0, 0.0, 1.0,//Red 
        1.0, 0.0, 0.0, 1.0}; //Green

    gradient = CGGradientCreateWithColorComponents(rgbColorspace, components1, locations2, num_locations);

    CGContextSetBlendMode(currentContext, kCGBlendModeOverlay);

    point1 = CGPointMake(self.bounds.size.width, 0);
    point2 = CGPointMake(0, self.bounds.size.height);

    CGContextDrawLinearGradient(currentContext, gradient, point1, point2, 0);


    CGGradientRelease(gradient);
    CGColorSpaceRelease(rgbColorspace); 
}

要更改颜色,您应该有 4 个 UIColors 作为视图上的成员,并相应地更改此片段。

I have 2 gradients placed diagonal. With overlay-blending

- (void)drawRect:(CGRect)rect 
{
    CGContextRef currentContext = UIGraphicsGetCurrentContext();

    size_t num_locations = 2;
    CGFloat locations[2] = { 0.0, 1.0 };
    CGFloat locations2[2] = { 1.0, 0.0 };
    CGFloat components[8] = { 
        1.0, 1.0, 0.0, 1.0 ,//Yellow
        0.0, 0.0, 1.0, 1.0};//Blue

    CGColorSpaceRef rgbColorspace = CGColorSpaceCreateDeviceRGB();
    CGGradientRef gradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);

    CGPoint point1 = CGPointMake(0, 0);
    CGPoint point2 = CGPointMake(self.bounds.size.width, self.bounds.size.height);
    CGContextDrawLinearGradient(currentContext, gradient, point1, point2, 0);

    CGFloat components1[8]  = { 
        0.0, 1.0, 0.0, 1.0,//Red 
        1.0, 0.0, 0.0, 1.0}; //Green

    gradient = CGGradientCreateWithColorComponents(rgbColorspace, components1, locations2, num_locations);

    CGContextSetBlendMode(currentContext, kCGBlendModeOverlay);

    point1 = CGPointMake(self.bounds.size.width, 0);
    point2 = CGPointMake(0, self.bounds.size.height);

    CGContextDrawLinearGradient(currentContext, gradient, point1, point2, 0);


    CGGradientRelease(gradient);
    CGColorSpaceRelease(rgbColorspace); 
}

To change the color you should have 4 UIColors as members on the view and change this fragment accordingly.

一个人的旅程 2024-10-28 15:55:26

这是一个可行的解决方案。

绘制两种颜色渐变时,一个垂直渐变位图蒙版既可以按原样使用,也可以镜像使用。

FourTimesRGBA分量是四个角颜色UL、UR、LL、LR的R、G、B、A分量,即ULR、ULG、ULB、ULA、URR等。

void DrawFourGradientRect(CGContextRef Cgc,
                          const CGRect * Rect,
                          const CGFloat FourTimesRGBAcomponents[16])
{
   int            w;
   int            h;
   void          *MaskData;
   CGColorSpaceRef GrayCS;
   CGColorSpaceRef CS;
   CGContextRef   BC;           //Bitmap context
   CGFloat        GrayComp[4] = {1.0, 1.0, 0.0, 1.0}; //2 * Gray+Alpha
   CGGradientRef  Gradient;
   CGImageRef     Mask;

   w = Rect->size.width;
   h = Rect->size.height;

   //Start filling with white
   CGContextSetRGBFillColor(Cgc, 1, 1, 1, 1);
   CGContextFillRect(Cgc, *Rect);

   //Then create vertical gradient mask bitmap, white on top, black at bottom
   MaskData = malloc(w * h);
   if (!MaskData)
      return;
   GrayCS = CGColorSpaceCreateDeviceGray();
   if (!GrayCS)
   {
      free(MaskData);
      return;
   }
   BC = CGBitmapContextCreate(MaskData, w, h, 8, w, GrayCS, kCGImageAlphaNone);
   if (!BC)
   {
      CGColorSpaceRelease(GrayCS);
      free(MaskData);
      return;
   }
   Gradient = CGGradientCreateWithColorComponents(GrayCS, GrayComp, NULL, 2);
   if (!Gradient)
   {
      CGContextRelease(BC);
      CGColorSpaceRelease(GrayCS);
      free(MaskData);
      return;
   }
   CGColorSpaceRelease(GrayCS);
   CGContextDrawLinearGradient(BC, Gradient, CGPointZero, CGPointMake(0, h), 0);
   CGGradientRelease(Gradient);
   Mask = CGBitmapContextCreateImage(BC);
   CGContextRelease(BC);
   free(MaskData);
   if (!Mask)
      return;

   //Now draw first horizontal color gradient from UL to UR
   CS = CGColorSpaceCreateDeviceRGB();
   if (!CS)
   {
      CGImageRelease(Mask);
      return;
   }

   CGContextSaveGState(Cgc);
   CGContextTranslateCTM(Cgc, Rect->origin.x, Rect->origin.y);
   CGContextClipToMask(Cgc, CGRectMake(0, 0, w, h), Mask);

   Gradient = CGGradientCreateWithColorComponents(CS,
                                        FourTimesRGBAcomponents, NULL, 2);
   if (Gradient)
   {
      CGContextDrawLinearGradient(Cgc, Gradient, CGPointZero, CGPointMake(w, 0), 0);
      CGGradientRelease(Gradient);
   }

   CGContextRestoreGState(Cgc);

   //Finally draw second horizontal color gradient from LL to LR
   CGContextSaveGState(Cgc);
   CGContextTranslateCTM(Cgc, Rect->origin.x, Rect->origin.y + Rect->size.height);
   CGContextScaleCTM(Cgc, 1, -1);   //Use vertical gradient mask upside-down
   CGContextClipToMask(Cgc, CGRectMake(0, 0, w, h), Mask);

   Gradient = CGGradientCreateWithColorComponents(CS,
                                    FourTimesRGBAcomponents + 8, NULL, 2);
   if (Gradient)
   {
      CGContextDrawLinearGradient(Cgc, Gradient, CGPointZero, CGPointMake(w, 0), 0);
      CGGradientRelease(Gradient);
   }

   CGContextRestoreGState(Cgc);

   CGImageRelease(Mask);
   CGColorSpaceRelease(CS);
}                               /* DrawFourGradientRect                      */

Here is a working solution.

One vertical gradient bitmap mask used both as is and mirrored when drawing two color gradients.

FourTimesRGBAcomponents is the R,G,B,A components of the four corner colors UL, UR, LL and LR, i.e. ULR, ULG, ULB, ULA, URR etc.

void DrawFourGradientRect(CGContextRef Cgc,
                          const CGRect * Rect,
                          const CGFloat FourTimesRGBAcomponents[16])
{
   int            w;
   int            h;
   void          *MaskData;
   CGColorSpaceRef GrayCS;
   CGColorSpaceRef CS;
   CGContextRef   BC;           //Bitmap context
   CGFloat        GrayComp[4] = {1.0, 1.0, 0.0, 1.0}; //2 * Gray+Alpha
   CGGradientRef  Gradient;
   CGImageRef     Mask;

   w = Rect->size.width;
   h = Rect->size.height;

   //Start filling with white
   CGContextSetRGBFillColor(Cgc, 1, 1, 1, 1);
   CGContextFillRect(Cgc, *Rect);

   //Then create vertical gradient mask bitmap, white on top, black at bottom
   MaskData = malloc(w * h);
   if (!MaskData)
      return;
   GrayCS = CGColorSpaceCreateDeviceGray();
   if (!GrayCS)
   {
      free(MaskData);
      return;
   }
   BC = CGBitmapContextCreate(MaskData, w, h, 8, w, GrayCS, kCGImageAlphaNone);
   if (!BC)
   {
      CGColorSpaceRelease(GrayCS);
      free(MaskData);
      return;
   }
   Gradient = CGGradientCreateWithColorComponents(GrayCS, GrayComp, NULL, 2);
   if (!Gradient)
   {
      CGContextRelease(BC);
      CGColorSpaceRelease(GrayCS);
      free(MaskData);
      return;
   }
   CGColorSpaceRelease(GrayCS);
   CGContextDrawLinearGradient(BC, Gradient, CGPointZero, CGPointMake(0, h), 0);
   CGGradientRelease(Gradient);
   Mask = CGBitmapContextCreateImage(BC);
   CGContextRelease(BC);
   free(MaskData);
   if (!Mask)
      return;

   //Now draw first horizontal color gradient from UL to UR
   CS = CGColorSpaceCreateDeviceRGB();
   if (!CS)
   {
      CGImageRelease(Mask);
      return;
   }

   CGContextSaveGState(Cgc);
   CGContextTranslateCTM(Cgc, Rect->origin.x, Rect->origin.y);
   CGContextClipToMask(Cgc, CGRectMake(0, 0, w, h), Mask);

   Gradient = CGGradientCreateWithColorComponents(CS,
                                        FourTimesRGBAcomponents, NULL, 2);
   if (Gradient)
   {
      CGContextDrawLinearGradient(Cgc, Gradient, CGPointZero, CGPointMake(w, 0), 0);
      CGGradientRelease(Gradient);
   }

   CGContextRestoreGState(Cgc);

   //Finally draw second horizontal color gradient from LL to LR
   CGContextSaveGState(Cgc);
   CGContextTranslateCTM(Cgc, Rect->origin.x, Rect->origin.y + Rect->size.height);
   CGContextScaleCTM(Cgc, 1, -1);   //Use vertical gradient mask upside-down
   CGContextClipToMask(Cgc, CGRectMake(0, 0, w, h), Mask);

   Gradient = CGGradientCreateWithColorComponents(CS,
                                    FourTimesRGBAcomponents + 8, NULL, 2);
   if (Gradient)
   {
      CGContextDrawLinearGradient(Cgc, Gradient, CGPointZero, CGPointMake(w, 0), 0);
      CGGradientRelease(Gradient);
   }

   CGContextRestoreGState(Cgc);

   CGImageRelease(Mask);
   CGColorSpaceRelease(CS);
}                               /* DrawFourGradientRect                      */
我ぃ本無心為│何有愛 2024-10-28 15:55:26

为了比卡尔更有帮助,答案是“是”,但如何实现它取决于您想要使用的技术。 Quartz 渐变系统的描述如下:

http: //developer.apple.com/library/mac/#documentation/graphicsimaging/Conceptual/drawingwithquartz2d/dq_shadings/dq_shadings.html

...但是OpenGL是另一种可能性。这取决于您的应用程序。

To be a little more helpful than Carl, the answer is 'yes', but how you implement it would depend on the tech you wanted to use. The Quartz gradient system is described here:

http://developer.apple.com/library/mac/#documentation/graphicsimaging/Conceptual/drawingwithquartz2d/dq_shadings/dq_shadings.html

...but OpenGL is another possibility. It would depend on your application.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文