NSScrollView setMagnification: centeredAtPoint: возможная ошибка? - PullRequest
0 голосов
/ 21 января 2020

У меня есть NSScrollView, и мне нужно масштабировать DocumentView с помощью мыши (вертикальное движение) вокруг точки фокусировки (точка внутри documentView). Я использовал NSScrollView - (void)setMagnification:(CGFloat)magnification centeredAtPoint:(NSPoint)point. Увеличение вычисляется с помощью дельты Y движения мыши на дорожке mouseDown l oop, point - местоположение мыши внутри DocumentView на mouseDown:. Хотя масштабирование назад и вперед (с тем же point) вызывает смещение источника documentView, поэтому, когда я возвращаюсь к той же точке с помощью мыши (точка, где я начал масштабировать), фактические пиксели под курсором мыши перемещаются. Это выглядит как ошибка в вычислении contentView.bounds.origin для NSScrollView во время вызова - (void)setMagnification:(CGFloat)magnification centeredAtPoint:(NSPoint)point. Кто-нибудь заметил / исправил это?

Код, используемый для увеличения NSScroll documentView с вертикальным движением мыши:

@interface MyViewController ()
{
    CGPoint  focusPoint;
    CGPoint  startMouseLocation;
    CGFloat  startZoom;
}

@property (weak) IBOutlet NSScrollView *scrollView;
@property (weak) IBOutlet OverlayView *overlay;

@end

@implementation MyViewController

- (void)awakeFromNib
{
    [super awakeFromNib];
    NSImage* image = [NSImage imageNamed: @"your_image_name"];
    self.scrollView.documentView.wantsLayer = YES;
    self.scrollView.documentView.layer.contents = image;
    [self.scrollView.documentView setFrameSize: image.size];
}

- (void)mouseDown:(NSEvent *)event
{
    self.overlay.testPoint = CGPointIntegral([self.overlay convertPoint: event.locationInWindow fromView: nil]);

    focusPoint = CGPointIntegral([self.scrollView.documentView convertPoint: event.locationInWindow fromView: nil]);
    startMouseLocation = CGPointIntegral(event.locationInWindow);
    startZoom = self.scrollView.magnification;

    [self.scrollView setMagnification: startZoom centeredAtPoint: focusPoint];

        BOOL keepOn = YES;
        NSPoint mouseLoc;

        while (keepOn) {
            event = [self.view.window nextEventMatchingMask: NSEventMaskLeftMouseUp | NSEventMaskLeftMouseDragged];
            mouseLoc = event.locationInWindow;

            switch (event.type) {
                case NSEventTypeLeftMouseDragged:
                {
                    NSInteger y = CGPointIntegral(mouseLoc).y;

                    CGFloat deltaY =  y - startMouseLocation.y;
                    CGFloat zoom = startZoom + deltaY/100.0;
                    [self.scrollView setMagnification: zoom centeredAtPoint: focusPoint];
                }
                break;
                case NSEventTypeLeftMouseUp:
                    keepOn = NO;
                break;
                default:
                        break;
            }
        };

    return;
}

@end

Добавить 2: да, я пытался установить точку фокусировки в пространстве documentView или contentView, но это не влияет на дрейфует во время зума. Проверьте это видео: https://www.dropbox.com/s/zkpg2p53l84s55c/m.mov?dl=0 Оранжевая точка - это место фокусировки. После увеличения и уменьшения масштаба изображение сместилось влево. Дельта (расстояние изображения от точки фокусировки) меньше, когда точка фокусировки ближе к центру изображения. Я проверил все вычисления zoom и focusPoint, и, кажется, все в порядке. После нескольких циклов увеличения / уменьшения я попытался поместить курсор мыши в точное положение при начале масштабирования (focusPoint), чтобы получить исходное значение масштабирования, и даже focusPoint и масштабирование, переданные методу setMagnification:centeredAtPoint:, были правильными (равными значения при запуске масштабирования), изображение сместилось.

...