swift - CATransform3DRotate applied to layer doesnt work -
could please advice why catransform3drotate doesnt work layer in case, blue layer on image.
i have custom view, draw nature view, want animate changing moon phase done inside white circle layer mask. suppose idea apply here 3drotation, reason doesn't work without animation, please advice doing wrong?
func drawmoonphase(inrect rect:cgrect, incontext context: cgcontext) { let moonshape = uibezierpath(ovalin: rect) moonshape.linewidth = 4.0 uicolor.white.setstroke() moonshape.stroke() moonshape.close() let moonlayer = cashapelayer() moonlayer.path = moonshape.cgpath moonlayer.opacity = 0 self.layer.addsublayer(moonlayer) let circlepath = uibezierpath(ovalin: rect) uicolor.blue.setfill() circlepath.fill() circlepath.close() let circleshape = cashapelayer() circleshape.path = circlepath.cgpath circleshape.opacity = 0 var transform = catransform3didentity transform.m34 = -1 / 500.0 transform = catransform3drotate(transform, (cgfloat(double.pi * 0.3)), 0, 1, 0) circleshape.transform = transform moonlayer.mask = circleshape
}
thanks in advance
the transform occurs around layer's anchor point default in center. therefore happening there shape rotates around causing no visible result. :)
what should in layout of layer use cos , sin math functions in order determine x , y position of moon.
let me know if need more insights happy help.
also, please note don't need 2 shapelayers in order have blue moon white stroke. cashapelayer has properties both fill , stroke can simplify code.
based on new info here new answer:
i not able nice effect using transform, decided write mask manually. result:
/** draw mask based on moon phase progress. - parameter rect: rect mon drawn - parameter progress: progress of moon phase. value must between 0 , 1 */ func moonmask(in rect: cgrect, forprogress progress: cgfloat)->calayer { let path = cgmutablepath() let center = cgpoint(x: rect.midx, y: rect.midy) path.move(to: cgpoint(x: rect.midx, y: 0)) let relativeprogress = (max(min(progress, 1), 0) - 0.5) * 2 let radius = rect.width/2 let tgx = rect.midx+(relativeprogress * (radius*4/3)) path.addcurve(to: cgpoint(x: rect.midx, y: rect.maxy), control1: cgpoint(x: tgx, y: 0), control2: cgpoint(x: tgx, y: rect.maxy)) path.addarc(center: center, radius: rect.width/2, startangle: .pi/2, endangle: .pi*3/2, clockwise: false) //path.closesubpath() let mask = cashapelayer() mask.path = path mask.fillcolor = uicolor.black.cgcolor return mask }
the function above draws shapelier can used mask moonlayer. layer drawnin relation progress parameter pass in function 1 full moon , 0 new moon.
you can put have desired effect, , can extract path creation code make nice animation if want.
this should answer question hope. quick test wrote playground:
import uikit let rect = cgrect(origin: .zero, size: cgsize(width: 200, height: 200)) let view = uiview(frame: rect) view.backgroundcolor = .black let layer = view.layer /** draw mask based on moon phase progress. - parameter rect: rect mon drawn - parameter progress: progress of moon phase. value must between 0 , 1 */ func moonmask(in rect: cgrect, forprogress progress: cgfloat)->calayer { let path = cgmutablepath() let center = cgpoint(x: rect.midx, y: rect.midy) path.move(to: cgpoint(x: rect.midx, y: 0)) let relativeprogress = (max(min(progress, 1), 0) - 0.5) * 2 let radius = rect.width/2 let tgx = rect.midx+(relativeprogress * (radius*4/3)) path.addcurve(to: cgpoint(x: rect.midx, y: rect.maxy), control1: cgpoint(x: tgx, y: 0), control2: cgpoint(x: tgx, y: rect.maxy)) path.addarc(center: center, radius: rect.width/2, startangle: .pi/2, endangle: .pi*3/2, clockwise: false) //path.closesubpath() let mask = cashapelayer() mask.path = path mask.fillcolor = uicolor.white.cgcolor return mask } let moonlayer = cashapelayer() moonlayer.path = uibezierpath(ovalin: rect).cgpath moonlayer.fillcolor = uicolor.clear.cgcolor moonlayer.strokecolor = uicolor.white.cgcolor moonlayer.linewidth = 2 moonlayer.shadowcolor = uicolor.white.cgcolor moonlayer.shadowopacity = 1 moonlayer.shadowradius = 10 moonlayer.shadowpath = moonlayer.path moonlayer.shadowoffset = .zero layer.addsublayer(moonlayer) let moonphase = moonmask(in: rect, forprogress: 0.3) moonphase.shadowcolor = uicolor.white.cgcolor moonphase.shadowopacity = 1 moonphase.shadowradius = 10 moonphase.shadowpath = moonlayer.path moonphase.shadowoffset = .zero layer.addsublayer(moonphase) view
Comments
Post a Comment