UIViewをCGAffineTransformMakeScaleでスケーリングしていますが、スケーリング時に現在の上部の中心点に固定したままにしておきたいです。
view.layer.anchorPoint
の設定を検討しましたが、アンカーポイントの変更を考慮して、これをview.layer.position
の設定と組み合わせて使用する必要があると思います。
誰かが私を正しい方向に向けることができれば、私はとても感謝しています!
ここで私の答えを見て、アンカーポイントを変更したときにビューが移動する理由を理解してください: https://stackoverflow.com/a/12208587/77567
したがって、ビューの変換をIDに設定することから始めます。ビューが変換されていないときに、その上端の中心を見つけます。
CGRect frame = view.frame;
CGPoint topCenter = CGPointMake(CGRectGetMidX(frame), CGRectGetMinY(frame));
次に、上部エッジの中央へのアンカーポイント:
view.layer.anchorPoint = CGPointMake(0.5, 0);
これで、レイヤーのposition
(またはビューのcenter
)がレイヤーの上端の中心の位置になります。ここで停止すると、アンカーポイントを変更する前に、その上端の中心が真の中心であった場所になるようにレイヤーが移動します。したがって、レイヤーのposition
を少し前からそのトップエッジの中央に変更します。
view.layer.position = topCenter;
これで、レイヤーは画面上の同じ場所にとどまりますが、アンカーポイントはその上端の中心であるため、スケールと回転によってそのポイントは固定されたままになります。
置き忘れを避けながら、特定のアンカーポイントを使用してUIViewをスケーリングします。
extension UIView {
func applyTransform(withScale scale: CGFloat, anchorPoint: CGPoint) {
layer.anchorPoint = anchorPoint
let scale = scale != 0 ? scale : CGFloat.leastNonzeroMagnitude
let xPadding = 1/scale * (anchorPoint.x - 0.5)*bounds.width
let yPadding = 1/scale * (anchorPoint.y - 0.5)*bounds.height
transform = CGAffineTransform(scaleX: scale, y: scale).translatedBy(x: xPadding, y: yPadding)
}
}
したがって、ビューの上部中央をアンカーポイントとして、ビューをそのサイズの半分に縮小するには、次のようにします。
view.applyTransform(withScale: 0.5, anchorPoint: CGPoint(x: 0.5, y: 0))
これは古い質問ですが、同じ問題に直面し、@ Rob Mayoffからの回答を少し拡大して目的の動作に到達するまでに多くの時間を要しました(彼の説明のおかげで解決策を見つけました)。ユーザーが触れたポイントからフローティングビューのスケーリングを表示する必要がありました。画面の座標に応じて、縮小、右、左、上、または中央から縮小できます。
最初に行うことは、フローティングビューの中心を設定するタッチポイントで行うことです(Robの説明として、中心である必要があります):
-(void)onTouchInView:(CGPoint)theTouchPosition
{
self.floatingView.center = theTouchPosition;
....
}
次の問題は、実行する内容に応じて、レイヤーのアンカーポイントを設定することです(画面フレームを基準にしてポイントを測定し、スケーリングする場所を決定しました)。
switch (desiredScallingDirection) {
case kScaleFromCenter:
{
//SCALE FROM THE CENTER, SO
//SET ANCHOR POINT IN THE VIEW'S CENTER
self.floatingView.layer.anchorPoint=CGPointMake(.5, .5);
}
break;
case kScaleFromLeft:
//SCALE FROM THE LEFT, SO
//SET ANCHOR POINT IN THE VIEW'S LEFT-CENTER
self.floatingView.layer.anchorPoint=CGPointMake(0, .5);
break;
case kScaleFromBottom:
//SCALE FROM BOTTOM, SO
//SET ANCHOR POINT IN THE VIEW'S CENTER-BOTTOM
self.floatingView.layer.anchorPoint=CGPointMake(.5, 1);
break;
case kScaleFromRight:
//SCALE FROM THE RIGHT, SO
//SET ANCHOR POINT IN THE VIEW'S RIGHT-CENTER
self.floatingView.layer.anchorPoint=CGPointMake(1, .5);
break;
case kScallingFromTop:
//SCALE FROM TOP, SO
//SET ANCHOR POINT IN THE VIEW'S CENTER-TOP
self.floatingView.layer.anchorPoint=CGPointMake(.5, 0);
break;
default:
break;
}
今、それはすべて簡単です。アニメーションに与えたい効果に応じて(アイデアは0から100%までのバウンススケーリングでした):
//SETUP INITIAL SCALING TO (ALMOST) 0%
CGAffineTransform t=CGAffineTransformIdentity;
t=CGAffineTransformScale(t, .001, .001);
self.floatingView.transform=t;
[UIView animateWithDuration:.2
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
//BOUNCE A LITLE UP!
CGAffineTransform t = CGAffineTransformMakeScale(1.1,1.1);
self.floatingView.transform=t;
} completion:^(BOOL finished) {
[UIView animateWithDuration:.1
animations:^{
//JUST A LITTLE DOWN
CGAffineTransform t = CGAffineTransformMakeScale(.9,.9);
self.floatingView.transform = t;
} completion:^(BOOL finished) {
[UIView animateWithDuration:.05
animations:^{
//AND ALL SET
self.floatingView.transform = CGAffineTransformIdentity;
}
completion:^(BOOL finished) {
//ALL SET
}];
}];
}];
それでおしまい。ご覧のとおり、主なことはビューの位置とアンカーポイントを正しく設定することです。これで、すべてが簡単になります。よろしく、そしてコードをあなたと一緒にしましょう!
Swift 4.2
これは私のために働きます:
public extension UIView {
func applyTransform(withScale scale: CGFloat, anchorPoint: CGPoint) {
let xPadding = (scale - 1) * (anchorPoint.x - 0.5) * bounds.width
let yPadding = (scale - 1) * (anchorPoint.y - 0.5) * bounds.height
transform = CGAffineTransform(scaleX: scale, y: scale).translatedBy(x: xPadding, y: yPadding)
}
}