swift - iOS Animate Mask Over UIImage -
i using swift 1.2 , goal animate image mask on static uiimage. have implemented swift version of masking image found in objective-c.
func maskimage(image: uiimage, mask: uiimage) -> uiimage! { let maskref = mask.cgimage; let mask = cgimagemaskcreate( cgimagegetwidth(maskref), cgimagegetheight(maskref), cgimagegetbitspercomponent(maskref), cgimagegetbitsperpixel(maskref), cgimagegetbytesperrow(maskref), cgimagegetdataprovider(maskref), nil, false); let masked = cgimagecreatewithmask(image.cgimage, mask); let retimage = uiimage(cgimage: masked); return retimage; }
it works great! however, putting in motion challenge.
is there way either iteratively apply mask different horizontal offset or better way approach problem entirely - perhaps calayer implementation?
thanks help!
edit: based on posted answer, added this:
let image = uiimage(named: "clouds"); let imageview = uiimageview(image: image); let layer = calayer(); layer.contents = uiimage(named: "alpha-mask")?.cgimage; layer.bounds = cgrectmake(0, 0, image.size.width, image.size.height); // other folks learning, did not work //let animation = cabasicanimation(keypath: "bounds.origin.x"); // work let animation = cabasicanimation(keypath: "position.x"); animation.duration = 2; animation.delegate = self; animation.fillmode = kcafillmodeforwards; animation.repeatcount = 0; animation.fromvalue = 0.0; animation.tovalue = image.size.width; animation.timingfunction = camediatimingfunction(name: kcamediatimingfunctionlinear); animation.removedoncompletion = false; layer.addanimation(animation, forkey: "transform"); imageview.layer.mask = layer; self.addsubview(imageview);
i able see alpha mask properly, animation not work. ideas?
edit: modified code above , works! needed make keypath position.x. see above
you indeed want use calayer - or rather, cashapelayer.
you can create cashapelayer , install as mask on layer.
you can create caanimation animates changes shape layer's path, or can animate changes layer's strokestart and/or strokeend properties.
if animate path, 1 rule want follow make sure starting , ending path have same number , type of control points. otherwise animation "undefined", , results can strange.
i have development blog post outlines how it's done:
http://wareto.com/using-core-animation-groups-to-create-animation-sequences-2
it's using caanimationgroups, includes working example of animating changes cashapelayer that's used mask of image view's layer.
below gif of mask animation creates - "clock wipe" shows , hides image view:
unfortunately it's written in objective-c, core animation calls identical in swift. let me know if have problems figuring out how adapt it.
the meat of animation code method:
- (ibaction)domaskanimation:(id)sender; { waretologolarge.hidden = false;//show image view //create shape layer use mask waretologolarge image view cashapelayer *masklayer = [cashapelayer layer]; cgfloat maskheight = waretologolarge.layer.bounds.size.height; cgfloat maskwidth = waretologolarge.layer.bounds.size.width; cgpoint centerpoint; centerpoint = cgpointmake( maskwidth/2, maskheight/2); //make radius of our arc large enough reach corners of image view. cgfloat radius = sqrtf(maskwidth * maskwidth + maskheight * maskheight)/2; //don't fill path, stroke in black. masklayer.fillcolor = [[uicolor clearcolor] cgcolor]; masklayer.strokecolor = [[uicolor blackcolor] cgcolor]; masklayer.linewidth = radius; //make line thick enough fill circle we're drawing cgmutablepathref arcpath = cgpathcreatemutable(); //move starting point of arc there no initial line connecting arc cgpathmovetopoint(arcpath, nil, centerpoint.x, centerpoint.y-radius/2); //create arc @ 1/2 our circle radius, line thickess of full circle radius cgpathaddarc(arcpath, nil, centerpoint.x, centerpoint.y, radius/2, 3*m_pi/2, -m_pi/2, yes); masklayer.path = arcpath; //start empty mask path (draw 0% of arc) masklayer.strokeend = 0.0; cfrelease(arcpath); //install mask layer out image view's layer. waretologolarge.layer.mask = masklayer; //set our mask layer's frame parent layer's bounds. waretologolarge.layer.mask.frame = waretologolarge.layer.bounds; //create animation increases stroke length 1, reverses zero. cabasicanimation *swipe = [cabasicanimation animationwithkeypath:@"strokeend"]; swipe.duration = 2; swipe.delegate = self; [swipe setvalue: theblock forkey: kanimationcompletionblock]; swipe.timingfunction = [camediatimingfunction functionwithname:kcamediatimingfunctionlinear]; swipe.fillmode = kcafillmodeforwards; swipe.removedoncompletion = no; swipe.autoreverses = yes; swipe.tovalue = [nsnumber numberwithfloat: 1.0]; [masklayer addanimation: swipe forkey: @"strokeend"]; }
i have blog entry is in swift shows how create , animate pie chart using cashapelayer
. project animates shape, not mask, real difference whether install shape layer regular content layer or mask on layer backing layer of image view.
you can check out project @ link:
Comments
Post a Comment