2009-08-18 9 views
14

NSScrollView (myScrollView)에 래핑 된 NSView (myView)가 있습니다. 확대/축소 버튼을 사용하여 myView의 배율을 변경할 수 있습니다. 사용자가 현재 myView의 특정 지점으로 스크롤되는 경우, 확대 한 후에 화면의 해당 부분을 화면에 유지하고 싶습니다.스케일을 변경할 때 NSScrollView에서 스크롤 위치를 유지하는 방법은 무엇입니까?

I는 다음과 같습니다 코드를 가지고 :

// 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]]; 

을 그리고 그것은 일종의 가까이 보이지만, 그것은 아주 옳지 않아 나는 내가 잘못 뭘하는지 알아낼 수 없습니다. 내 두 가지 질문은 다음과 같습니다

1)이 아닌 내장의 라인을 따라 뭔가 :하지 않으면

[myView adjustScaleBy: 0.5 whilePreservingLocationInScrollview:myScrollView]; 

2), 사람이 내 "먼 길을 잘못 뭘하는지 볼 수 있습니다 위의 "접근 방식을 사용합니까?

감사합니다.

답변

11

스케일링 후 동일한 스크롤 위치를 유지하는 것은 쉽지 않습니다. 당신이 결정할 필요가있는 것은 "같은 것"에 의한 것입니다 - 스케일링 이전에 가시 영역의 상단, 중간 또는 하단을 스케일링하기를 원합니까?

또는 더 직관적으로, 시작 위치에서 문서를 아래로 스크롤하는 백분율과 동일한 백분율로 위치를 유지하고 싶습니다 (예 : 스크롤러의 엄지 중심에서 ' 척도 중 위나 아래로 움직이면 엄지 손가락이 커지거나 작아짐).

후자의 효과를 원한다면 NSScrollView의 verticalScroller 및 horizontalScroller를 가져 와서 'floatValue 's'를 읽는 것입니다. 0에서 1로 정규화됩니다. 여기서 '0'은 문서 상단에 있음을 의미하고 1은 사용자의 끝에 있음을 의미합니다. 스크롤러에 대해 좋은 점은 문서가 NSScrollView보다 짧으면 스크롤러가 항상 'floatValue'에 대한 모든 경우에 정상적인 응답을 반환하기 때문에 특별한 경우는 필요하지 않습니다.

크기를 조정 한 후 NSScrollView의 스크롤 위치를 배율 이전과 동일한 백분율로 설정합니다.하지만 슬프게도 손을 조금 흔들립니다. 나는 잠시 동안 내 코드에서이 작업을 수행하지는 않았지만, NSScrollers의 'floatValue'를 직접 설정할 수는 없다는 것을 기억하고 있습니다. 즉, 실제로는 NSScrollView에 영향을 미치지 않을 것입니다.

따라서 y 축에서 원하는 백분율을 기준으로 문서의 새로운 왼쪽 위 점을 계산하려면 몇 가지 계산을 작성해야합니다. 예를 들어, "문서가 scrollView의 contentView보다 더 짧으면 0 점으로 스크롤하고, 그렇지 않으면 문서의 아래쪽에있는 (heightView of contentView - height of documentView) * oldVerticalPercentage) 점으로 스크롤하십시오." X 축은 물론 유사합니다.

또한 여기서는 -display에 대한 호출이 필요하지 않으며 일반적으로 호출해서는 안됩니다. (-setNeedsDisplay :. 최대)

-Wil 나 당신이 너무 많이 입력 싶은 생각

+0

내가 원하는 결과는 다음과 같습니다. 화면 중간을보고 있습니다. 내가 확대 (또는 -out) 할 때, 화면 중앙에 그 것을 유지하십시오. 감사합니다. – Olie

+0

우수 답변! 계산 된 원점으로 뷰를 스크롤 한 후에 스크롤러에 floatValue를 설정하는 대신 스크롤 뷰에서 reflectScrolledClipView :를 호출했습니다. 이것은 스크롤 바가 올바른 위치에있는 것처럼 보입니다. 이것이 내가 만든 첫 번째 Mac 응용 프로그램이므로 이것이 맞는지 확실하지 않지만 나에게 적합합니다. – afarnham

7

... ;-)

// 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); 
+0

네, 게시 한 직후에 대해 배웠습니다. 나는 아이폰 세계에서 왔고, 사물의 NS 이름을 추측하는 것은 나에게 조금 느리다. 감사! :) – Olie

6

이 오래된 질문이다,하지만 난 사람이 찾고 희망 내 대답이 유용하다는 걸 알았어.

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]; 
} 
+0

나는 그것이 아주 유용하다는 것을 알았다. 이것은 여러 가지 다른 일을 시도한 후에도 효과가있었습니다. 게시 해 주셔서 감사합니다! – jbillfinger

+1

위대한 작품! 유일한 문제는 윈도우의 크기를 조절할 때 (따라서 스크롤보기), 내용이 왼쪽 아래로 다시 스크롤됩니다. –

+0

@ NicolasMiari 콘텐츠가 왼쪽 하단으로 스크롤되는 문제가 있습니다. 해결 방법을 찾았습니까? –