Skip to content

Instantly share code, notes, and snippets.

@Coder-ACJHP
Last active March 9, 2021 16:58
Show Gist options
  • Save Coder-ACJHP/6bca1d6e69f10333e57a16a461c5e8b0 to your computer and use it in GitHub Desktop.
Save Coder-ACJHP/6bca1d6e69f10333e57a16a461c5e8b0 to your computer and use it in GitHub Desktop.
With this function you can draw 3D text in Core graphics api in swift
// Original code in obj-c = https://stackoverflow.com/questions/13766268/3d-text-effect-in-ios
private func draw3D(text: NSString, usingfont font: UIFont, depthValue depth: CGFloat, foregroundColor: UIColor, shadowColor: UIColor, outlineColor: UIColor) -> UIImage? {
let attributes: [NSAttributedString.Key: Any] = [
.font : font,
.foregroundColor : foregroundColor
]
var textSize = view.bounds.size
textSize.width += depth + 5
textSize.height += depth + 5
UIGraphicsBeginImageContext(textSize)
guard let context = UIGraphicsGetCurrentContext() else { return nil }
var colorList = Array<UIColor>()
colorList.append(foregroundColor)
var colorComponents = foregroundColor.cgColor.components
let colorSteps = floor(100 / depth)
for _ in stride(from: 0, to: depth, by: 1) {
for kIndex in stride(from: 0, to: 2, by: 1) {
if colorComponents![kIndex] > colorSteps / 255.0 {
colorComponents?[kIndex] -= (colorSteps / 255.0)
}
}
let newColor = UIColor(red: colorComponents![0], green: colorComponents![1], blue: colorComponents![2], alpha: foregroundColor.cgColor.alpha)
colorList.insert(newColor, at: 0)
}
for iIndex in stride(from: 0, to: depth, by: 1) {
let newColor = colorList[Int(iIndex)]
context.saveGState()
context.setShouldAntialias(true)
//draw outline if this is the last layer (front one)
if iIndex + 1 == depth {
context.setLineWidth(1.0)
context.setLineJoin(.round)
context.setTextDrawingMode(.stroke)
outlineColor.setStroke()
text.draw(at: CGPoint(x: 1, y: 1), withAttributes: attributes)
}
// Fill drawing
newColor.set()
context.setTextDrawingMode(.fill)
if iIndex == 0 {
context.setShadow(offset: CGSize(width: -1, height: -1), blur: 4.0, color: shadowColor.cgColor)
} else if iIndex + 1 != depth {
//add glow like blur
context.setShadow(offset: CGSize(width: -1, height: -1), blur: 3.0, color: newColor.cgColor)
}
text.draw(at: CGPoint(x: iIndex, y: iIndex), withAttributes: attributes)
}
let colorSpace:CGColorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
let bitmapContext = CGContext(data: nil,
width: Int(textSize.width),
height: Int(textSize.height),
bitsPerComponent: 8,
bytesPerRow: Int(textSize.width) * 4,
space: colorSpace,
bitmapInfo: bitmapInfo.rawValue)
UIGraphicsPushContext(bitmapContext!)
bitmapContext?.setTextDrawingMode(.fill)
text.draw(at: CGPoint(x: depth - 1, y: depth - 1), withAttributes: attributes)
let alphaMask = bitmapContext?.makeImage()
UIGraphicsPopContext()
var drawRect: CGRect = .zero
drawRect.size = textSize
context.saveGState()
context.clip(to: drawRect, mask: alphaMask!)
context.setBlendMode(.luminosity)
let locations: [CGFloat] = [0.0, 0.4, 0.6, 1.0]
let gradientComponents: [CGFloat] = [
0.0, 0.0, 0.0, 1.0,
0.6, 0.6, 0.6, 1.0,
0.8, 0.8, 0.8, 1.0,
0.0, 0.0, 0.0, 1.0
]
let gradient = CGGradient(colorSpace: colorSpace,
colorComponents: gradientComponents,
locations: locations, count: locations.count)
let startPoint: CGPoint = .zero
let endPoint: CGPoint = CGPoint(x: 0, y: textSize.height)
context.drawLinearGradient(gradient!,
start: startPoint,
end: endPoint,
options: .drawsAfterEndLocation)
context.restoreGState()
guard let finalImage = UIGraphicsGetImageFromCurrentImageContext() else {
return nil
}
UIGraphicsEndImageContext()
return finalImage
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment