Использование UIPinchGestureRecognizer для масштабирования uiviews в одном направлении - PullRequest
6 голосов
/ 20 июля 2011

Я хотел бы знать, как мы можем использовать UIPinchGestureRecognizer для масштабирования UIView только в одном (x или y) направлении.Скажем, если пользователь перемещает свои два пальца жестом сжимания только в одном направлении (горизонтальном), только ширина просмотра должна увеличиваться / уменьшаться, а если пальцы перемещаются только вертикально, высота должна меняться.Если пальцы двигаются по диагонали, то высота и ширина изображения должны увеличиваться / уменьшаться.Я видел пример кода MoveMe от Apple.

UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(scalePiece:)];
[pinchGesture setDelegate:self];
[piece addGestureRecognizer:pinchGesture];
[pinchGesture release];

Масштаб:

- (void)scalePiece:(UIPinchGestureRecognizer *)gestureRecognizer
{
    UIView *piece = (UIView *) [gestureRecognizer view];
    NSLog(@"scalePiece enter");
    if ([gestureRecognizer state] == UIGestureRecognizerStateBegan){
          NSLog(@"inside if");
          lastTouchPosition = [gestureRecognizer locationInView:piece];
    } 
    else if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged){
          NSLog(@"inside else");
          CGPoint currentTouchLocation = [gestureRecognizer locationInView:piece];
          NSLog(@"currentTouchLocation = %@ and lastTouchPosition= %@",NSStringFromCGPoint(currentTouchLocation), NSStringFromCGPoint(lastTouchPosition));
          CGPoint deltaMove = [self calculatePointDistancewithPoint1:currentTouchLocation andPoint2:lastTouchPosition];
          NSLog(@"deltaMove = %@",NSStringFromCGPoint(deltaMove));
          float distance = sqrt(deltaMove.x*deltaMove.x + deltaMove.y*deltaMove.y);
          NSLog(@"distance = %f",distance);
          float hScale = 1 - deltaMove.x/distance * (1-gestureRecognizer.scale);
          float vScale = 1 - deltaMove.y/distance * (1-gestureRecognizer.scale);
          if (distance == 0) {
                     hScale = 1;
                     vScale = 1;
          }
          NSLog(@"[gestureRecognizer scale] = %f",[gestureRecognizer scale]);
          NSLog(@"hScale = %f and vScale = %f",hScale, vScale);
          piece.transform = CGAffineTransformScale([piece transform], hScale, vScale);
          [gestureRecognizer setScale:1];
          lastTouchPosition = currentTouchLocation;
    }
    NSLog(@"scalePiece exit");
}

Расчет расстояния:

- (CGPoint) calculatePointDistancewithPoint1:(CGPoint)point1 andPoint2:(CGPoint) point2 {
    return CGPointMake(point2.x - point1.x, point2.y - point1.y);
}

Это вывод журнала, когда япопытайтесь ущипнуть (увеличить) изображение, только двигая пальцами в вертикальном направлении.Высота элемента не увеличивается.

2011-07-21 13:06:56.245 New[8169:707] scalePiece enter
2011-07-21 13:06:56.248 New[8169:707] inside if
2011-07-21 13:06:56.251 New[8169:707] scalePiece exit
2011-07-21 13:06:56.259 New[8169:707] scalePiece enter
2011-07-21 13:06:56.262 New[8169:707] inside else
2011-07-21 13:06:56.264 New[8169:707] currentTouchLocation = {88, 87} and lastTouchPosition= {87, 86}
2011-07-21 13:06:56.265 New[8169:707] deltaMove = {-1, -1}
2011-07-21 13:06:56.267 New[8169:707] distance = 1.414214
2011-07-21 13:06:56.268 New[8169:707] [gestureRecognizer scale] = 1.102590
2011-07-21 13:06:56.271 New[8169:707] hScale = 0.927458 and vScale = 0.927458
2011-07-21 13:06:56.272 New[8169:707] scalePiece exit
2011-07-21 13:06:56.281 New[8169:707] scalePiece enter
2011-07-21 13:06:56.283 New[8169:707] inside else
2011-07-21 13:06:56.284 New[8169:707] currentTouchLocation = {87, 89} and lastTouchPosition= {88, 87}
2011-07-21 13:06:56.286 New[8169:707] deltaMove = {1, -2}
2011-07-21 13:06:56.287 New[8169:707] distance = 2.236068
2011-07-21 13:06:56.296 New[8169:707] [gestureRecognizer scale] = 1.096172
2011-07-21 13:06:56.298 New[8169:707] hScale = 1.043009 and vScale = 0.913981
2011-07-21 13:06:56.299 New[8169:707] scalePiece exit
2011-07-21 13:06:56.302 New[8169:707] scalePiece enter
2011-07-21 13:06:56.303 New[8169:707] inside else
2011-07-21 13:06:56.305 New[8169:707] currentTouchLocation = {88, 89} and lastTouchPosition= {87, 89}
2011-07-21 13:06:56.309 New[8169:707] deltaMove = {-1, 0}
2011-07-21 13:06:56.311 New[8169:707] distance = 1.000000
2011-07-21 13:06:56.313 New[8169:707] [gestureRecognizer scale] = 1.066320
2011-07-21 13:06:56.314 New[8169:707] hScale = 0.933680 and vScale = 1.000000
2011-07-21 13:06:56.316 New[8169:707] scalePiece exit
2011-07-21 13:06:56.318 New[8169:707] scalePiece enter
2011-07-21 13:06:56.320 New[8169:707] inside else
2011-07-21 13:06:56.329 New[8169:707] currentTouchLocation = {88, 90} and lastTouchPosition= {88, 89}
2011-07-21 13:06:56.331 New[8169:707] deltaMove = {0, -1}
2011-07-21 13:06:56.333 New[8169:707] distance = 1.000000
2011-07-21 13:06:56.334 New[8169:707] [gestureRecognizer scale] = 1.061696
2011-07-21 13:06:56.335 New[8169:707] hScale = 1.000000 and vScale = 0.938304
2011-07-21 13:06:56.338 New[8169:707] scalePiece exit
2011-07-21 13:06:56.343 New[8169:707] scalePiece enter
2011-07-21 13:06:56.346 New[8169:707] inside else
2011-07-21 13:06:56.347 New[8169:707] currentTouchLocation = {88, 92} and lastTouchPosition= {88, 90}
2011-07-21 13:06:56.349 New[8169:707] deltaMove = {0, -2}
2011-07-21 13:06:56.350 New[8169:707] distance = 2.000000
2011-07-21 13:06:56.351 New[8169:707] [gestureRecognizer scale] = 1.096869
2011-07-21 13:06:56.353 New[8169:707] hScale = 1.000000 and vScale = 0.903131
2011-07-21 13:06:56.362 New[8169:707] scalePiece exit
2011-07-21 13:06:56.366 New[8169:707] scalePiece enter
2011-07-21 13:06:56.370 New[8169:707] inside else
2011-07-21 13:06:56.373 New[8169:707] currentTouchLocation = {88, 92} and lastTouchPosition= {88, 92}
2011-07-21 13:06:56.376 New[8169:707] deltaMove = {0, 0}
2011-07-21 13:06:56.380 New[8169:707] distance = 0.000000
2011-07-21 13:06:56.383 New[8169:707] [gestureRecognizer scale] = 1.035330
2011-07-21 13:06:56.387 New[8169:707] hScale = 1.000000 and vScale = 1.000000
2011-07-21 13:06:56.389 New[8169:707] scalePiece exit
2011-07-21 13:06:56.393 New[8169:707] scalePiece enter
2011-07-21 13:06:56.397 New[8169:707] inside else
2011-07-21 13:06:56.399 New[8169:707] currentTouchLocation = {88, 93} and lastTouchPosition= {88, 92}
2011-07-21 13:06:56.403 New[8169:707] deltaMove = {0, -1}
2011-07-21 13:06:56.406 New[8169:707] distance = 1.000000
2011-07-21 13:06:56.409 New[8169:707] [gestureRecognizer scale] = 1.042659
2011-07-21 13:06:56.412 New[8169:707] hScale = 1.000000 and vScale = 0.957341
2011-07-21 13:06:56.414 New[8169:707] scalePiece exit
2011-07-21 13:06:56.419 New[8169:707] scalePiece enter
2011-07-21 13:06:56.422 New[8169:707] inside else
2011-07-21 13:06:56.425 New[8169:707] currentTouchLocation = {88, 92} and lastTouchPosition= {88, 93}
2011-07-21 13:06:56.427 New[8169:707] deltaMove = {0, 1}
2011-07-21 13:06:56.430 New[8169:707] distance = 1.000000
2011-07-21 13:06:56.432 New[8169:707] [gestureRecognizer scale] = 1.024549
2011-07-21 13:06:56.436 New[8169:707] hScale = 1.000000 and vScale = 1.024549
2011-07-21 13:06:56.439 New[8169:707] scalePiece exit
2011-07-21 13:06:56.442 New[8169:707] scalePiece enter
2011-07-21 13:06:56.447 New[8169:707] inside else
2011-07-21 13:06:56.450 New[8169:707] currentTouchLocation = {88, 92} and lastTouchPosition= {88, 92}
2011-07-21 13:06:56.453 New[8169:707] deltaMove = {0, 0}
2011-07-21 13:06:56.455 New[8169:707] distance = 0.000000
2011-07-21 13:06:56.458 New[8169:707] [gestureRecognizer scale] = 1.007702
2011-07-21 13:06:56.460 New[8169:707] hScale = 1.000000 and vScale = 1.000000
2011-07-21 13:06:56.464 New[8169:707] scalePiece exit
2011-07-21 13:06:56.501 New[8169:707] scalePiece enter
2011-07-21 13:06:56.504 New[8169:707] inside else
2011-07-21 13:06:56.507 New[8169:707] currentTouchLocation = {89, 92} and lastTouchPosition= {88, 92}
2011-07-21 13:06:56.509 New[8169:707] deltaMove = {-1, 0}
2011-07-21 13:06:56.510 New[8169:707] distance = 1.000000
2011-07-21 13:06:56.511 New[8169:707] [gestureRecognizer scale] = 1.000283
2011-07-21 13:06:56.513 New[8169:707] hScale = 0.999717 and vScale = 1.000000
2011-07-21 13:06:56.517 New[8169:707] scalePiece exit
2011-07-21 13:06:56.566 New[8169:707] scalePiece enter
2011-07-21 13:06:56.570 New[8169:707] inside else
2011-07-21 13:06:56.572 New[8169:707] currentTouchLocation = {89, 91} and lastTouchPosition= {89, 92}
2011-07-21 13:06:56.573 New[8169:707] deltaMove = {0, 1}
2011-07-21 13:06:56.575 New[8169:707] distance = 1.000000
2011-07-21 13:06:56.576 New[8169:707] [gestureRecognizer scale] = 1.008267
2011-07-21 13:06:56.579 New[8169:707] hScale = 1.000000 and vScale = 1.008267
2011-07-21 13:06:56.582 New[8169:707] scalePiece exit
2011-07-21 13:06:56.585 New[8169:707] scalePiece enter
2011-07-21 13:06:56.586 New[8169:707] inside else
2011-07-21 13:06:56.588 New[8169:707] currentTouchLocation = {89, 91} and lastTouchPosition= {89, 91}
2011-07-21 13:06:56.589 New[8169:707] deltaMove = {0, 0}
2011-07-21 13:06:56.591 New[8169:707] distance = 0.000000
2011-07-21 13:06:56.597 New[8169:707] [gestureRecognizer scale] = 1.000000
2011-07-21 13:06:56.599 New[8169:707] hScale = 1.000000 and vScale = 1.000000
2011-07-21 13:06:56.600 New[8169:707] scalePiece exit
2011-07-21 13:06:56.603 New[8169:707] scalePiece enter
2011-07-21 13:06:56.604 New[8169:707] inside else
2011-07-21 13:06:56.606 New[8169:707] currentTouchLocation = {89, 182} and lastTouchPosition= {89, 91}
2011-07-21 13:06:56.607 New[8169:707] deltaMove = {0, -91}
2011-07-21 13:06:56.617 New[8169:707] distance = 91.000000
2011-07-21 13:06:56.620 New[8169:707] [gestureRecognizer scale] = 1.000000
2011-07-21 13:06:56.623 New[8169:707] hScale = 1.000000 and vScale = 1.000000
2011-07-21 13:06:56.626 New[8169:707] scalePiece exit
2011-07-21 13:06:56.630 New[8169:707] scalePiece enter
2011-07-21 13:06:56.632 New[8169:707] scalePiece exit

Ответы [ 3 ]

8 голосов
/ 20 июля 2011

Если я правильно понимаю ваш вопрос, вы нацелены на непропорциональное масштабирование по горизонтальной и вертикальной оси.В этом случае все сводится к обеспечению вашего аффинного преобразования:

  piece.transform = CGAffineTransformScale([piece transform], hScale, vScale);

с различными коэффициентами масштабирования.

Один из способов их вычисления заключается в следующем:

  1. определите в своем классе ивара для хранения lastTouchPosition;

  2. в вашем обработчике жестов, вы сделаете что-то вроде этого:

    if ([gestureRecognizer state] == UIGestureRecognizerStateBegan){
    
       lastTouchPosition = [gestureRecognize locationInView:yourViewHere];
       hScale = 1;
       vScale = 1;
    
    } else if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged){
    
       CGPoint currentTouchLocation = [gestureRecognize locationInView:yourViewHere];
       CGPoint deltaMove = CGPointDistance(currentTouchLocation, lastTouchPosition);
       float distance = sqrt(deltaMove.x*deltaMove.x + deltaMove.y*deltaMove.y);
       hScale -= abs(deltaMove.x)/distance * (1-gestureRecognizer.scale);
       vScale -= abs(deltaMove.y)/distance * (1-gestureRecognizer.scale);
       piece.transform = CGAffineTransformScale([piece transform], hScale, vScale);
       [gestureRecognizer setScale:1];
    
       lastTouchPosition = currentTouchLocation;
    }
    

Альтернативный способ сделать это:

    if ([gestureRecognizer state] == UIGestureRecognizerStateBegan){

       lastTouchPosition = [gestureRecognize locationInView:yourViewHere];

    } else if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged){

       CGPoint currentTouchLocation = [gestureRecognize locationInView:yourViewHere];
       CGPoint deltaMove = CGPointDistance(currentTouchLocation, lastTouchPosition);
       float distance = sqrt(deltaMove.x*deltaMove.x + deltaMove.y*deltaMove.y);
       float hScale = 1 - abs(deltaMove.x)/distance * (1-gestureRecognizer.scale);
       float vScale = 1 - abs(deltaMove.y)/distance * (1-gestureRecognizer.scale);
       piece.transform = CGAffineTransformScale([piece transform], hScale, vScale);

       lastTouchPosition = currentTouchLocation;
    }

Это не будет хранить на каждой итерации текущие hFloat и vFloat и вместо этого полагаться на тот факт, что gestureRecognizer будетнакапливать общее изменение масштаба.Он выполняет «абсолютный» расчет, в то время как первая реализация выполняет «относительный».

Обратите внимание, что вам также необходимо определить CGPointDistance, чтобы вычислить расстояние между двумя касаниями и выбрать, какой вид вы собираетесь использовать.используйте для вычисления расстояния (yourViewHere).

РЕДАКТИРОВАТЬ:

CGPoint CGPointDistance(CGPoint point1, CGPoint point2)
{
    return = CGPointMake(point2.x - point1.x, point2.y - point1.y);
};

РЕДАКТИРОВАТЬ 2: о формуле для расчета масштабирования

Идея заключается в вычислении вариации вмасштабный коэффициент и примените его к двум направлениям (x и y) в соответствии с их относительными вариациями.

  1. дельта масштабного коэффициента равна: 1-gestureRecognizer.scale;

  2. дельта умножается на коэффициент, так что он каким-то образом пропорционален смещению по горизонтальной или вертикальной оси;когда смещение равно нулю, дельта-шкала также равна нулю;когда смещение равно по двум осям, дельта шкалы также равна по двум осям;Я решил разделить на distance, но есть и другие возможности (например, деление на сумму двух deltaMoves или на максимум deltaMoves и т. Д.).

  3. скорректированная дельта окончательно вычитается из текущей шкалы элемента.

5 голосов
/ 25 апреля 2014

Сегодня я столкнулся с той же проблемой, и я нашел простой и короткий способ сделать это

- (IBAction)handlePinch:(UIPinchGestureRecognizer *)recognizer
{
  recognizer.view.transform = CGAffineTransformScale(recognizer.view.transform, recognizer.scale,1);
  recognizer.scale = 1;
}
2 голосов
/ 30 июля 2013

Я создал пользовательскую версию UIPinchGestureRecognizer, чтобы сделать именно то, что вы ищете.Он использует наклон линии между двумя пальцами, чтобы определить направление шкалы.Это делает 3 типа: вертикальный;Горизонтальный;и комбинированный (диагональ).Пожалуйста, смотрите мои заметки внизу.

-(void) scaleTheView:(UIPinchGestureRecognizer *)pinchRecognizer
    {
    if ([pinchRecognizer state] == UIGestureRecognizerStateBegan || [pinchRecognizer state] == UIGestureRecognizerStateChanged) {

    if ([pinchRecognizer numberOfTouches] > 1) {

        UIView *theView = [pinchRecognizer view];

        CGPoint locationOne = [pinchRecognizer locationOfTouch:0 inView:theView];
        CGPoint locationTwo = [pinchRecognizer locationOfTouch:1 inView:theView];
            NSLog(@"touch ONE  = %f, %f", locationOne.x, locationOne.y);
            NSLog(@"touch TWO  = %f, %f", locationTwo.x, locationTwo.y);
        [scalableView setBackgroundColor:[UIColor redColor]];

        if (locationOne.x == locationTwo.x) {
                // perfect vertical line
                // not likely, but to avoid dividing by 0 in the slope equation
            theSlope = 1000.0;
        }else if (locationOne.y == locationTwo.y) {
                // perfect horz line
                // not likely, but to avoid any problems in the slope equation
            theSlope = 0.0;
        }else {
            theSlope = (locationTwo.y - locationOne.y)/(locationTwo.x - locationOne.x);
        }

        double abSlope = ABS(theSlope);

        if (abSlope < 0.5) {
                    //  Horizontal pinch - scale in the X
            [arrows setImage:[UIImage imageNamed:@"HorzArrows.png"]];
            arrows.hidden = FALSE;
                    // tranform.a  = X-axis
                NSLog(@"transform.A = %f", scalableView.transform.a);
                    // tranform.d  = Y-axis
                NSLog(@"transform.D = %f", scalableView.transform.d);

                    //  if hit scale limit along X-axis then stop scale and show Blocked image
            if (((pinchRecognizer.scale > 1.0) && (scalableView.transform.a >= 2.0)) || ((pinchRecognizer.scale < 1.0) && (scalableView.transform.a <= 0.1))) {
                blocked.hidden = FALSE;
                arrows.hidden = TRUE;
            } else {
                        // scale along X-axis
                scalableView.transform = CGAffineTransformScale(scalableView.transform, pinchRecognizer.scale, 1.0);
                pinchRecognizer.scale = 1.0;
                blocked.hidden = TRUE;
                arrows.hidden = FALSE;
            }
        }else if (abSlope > 1.7) {
                    // Vertical pinch - scale in the Y
            [arrows setImage:[UIImage imageNamed:@"VerticalArrows.png"]];
            arrows.hidden = FALSE;
                NSLog(@"transform.A = %f", scalableView.transform.a);
                NSLog(@"transform.D = %f", scalableView.transform.d);

                    //  if hit scale limit along Y-axis then don't scale and show Blocked image
            if (((pinchRecognizer.scale > 1.0) && (scalableView.transform.d >= 2.0)) || ((pinchRecognizer.scale < 1.0) && (scalableView.transform.d <= 0.1))) {
                blocked.hidden = FALSE;
                arrows.hidden = TRUE;
            } else {
                        // scale along Y-axis
                scalableView.transform = CGAffineTransformScale(scalableView.transform, 1.0, pinchRecognizer.scale);
                pinchRecognizer.scale = 1.0;
                blocked.hidden = TRUE;
                arrows.hidden = FALSE;
            }
        } else {
                    // Diagonal pinch - scale in both directions
            [arrows setImage:[UIImage imageNamed:@"CrossArrows.png"]];
            blocked.hidden = TRUE;
            arrows.hidden = FALSE;

                NSLog(@"transform.A = %f", scalableView.transform.a);
                NSLog(@"transform.D = %f", scalableView.transform.d);

                    // if we have hit any limit don't allow scaling
            if ((((pinchRecognizer.scale > 1.0) && (scalableView.transform.a >= 2.0)) || ((pinchRecognizer.scale < 1.0) && (scalableView.transform.a <= 0.1))) || (((pinchRecognizer.scale > 1.0) && (scalableView.transform.d >= 2.0)) || ((pinchRecognizer.scale < 1.0) && (scalableView.transform.d <= 0.1)))) {
                blocked.hidden = FALSE;
                arrows.hidden = TRUE;
            } else {
                        // scale in both directions
                scalableView.transform = CGAffineTransformScale(scalableView.transform, pinchRecognizer.scale, pinchRecognizer.scale);
                pinchRecognizer.scale = 1.0;
                blocked.hidden = TRUE;
                arrows.hidden = FALSE;
            }
        }  // else for diagonal pinch
    }  // if numberOfTouches
}  // StateBegan if

if ([pinchRecognizer state] == UIGestureRecognizerStateEnded || [pinchRecognizer state] == UIGestureRecognizerStateCancelled) {
    NSLog(@"StateEnded StateCancelled");
    [scalableView setBackgroundColor:[UIColor whiteColor]];
    arrows.hidden = TRUE;
    blocked.hidden = TRUE;
    }
}

Не забудьте добавить протокол в заголовочный файл контроллера представления:

@interface WhiteViewController : UIViewController <UIGestureRecognizerDelegate>
{
IBOutlet UIView *scalableView;
IBOutlet UIView *mainView;
IBOutlet UIImageView *arrows;
IBOutlet UIImageView *blocked;
}
@property (strong, nonatomic) IBOutlet UIView *scalableView;
@property (strong, nonatomic) IBOutlet UIView *mainView;
@property (strong, nonatomic)IBOutlet UIImageView *arrows;
@property (strong, nonatomic)IBOutlet UIImageView *blocked;

-(void) scaleTheView:(UIPinchGestureRecognizer *)pinchRecognizer;
@end

И добавить распознаватель в viewDidLoad:

- (void)viewDidLoad
{ UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(scaleTheView:)];
[pinchGesture setDelegate:self];
[mainView addGestureRecognizer:pinchGesture];

arrows.hidden = TRUE;
blocked.hidden = TRUE;
[scalableView setBackgroundColor:[UIColor whiteColor]];}

Это настроено на использование основного вида для захвата пинча;и манипулировать вторым видом.Таким образом, вы все еще можете масштабировать его, так как вид становится маленькимВы можете изменить его, чтобы реагировать непосредственно на масштабируемое представление.

LIMITS: Я произвольно выбрал начальный размер моего обзора, чтобы ограничение масштаба 2,0 равнялось полноэкранному.Моя нижняя шкала установлена ​​на 0,1.

ВЗАИМОДЕЙСТВИЕ ПОЛЬЗОВАТЕЛЯ: Я возиться со многими вещами взаимодействия с пользователем, такими как изменение цвета фона представления и добавление / изменение стрелок над видом, чтобы показать направление.Важно дать им обратную связь во время процесса масштабирования, особенно когда изменение направления, как позволяет этот код.

BUG: в UIPinchGestureRecognizer от Apple есть ошибка.Он регистрирует UIGestureRecognizerStateBegan одним касанием пальца, как и следовало ожидать.Но как только он находится в StateBegan или StateChanged, вы можете поднять один палец, и состояние останется.Он не перемещается в StateEnded или StateCancelled, пока оба пальца не будут подняты.Это создало ошибку в моем коде и много головной боли!If numberOfTouches> 1 исправляет это.

БУДУЩЕЕ: Вы можете изменить настройки наклона для масштабирования только в одном направлении или только 2. Если вы добавите изображения стрелок, вы сможете увидеть, как они меняются при повороте пальцев.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...