给 UIView 添加斜角效果
Add bevel effect to UIView
我希望我的按钮看起来像这样。
问过设计师,他说用了斜角效果,倒角这个词我还是第一次听说。
我搜索了 Stack Overflow,但找不到任何有用的信息。
我相信设计师的意思是斜面和浮雕效果。这是 UIImage 上的示例扩展,用于使用着色器图像应用浮雕效果。
extension UIImage {
func applyBevelAndEmboss(shadingImage: UIImage) -> UIImage {
// Create filters
guard let heightMapFilter = CIFilter(name: "CIHeightFieldFromMask") else { return self }
guard let shadedMaterialFilter = CIFilter(name: "CIShadedMaterial") else { return self }
// Filters chain
heightMapFilter.setValue(CIImage(image: self),
forKey: kCIInputImageKey)
guard let heightMapFilterOutput = heightMapFilter.outputImage else { return self }
shadedMaterialFilter.setValue(heightMapFilterOutput,
forKey: kCIInputImageKey)
shadedMaterialFilter.setValue(CIImage(image: shadingImage),
forKey: "inputShadingImage")
// Catch output
guard let filteredImage = shadedMaterialFilter.outputImage else { return self }
return UIImage(ciImage: filteredImage)
}
}
请向设计师索取着色器图像并将其应用于平面图像。
我个人的看法是,最好从设计师那里获取处理后的图像并使用它,而不是在应用程序中执行所有这些处理。
我的建议是尽可能以矢量形式导出此按钮(无文本)。而你它只是作为图像。有时在这种情况下最好节省时间并使用图像。我更喜欢只画简单的形状。或者您可以通过将斜角效果替换为渐变/边框/阴影的组合来实现。
斜面是 "sloping surface along the edge of a piece of wood, glass etc"。在计算世界中,我们通常在按钮周围使用 "bevel",以产生 3D 的错觉。尽管自 iOS7 以来有一个明确的趋势,那就是更喜欢扁平化的外观。
当您说要对 UI 视图应用斜角时,您指的是边缘周围的渐变。我在下图中用红色突出显示了这一点。
当您说您希望按钮看起来像您的图片时,斜角可能只是该目标的一部分。
正如已经建议的那样,使您的按钮看起来像那样的最快和最简单的方法是使用按钮的图像,并将其应用到您的视图中。这也可能是更有效的方法。或者,可以使用代码创建按钮。尽管您需要矢量格式的按钮。
为了在代码中生成按钮,您需要向设计师询问矢量格式的按钮。 SVG 格式可能是最简单的。有许多第三方程序可以将矢量图像转换为 Core Graphics 代码。对于这个例子,我使用了一个名为 Graphic(由 Autodesk 开发)的程序。虽然,我不得不修复它生成的代码中的几个错误。更新的替代方案可能更好。我没有尝试使用 Graphic 在 Swift 中生成代码。
这是我的按钮示例,与您的设计类似。此代码是概念验证,因此按钮的大小或位置不是很好。我没有花太长时间将我的按钮与您的确切设计相匹配。但是,它会生成一个包含类似按钮的视图。
#import "Button.h"
#import <CoreText/CoreText.h>
@implementation Button
- (void)drawRect:(CGRect)rect {
// Do any additional setup after loading the view, typically from a nib.
CGContextRef ctx = UIGraphicsGetCurrentContext();
// enable the following lines for flipped coordinate systems
//CGContextTranslateCTM(ctx, 0, self.bounds.size.height);
//CGContextScaleCTM(ctx, 1, -1);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
/* Shape */
CGMutablePathRef pathRef = CGPathCreateMutable();
CGPathMoveToPoint(pathRef, NULL, 251.424, 272.035);
CGPathAddCurveToPoint(pathRef, NULL, 251.424, 288.189, 238.328, 301.285, 222.174, 301.285);
CGPathAddCurveToPoint(pathRef, NULL, 206.02, 301.285, 192.924, 288.189, 192.924, 272.035);
CGPathAddCurveToPoint(pathRef, NULL, 192.924, 255.881, 206.02, 242.785, 222.174, 242.785);
CGPathAddCurveToPoint(pathRef, NULL, 238.328, 242.785, 251.424, 255.881, 251.424, 272.035);
CGPathCloseSubpath(pathRef);
/* Gradient Fill */
CGContextSaveGState(ctx);
CGContextAddPath(ctx, pathRef);
CGContextClip(ctx);
CGFloat gradientColors[] = {
0.549, 0.557, 0.565, 1,
0, 0, 0, 1 };
CGFloat gradientLocations[] = { 0, 0.973 };
CGGradientRef gradientRef = CGGradientCreateWithColorComponents(colorSpace, gradientColors, gradientLocations, 2);
CGContextDrawLinearGradient(ctx, gradientRef, CGPointMake(201.492, 251.353), CGPointMake(242.857, 292.719), (kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation));
CGGradientRelease(gradientRef);
CGContextRestoreGState(ctx);
CGPathRelease(pathRef);
/* Shape 2 */
CGMutablePathRef pathRef2 = CGPathCreateMutable();
CGPathMoveToPoint(pathRef2, NULL, 247.069, 272.035);
CGPathAddCurveToPoint(pathRef2, NULL, 247.069, 285.784, 235.923, 296.93, 222.174, 296.93);
CGPathAddCurveToPoint(pathRef2, NULL, 208.425, 296.93, 197.279, 285.784, 197.279, 272.035);
CGPathAddCurveToPoint(pathRef2, NULL, 197.279, 258.286, 208.425, 247.14, 222.174, 247.14);
CGPathAddCurveToPoint(pathRef2, NULL, 235.923, 247.14, 247.069, 258.286, 247.069, 272.035);
CGPathCloseSubpath(pathRef2);
/* Gradient Fill */
CGContextSaveGState(ctx);
CGContextAddPath(ctx, pathRef2);
CGContextClip(ctx);
CGFloat gradientColors2[] = {
0.165, 0.153, 0.153, 1,
0, 0, 0, 0.651 };
CGFloat gradientLocations2[] = { 0.897, 0.991 };
CGGradientRef gradientRef2 = CGGradientCreateWithColorComponents(colorSpace, gradientColors2, gradientLocations2, 2);
CGContextDrawRadialGradient(ctx, gradientRef2, CGPointMake(222.174, 272.035), 0, CGPointMake(222.174, 272.035), 24.895, (kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation));
CGGradientRelease(gradientRef2);
CGContextRestoreGState(ctx);
CGPathRelease(pathRef2);
/* Text */
UIColor *colour = [UIColor colorWithRed:1 green:1 blue:1 alpha:1];
NSMutableAttributedString *attributedStr = [[NSMutableAttributedString alloc] initWithString:@"STOP"];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.alignment = NSTextAlignmentLeft;
NSDictionary *textAttribs = @{
NSFontAttributeName: [UIFont fontWithName:@"Helvetica" size:10],
NSForegroundColorAttributeName: colour,
NSParagraphStyleAttributeName: paragraphStyle
};
[attributedStr setAttributes:textAttribs range:NSMakeRange(0, 4)];
CGRect textBox = CGRectMake(208.736, 270.375, 28.051, 14);
CGPathRef textBoxPath = CGPathCreateWithRect(CGRectMake(0, 0, textBox.size.width, textBox.size.height), NULL);
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attributedStr);
CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), textBoxPath, NULL);
CGContextSaveGState(ctx);
CGContextTranslateCTM(ctx, textBox.origin.x, textBox.origin.y);
CGContextSetTextMatrix(ctx, CGAffineTransformIdentity);
CGContextTranslateCTM(ctx, 0.0, textBox.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);
CTFrameDraw(frameRef, ctx);
CGContextRestoreGState(ctx);
CGPathRelease(textBoxPath);
CFRelease(framesetter);
CFRelease(frameRef);
/* Shape 3 */
CGMutablePathRef pathRef3 = CGPathCreateMutable();
CGPathMoveToPoint(pathRef3, NULL, 229.861, 260.812);
CGPathAddCurveToPoint(pathRef3, NULL, 229.861, 262.987, 228.098, 264.75, 225.923, 264.75);
CGPathAddLineToPoint(pathRef3, NULL, 218.423, 264.75);
CGPathAddCurveToPoint(pathRef3, NULL, 216.248, 264.75, 214.485, 262.987, 214.485, 260.812);
CGPathAddLineToPoint(pathRef3, NULL, 214.485, 260.812);
CGPathAddCurveToPoint(pathRef3, NULL, 214.485, 258.637, 216.248, 256.874, 218.423, 256.874);
CGPathAddLineToPoint(pathRef3, NULL, 225.923, 256.874);
CGPathAddCurveToPoint(pathRef3, NULL, 228.099, 256.875, 229.861, 258.638, 229.861, 260.812);
CGPathAddLineToPoint(pathRef3, NULL, 229.861, 260.812);
CGPathCloseSubpath(pathRef3);
CGContextSetRGBFillColor(ctx, 0.514, 0.773, 0.357, 1);
CGContextAddPath(ctx, pathRef3);
CGContextFillPath(ctx);
CGPathRelease(pathRef3);
CGColorSpaceRelease(colorSpace);
}
@end
我希望我的按钮看起来像这样。
问过设计师,他说用了斜角效果,倒角这个词我还是第一次听说。
我搜索了 Stack Overflow,但找不到任何有用的信息。
我相信设计师的意思是斜面和浮雕效果。这是 UIImage 上的示例扩展,用于使用着色器图像应用浮雕效果。
extension UIImage {
func applyBevelAndEmboss(shadingImage: UIImage) -> UIImage {
// Create filters
guard let heightMapFilter = CIFilter(name: "CIHeightFieldFromMask") else { return self }
guard let shadedMaterialFilter = CIFilter(name: "CIShadedMaterial") else { return self }
// Filters chain
heightMapFilter.setValue(CIImage(image: self),
forKey: kCIInputImageKey)
guard let heightMapFilterOutput = heightMapFilter.outputImage else { return self }
shadedMaterialFilter.setValue(heightMapFilterOutput,
forKey: kCIInputImageKey)
shadedMaterialFilter.setValue(CIImage(image: shadingImage),
forKey: "inputShadingImage")
// Catch output
guard let filteredImage = shadedMaterialFilter.outputImage else { return self }
return UIImage(ciImage: filteredImage)
}
}
请向设计师索取着色器图像并将其应用于平面图像。
我个人的看法是,最好从设计师那里获取处理后的图像并使用它,而不是在应用程序中执行所有这些处理。
我的建议是尽可能以矢量形式导出此按钮(无文本)。而你它只是作为图像。有时在这种情况下最好节省时间并使用图像。我更喜欢只画简单的形状。或者您可以通过将斜角效果替换为渐变/边框/阴影的组合来实现。
斜面是 "sloping surface along the edge of a piece of wood, glass etc"。在计算世界中,我们通常在按钮周围使用 "bevel",以产生 3D 的错觉。尽管自 iOS7 以来有一个明确的趋势,那就是更喜欢扁平化的外观。
当您说要对 UI 视图应用斜角时,您指的是边缘周围的渐变。我在下图中用红色突出显示了这一点。
当您说您希望按钮看起来像您的图片时,斜角可能只是该目标的一部分。
正如已经建议的那样,使您的按钮看起来像那样的最快和最简单的方法是使用按钮的图像,并将其应用到您的视图中。这也可能是更有效的方法。或者,可以使用代码创建按钮。尽管您需要矢量格式的按钮。
为了在代码中生成按钮,您需要向设计师询问矢量格式的按钮。 SVG 格式可能是最简单的。有许多第三方程序可以将矢量图像转换为 Core Graphics 代码。对于这个例子,我使用了一个名为 Graphic(由 Autodesk 开发)的程序。虽然,我不得不修复它生成的代码中的几个错误。更新的替代方案可能更好。我没有尝试使用 Graphic 在 Swift 中生成代码。
这是我的按钮示例,与您的设计类似。此代码是概念验证,因此按钮的大小或位置不是很好。我没有花太长时间将我的按钮与您的确切设计相匹配。但是,它会生成一个包含类似按钮的视图。
#import "Button.h"
#import <CoreText/CoreText.h>
@implementation Button
- (void)drawRect:(CGRect)rect {
// Do any additional setup after loading the view, typically from a nib.
CGContextRef ctx = UIGraphicsGetCurrentContext();
// enable the following lines for flipped coordinate systems
//CGContextTranslateCTM(ctx, 0, self.bounds.size.height);
//CGContextScaleCTM(ctx, 1, -1);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
/* Shape */
CGMutablePathRef pathRef = CGPathCreateMutable();
CGPathMoveToPoint(pathRef, NULL, 251.424, 272.035);
CGPathAddCurveToPoint(pathRef, NULL, 251.424, 288.189, 238.328, 301.285, 222.174, 301.285);
CGPathAddCurveToPoint(pathRef, NULL, 206.02, 301.285, 192.924, 288.189, 192.924, 272.035);
CGPathAddCurveToPoint(pathRef, NULL, 192.924, 255.881, 206.02, 242.785, 222.174, 242.785);
CGPathAddCurveToPoint(pathRef, NULL, 238.328, 242.785, 251.424, 255.881, 251.424, 272.035);
CGPathCloseSubpath(pathRef);
/* Gradient Fill */
CGContextSaveGState(ctx);
CGContextAddPath(ctx, pathRef);
CGContextClip(ctx);
CGFloat gradientColors[] = {
0.549, 0.557, 0.565, 1,
0, 0, 0, 1 };
CGFloat gradientLocations[] = { 0, 0.973 };
CGGradientRef gradientRef = CGGradientCreateWithColorComponents(colorSpace, gradientColors, gradientLocations, 2);
CGContextDrawLinearGradient(ctx, gradientRef, CGPointMake(201.492, 251.353), CGPointMake(242.857, 292.719), (kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation));
CGGradientRelease(gradientRef);
CGContextRestoreGState(ctx);
CGPathRelease(pathRef);
/* Shape 2 */
CGMutablePathRef pathRef2 = CGPathCreateMutable();
CGPathMoveToPoint(pathRef2, NULL, 247.069, 272.035);
CGPathAddCurveToPoint(pathRef2, NULL, 247.069, 285.784, 235.923, 296.93, 222.174, 296.93);
CGPathAddCurveToPoint(pathRef2, NULL, 208.425, 296.93, 197.279, 285.784, 197.279, 272.035);
CGPathAddCurveToPoint(pathRef2, NULL, 197.279, 258.286, 208.425, 247.14, 222.174, 247.14);
CGPathAddCurveToPoint(pathRef2, NULL, 235.923, 247.14, 247.069, 258.286, 247.069, 272.035);
CGPathCloseSubpath(pathRef2);
/* Gradient Fill */
CGContextSaveGState(ctx);
CGContextAddPath(ctx, pathRef2);
CGContextClip(ctx);
CGFloat gradientColors2[] = {
0.165, 0.153, 0.153, 1,
0, 0, 0, 0.651 };
CGFloat gradientLocations2[] = { 0.897, 0.991 };
CGGradientRef gradientRef2 = CGGradientCreateWithColorComponents(colorSpace, gradientColors2, gradientLocations2, 2);
CGContextDrawRadialGradient(ctx, gradientRef2, CGPointMake(222.174, 272.035), 0, CGPointMake(222.174, 272.035), 24.895, (kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation));
CGGradientRelease(gradientRef2);
CGContextRestoreGState(ctx);
CGPathRelease(pathRef2);
/* Text */
UIColor *colour = [UIColor colorWithRed:1 green:1 blue:1 alpha:1];
NSMutableAttributedString *attributedStr = [[NSMutableAttributedString alloc] initWithString:@"STOP"];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.alignment = NSTextAlignmentLeft;
NSDictionary *textAttribs = @{
NSFontAttributeName: [UIFont fontWithName:@"Helvetica" size:10],
NSForegroundColorAttributeName: colour,
NSParagraphStyleAttributeName: paragraphStyle
};
[attributedStr setAttributes:textAttribs range:NSMakeRange(0, 4)];
CGRect textBox = CGRectMake(208.736, 270.375, 28.051, 14);
CGPathRef textBoxPath = CGPathCreateWithRect(CGRectMake(0, 0, textBox.size.width, textBox.size.height), NULL);
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attributedStr);
CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), textBoxPath, NULL);
CGContextSaveGState(ctx);
CGContextTranslateCTM(ctx, textBox.origin.x, textBox.origin.y);
CGContextSetTextMatrix(ctx, CGAffineTransformIdentity);
CGContextTranslateCTM(ctx, 0.0, textBox.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);
CTFrameDraw(frameRef, ctx);
CGContextRestoreGState(ctx);
CGPathRelease(textBoxPath);
CFRelease(framesetter);
CFRelease(frameRef);
/* Shape 3 */
CGMutablePathRef pathRef3 = CGPathCreateMutable();
CGPathMoveToPoint(pathRef3, NULL, 229.861, 260.812);
CGPathAddCurveToPoint(pathRef3, NULL, 229.861, 262.987, 228.098, 264.75, 225.923, 264.75);
CGPathAddLineToPoint(pathRef3, NULL, 218.423, 264.75);
CGPathAddCurveToPoint(pathRef3, NULL, 216.248, 264.75, 214.485, 262.987, 214.485, 260.812);
CGPathAddLineToPoint(pathRef3, NULL, 214.485, 260.812);
CGPathAddCurveToPoint(pathRef3, NULL, 214.485, 258.637, 216.248, 256.874, 218.423, 256.874);
CGPathAddLineToPoint(pathRef3, NULL, 225.923, 256.874);
CGPathAddCurveToPoint(pathRef3, NULL, 228.099, 256.875, 229.861, 258.638, 229.861, 260.812);
CGPathAddLineToPoint(pathRef3, NULL, 229.861, 260.812);
CGPathCloseSubpath(pathRef3);
CGContextSetRGBFillColor(ctx, 0.514, 0.773, 0.357, 1);
CGContextAddPath(ctx, pathRef3);
CGContextFillPath(ctx);
CGPathRelease(pathRef3);
CGColorSpaceRelease(colorSpace);
}
@end