Domanda

Ho un NSView (myView) avvolta in un NSScrollView (myScrollView). L'uso dello zoom-in / out pulsanti, l'utente può modificare la scala di myView. Se l'utente è attualmente scorrere ad un punto particolare nel myView, mi piacerebbe mantenere quella parte della vista sullo schermo dopo lo zoom ha avuto luogo.

Ho il codice che assomiglia a questo:

    // preserve current position in scrollview
    NSRect oldVisibleRect = [[myScrollView contentView] documentVisibleRect];
    NSPoint oldCenter = NSPointFromCGPoint(CGPointMake(oldVisibleRect.origin.x + (oldVisibleRect.size.width  / 2.0),
                                                       oldVisibleRect.origin.y + (oldVisibleRect.size.height / 2.0)));

    // adjust my zoom
    ++displayZoom;
    [self scaleUnitSquareToSize:NSSizeFromCGSize(CGSizeMake(0.5, 0.5))];
    [self calculateBounds];  // make sure my frame & bounds are at least as big as the visible content view
    [self display];

    // Adjust scroll view to keep the same position.
    NSRect newVisibleRect = [[myScrollView contentView] documentVisibleRect];
    NSPoint newOffset = NSPointFromCGPoint(CGPointMake((oldCenter.x * 0.5) - (newVisibleRect.size.width  / 2.0),
                                                       (oldCenter.y * 0.5) - (newVisibleRect.size.height / 2.0)));
    if (newOffset.x < 0)
        newOffset.x = 0;
    if (newOffset.y < 0)
        newOffset.y = 0;

    [[myScrollView contentView] scrollToPoint: newOffset];
    [myScrollView reflectScrolledClipView: [myScrollView contentView]];

E sembra sorta di vicino, ma non è giusto e non riesco a capire cosa sto facendo male. Le mie due domande sono:

1) Non v'è un built-in qualcosa sulla falsariga di:

   [myView adjustScaleBy: 0.5 whilePreservingLocationInScrollview:myScrollView];

2) Se non, qualcuno può vedere quello che sto facendo di sbagliato nel mio "lungo giro" l'approccio, di cui sopra?

Grazie!

È stato utile?

Soluzione

Mantenendo la stessa posizione di scorrimento dopo il ridimensionamento non è facile. Una cosa che devi decidere è che cosa si intende per "lo stesso" - vuoi alto, al centro o in basso della zona visibile prima di scalare fino a rimanere sul posto dopo la scalatura

?

O, più intuitivo, vuoi la posizione che resta al suo posto una percentuale lungo il rettangolo visibile pari alla percentuale che scorrono verso il basso il documento quando si avvia (ad esempio, in modo che il centro del pollice del scroller non lo fa spostarsi verso l'alto o verso il basso durante una scala, il pollice appena cresce o si riduce).

Se si desidera che l'effetto di questi ultimi, un modo per farlo è ottenere verticalScroller e horizontalScroller del NSScrollView, e quindi leggere la loro 'floatValue di. Questi sono normalizzati da 0 a 1, dove '0' significa che siete nella parte superiore del documento e 1 significa che sei alla fine. La cosa bella di chiedere al scroller di questo è che se il documento è più corta della NSScrollView, lo scroller restituisce ancora una risposta sana di mente in tutti i casi per 'floatValue,' in modo da non dover speciale-caso.

Dopo aver ridimensionato, impostare la posizione di scorrimento del NSScrollView essere la stessa percentuale era prima della scala - ma, purtroppo, qui è dove ho agito le mani un po '. Non ho fatto questo in un po 'nel mio codice, ma mi sembra di ricordare non si può semplicemente impostare i NSScrollers' 'di floatValue direttamente -. Cercheranno scorrere, ma non saranno effettivamente influenzare il NSScrollView

Quindi, dovrete scrivere po 'di matematica per calcolare il nuovo punto in alto a sinistra nel documento in base alla percentuale che si desidera essere attraverso di essa - sull'asse y, per esempio, sarà simile, " Se il documento è ora più corta contentView del ScrollView, scorrere fino al punto 0, altrimenti scorrere fino a un punto che è ((altezza contentView - altezza documentView) * oldVerticalPercentage). giù il documento" l'asse X è ovviamente simile.

Inoltre, io sono quasi positivo che non è necessario un invito -display qui, e in generale non dovrebbe mai chiamarlo, mai. (-SetNeedsDisplay:. Al massimo)

-Wil

Altri suggerimenti

Me pensa che ti piace di digitare troppo ...; -)

// instead of this:
NSPoint oldCenter = NSPointFromCGPoint(CGPointMake(oldVisibleRect.origin.x +
    (oldVisibleRect.size.width  / 2.0),

// use this:
NSPoint oldCenter = NSMakePoint(NSMidX(oldVisibleRect), NSMaxY(oldVisibleRect));

// likewise instead of this:
[self scaleUnitSquareToSize:NSSizeFromCGSize(CGSizeMake(0.5, 0.5))];

// use this:
[self scaleUnitSquareToSize:NSMakeSize(0.5, 0.5)];

// and instead of this
NSPoint newOffset = NSPointFromCGPoint(CGPointMake(
    (oldCenter.x * 0.5) - (newVisibleRect.size.width  / 2.0),
    (oldCenter.y * 0.5) - (newVisibleRect.size.height / 2.0)));

// use this:
NSPoint newOffset NSMakePoint(
    (oldCenter.x - NSWidth(newVisibleRect)) / 2.f,
    (oldCenter.y - NSHeight(newVisibleRect)) / 2.f);

Questa è una vecchia questione, ma spero che qualcuno alla ricerca di questo trova la mia risposta utile ...

float zoomFactor = 1.3;

-(void)zoomIn
{
    NSRect visible = [scrollView documentVisibleRect];
    NSRect newrect = NSInsetRect(visible, NSWidth(visible)*(1 - 1/zoomFactor)/2.0, NSHeight(visible)*(1 - 1/zoomFactor)/2.0);
    NSRect frame = [scrollView.documentView frame];

    [scrollView.documentView scaleUnitSquareToSize:NSMakeSize(zoomFactor, zoomFactor)];
    [scrollView.documentView setFrame:NSMakeRect(0, 0, frame.size.width * zoomFactor, frame.size.height * zoomFactor)];

    [[scrollView documentView] scrollPoint:newrect.origin];
}

-(void)zoomOut
{
    NSRect visible = [scrollView documentVisibleRect];
    NSRect newrect = NSOffsetRect(visible, -NSWidth(visible)*(zoomFactor - 1)/2.0, -NSHeight(visible)*(zoomFactor - 1)/2.0);

    NSRect frame = [scrollView.documentView frame];

    [scrollView.documentView scaleUnitSquareToSize:NSMakeSize(1/zoomFactor, 1/zoomFactor)];
    [scrollView.documentView setFrame:NSMakeRect(0, 0, frame.size.width / zoomFactor, frame.size.height / zoomFactor)];

    [[scrollView documentView] scrollPoint:newrect.origin];
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top