ios - How do you translate and scale a view without the transforms from conflicting with each other? -
i need translate , scale uiview center of screen upper right corner.
_____________________________ | | | | | _________ | | | | | start | | | | | |_________| | | | | | |____________________________| _____________________________ | __ | | |__| | | | | | end | | | | | | | | |____________________________| i verified individual calculations scale , translation accurate. 1 time set together, conflict each other. next code makes view end close center.
cgfloat finalpadding = 10.0f; cgfloat finalscale = 46.0f / 170.0f; cgfloat finalx = self.view.frame.size.width - self.platformprogressview.frame.size.width * finalscale - finalpadding; cgfloat finaly = finalpadding; cgfloat deltax = finalx - self.platformprogressview.frame.origin.x; cgfloat deltay = finaly - self.platformprogressview.frame.origin.y; [uiview animatewithduration:1.0 delay:1.0 options:uiviewanimationoptioncurveeaseout animations:^(void){ self.platformprogressview.transform = cgaffinetransformconcat( cgaffinetransformmaketranslation(deltax, deltay), cgaffinetransformmakescale(finalscale, finalscale) ); } completion:^(bool finished) { } ]; final effect:
_____________________________ | | | | | __ | | |__| | | | | | | | | | |____________________________| changing order of multiplication causes view veer off right border of screen.
self.platformprogressview.transform = cgaffinetransformconcat( cgaffinetransformmakescale(finalscale, finalscale), cgaffinetransformmaketranslation(deltax, deltay) ); final effect (projected):
_____________________________ | | | | __ | | |__| | | | | | | | | | | |____________________________| applying them seperately causes abrupt jump , final position worse.
self.platformprogressview.transform = cgaffinetransformmaketranslation(deltax, deltay); self.platformprogressview.transform = cgaffinetransformmakescale(finalscale, finalscale); final effect:
_____________________________ | | | | | | | | | __ | | |__| | | | | | |____________________________| understanding transforms
the main thing realize origin transforms center point of view rectangle. best shown example.
first translate view. v1 view @ it's original position, v2 view @ translated position. p padding want (finalpadding in code). c marks center point of view.
+--------------------------------+ | ^ | | | p | | v | | +- v2 --------+ | | | | | | | c |<->| | | | p | | +-------------+ | | | | | | +- v1 --------+ | | | | | | | c | | | | | | | +-------------+ | | | +--------------------------------+ next scale view. v3 view @ scaled position. note how center point v3 remains unchanged while dimensions of view around shrink. although dimensions correct, positioning of view , resulting padding p' wrong.
+--------------------------------+ | ^ | | | p' | | | | | v | | +- v3 --+ | | | c |<---->| | +-------+ p' | | | | | | +- v1 --------+ | | | | | | | c | | | | | | | +-------------+ | | | +--------------------------------+ a prepare delta calculations now know how scaling works, need prepare code calculate translation deltas. here how right:
cgrect windowframe = self.window.frame; cgrect viewframe = self.platformprogressview.frame; cgpoint finalcenter = cgpointzero; finalcenter.x = (windowframe.size.width - (viewframe.size.width * finalscale) / 2.0f - finalpadding); finalcenter.y = (finalpadding + (viewframe.size.height * finalscale) / 2.0f); cgpoint viewcenter = self.platformprogressview.center; cgfloat deltax = finalcenter.x - viewcenter.x; cgfloat deltay = finalcenter.y - viewcenter.y; order of transforms finally, have noted yourself, order in transformations concatenated cgaffinetransformconcat matters. in first effort have sequence 1) transform + 2) scale. result scale transform - comes later in sequence - affects deltas specified translate transform.
there 2 solution here: either own sec attempt, reverse sequence becomes 1) scale + 2) transform. or utilize helper function suggested in first revision of answer. this
self.platformprogressview.transform = cgaffinetransformconcat( cgaffinetransformmakescale(finalscale, finalscale), cgaffinetransformmaketranslation(deltax, deltay) ); is equivalent to
cgaffinetransform cgaffinetransformmakescaletranslate(cgfloat sx, cgfloat sy, cgfloat dx, cgfloat dy) { homecoming cgaffinetransformmake(sx, 0.0f, 0.0f, sy, dx, dy); } self.platformprogressview.transform = cgaffinetransformmakescaletranslate(finalscale, finalscale, deltax, deltay); a different solution: setting anchor point if you're unhappy center point beingness origin view's transforms can alter setting anchorpoint property of view's calayer. default anchor point @ 0.5/0.5, represents center of view rectangle. obviously, anchor point not coordinate kind of multiplication factor.
your original calculation translation deltas right if assume anchor point in upper-left corner of view. if this
self.platformprogressview.layer.anchorpoint = cgpointmake(0.0f, 0.0f) you can maintain original calculations.
referencethere lot more of info material out there, wwdc 2011 video understanding uikit rendering watched , helped me improve understanding of relationship between bounds, center, transform , frame.
also, if going alter calayer anchorpoint property, should read property documentation in calayer class reference first.
ios cocoa-touch matrix linear-algebra
No comments:
Post a Comment