我正在尝试在核心图形中生成chrome文本效果,但我在查看它时遇到了一些麻烦。
这是我想要达到的效果:
这是我设法得到的:
正如您所看到的,渐变边缘非常锯齿状。有没有办法实现这种效果而不需要使用静态png进行纹理填充?
这是我的代码:
- (void)setGradientFill:(UILabel*)label
{
CGSize textSize = [label.text sizeWithFont:label.font];
CGFloat width = textSize.width; // max 1024 due to Core Graphics limitations
CGFloat height = textSize.height; // max 1024 due to Core Graphics limitations
// create a new bitmap image context
UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), YES, 0.0);
// get context
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetAllowsAntialiasing(context, true);
CGContextSetShouldAntialias(context, true);
// push context to make it current (need to do this manually because we are not drawing in a UIView)
UIGraphicsPushContext(context);
CGContextSetAllowsAntialiasing(context, YES);
CGContextSetShouldAntialias(context, YES);
//draw gradient
CGGradientRef glossGradient;
CGColorSpaceRef rgbColorspace;
size_t num_locations = 5;
CGFloat locations[5] = { 0.0, 0.5, 0.5, 0.65, 1};
CGFloat components[20] = {
1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0,
0.878, 0.878, 0.878, 0.878,
0.78, 0.78, 0.78, 1.0,
1, 1, 1, 1.0
};
rgbColorspace = CGColorSpaceCreateDeviceRGB();
glossGradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);
CGPoint start = CGPointMake(0, 0);
CGPoint end = CGPointMake(width/4, height*1.2);
CGContextDrawLinearGradient(context, glossGradient, start, end, kCGGradientDrawsAfterEndLocation);
CGGradientRelease(glossGradient);
CGColorSpaceRelease(rgbColorspace);
// pop context
UIGraphicsPopContext();
// get a UIImage from the image context
UIImage *gradientImage = UIGraphicsGetImageFromCurrentImageContext();
// clean up drawing environment
UIGraphicsEndImageContext();
label.textColor = [UIColor colorWithPatternImage:gradientImage];
}
修改lefteris的建议:
我尝试了你做的扩展(左下图)。由于某种原因,我得到一些非常模糊的文字,边缘有人工制品。
我正在调整UIImage帧的大小以避免内容拉伸:
_test.frame = CGRectMake(_test.frame.origin.x, _test.frame.origin.y, image.size.width, image.size.height);
_test.image = image;
编辑最近的解决方案:
lefteris的解决方案是最接近的,你不能真正避免锯齿状的渐变边缘。如果你可以,你应该使用photoshop中生成的静态pngs来获取纹理(不是文本只是填充),但你可能需要几个版本(就像我一样),以便在每个屏幕上获得正确的效果,因为纹理是根据大小应用的框架不是包含的文本。动态地做它是可能的,但看起来有限。
答案 0 :(得分:1)
使用the UIGraphicsBeginImageContextWithOptions
function并将比例因子设置为0.0
。
UIGraphicsBeginImageContext
函数调用该函数,其比例因子设置为1.0
,无条件地,即使在Retina(@ 2x)设备上也是如此。在Retina设备上,您需要2.0。 0.0
会自动检测要使用的正确比例因子并使用它。
答案 1 :(得分:0)
你也应该平滑你的渐变。
请改用:
CGFloat locations[5] = { 0.0, 0.45, 0.55, 0.65, 1};
我编辑我的答案以提供不同的解决方案/建议:
我创建了一个3D文本渲染UIImage扩展,用于渲染3D文本,which can be found here
使用该类别扩展,经过一些修改,我最终得到了这张图片:
我相信你不应该将渐变作为背景颜色创建并将其作为一个整体应用于标签上,因为它也会在背景上添加渐变,这使得它看起来不那么逼真。
我使用以下设置创建了上面的图片:
UIImage *my3dImage = [UIImage create3DImageWithText:@"61" Font:[UIFont fontWithName:@"Helvetica-Bold" size:180] ForegroundColor:[UIColor colorWithRed:(255/255.f) green:(255/255.f) blue:(255/255.f) alpha:1.0] ShadowColor:[UIColor blackColor] outlineColor:[UIColor lightGrayColor] depth:4 useShine:YES];
我修改了我的源代码以应用不同的光泽效果:
size_t num_locations = 5;
CGFloat locations[5] = { 0.0, 0.49, 0.51, 0.65, 1};
CGFloat gradientComponents[20] = {
1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0,
0.878, 0.878, 0.878, 0.878,
0.78, 0.78, 0.78, 1.0,
1, 1, 1, 1.0
};
CGGradientRef glossGradient = CGGradientCreateWithColorComponents(genericRGBColorspace, gradientComponents, locations, num_locations);
CGPoint start = CGPointMake(0, expectedSize.height/4);
CGPoint end = CGPointMake(expectedSize.width/4, expectedSize.height);
原因,我相信我的方法更好,是因为它实际上是从文本创建一个蒙版然后应用渐变,这意味着只有文本得到的是渐变而不是背景。