您的位置:首页 > 移动开发 > Swift

Intermediate Core Graphics(Swift)-Transforms、Shadows

2016-12-22 15:33 411 查看
本文内容来自Intermediate Core Graphics

Intermediate Core Graphics(Swift)-Transforms、Shadows

Transforms

所有的
view
context
都有一个
current transformation matrix
,或者叫做CTM
matrix
表示的当前的
position
scale
rotation


UIView
有一个
CGAffineTransform
类型的
transform
属性来表示matrix

context通过
CGContextGetCTM
来获取当前状态的CTM

例如,需要绘制如下的饼状图:



首先绘制红色的扇形图:



绘制绿色的扇形,把
context
旋转红色的扇形大小的角度,由于
context
的默认旋转点是在左上角,所以此时绿色的扇形是绘制在屏幕之外的地方



所以,正确的做法是,在旋转context之前,平移context,这样context的左上角就处于旋转的正确的位置:



然后再旋转



再把context平移到原来的位置



这时就可以绘制绿色的扇形



所以,整个的绘制的过程是:Translate->Rotate->Translate Back->Draw

本例的绘制chart过程如下:

override func drawRect(rect: CGRect) {

let context = UIGraphicsGetCurrentContext()
let totalSpent = categories.reduce(0, combine: {$0 + $1.spent})
guard totalSpent > 0 else { return }

let diameter = min(bounds.width, bounds.height)
let margin: CGFloat = 20
//绘制Circle,平移到中心点
let circle = UIBezierPath(ovalInRect: CGRect(x: 0, y: 0, width: diameter, height: diameter).insetBy(dx: margin, dy: margin))
let transform = CGAffineTransformMakeTranslation(bounds.width/2-diameter/2, 0)
circle.applyTransform(transform)

let workingCategories = categories.filter({$0.spent > 0})
for(index, _) in workingCategories.enumerate() {

//扇形的百分比和角度
let percent = CGFloat(workingCategories[index].spent / totalSpent)
let angle = percent * 2 * π;

print(workingCategories[index].name, workingCategories[index].spent, round(percent * 100))
//半径和中心点
let radius = diameter / 2 - margin
let centerPoint = center
//扇形路径
let slice = UIBezierPath()
slice.moveToPoint(centerPoint);
slice.addLineToPoint(CGPoint(x: centerPoint.x+radius, y: centerPoint.y))
slice.addArcWithCenter(centerPoint, radius: radius, startAngle: 0, endAngle: angle, clockwise: true)
slice.closePath()
//填充
chartColors[index].setFill()
slice.fill()
//CTM变换
CGContextTranslateCTM(context, centerPoint.x, centerPoint.y)
CGContextRotateCTM(context, angle)
CGContextTranslateCTM(context, -centerPoint.x, -centerPoint.y)

}

circle.stroke()

}


结果如下:



不光Core Graphic可以应用Transform,view和layer也可以应用Transform

Shadows

设置阴影的非
UIKit
的方法:

CGContextSetShadowWithColor(_:_:_:_:)


指定color,shadow的偏移量和blur radius

如下所示的例子:



Shadow with Stroke

下图是上图的circle添加了stroke之后的阴影效果,会发现其有两个阴影

fill的阴影

stroke的阴影



如果要实现如下的只有一个阴影该怎么做呢?



答案就是要使用
transparency layer




在stroke和fill之前,开始了一个
transparency layer
。它所做的是,创建了一个单独的
drawing buffer
,所有的
shape
都被绘制到这个
buffer
中,在这个

transparency layer
结束后,然后
buffer
作为一个整体被绘制到
context
中,所以就只有一个阴影

本例的内容是为上一节的chart,创建一个阴影

如果单独添加如下代码:

//阴影
let shadowColor = UIColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 0.4)
CGContextSetShadowWithColor(context, CGSize(width: 10,height: 10), 1, shadowColor.CGColor)


此时的效果如下,会发现每个扇形区域都一个阴影:



当添加
CGContextBeginTransparencyLayer(context, nil)




还要注意的是当改变当前CTM,最好使用
CGContextSaveGState
来保存状态

完整代码如下:

    CGContextSaveGState(context)
//阴影 let shadowColor = UIColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 0.4) CGContextSetShadowWithColor(context, CGSize(width: 10,height: 10), 1, shadowColor.CGColor)
CGContextBeginTransparencyLayer(context, nil)

let workingCategories = categories.filter({ $0.spent > 0 })

for (index, _) in workingCategories.enumerate() {

......

}

circle.stroke()
//结束TransparencyLayer
CGContextEndTransparencyLayer(context)
CGContextRestoreGState(context)


可以对context进行scale和translate,使chart看起来有3d的效果

CGContextScaleCTM(context, 1, 0.6)
CGContextTranslateCTM(context, 0, 100)


效果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  core graphics swift matrix