스케일을 변경할 때 nsscrollview에서 스크롤 위치를 유지하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/1296920

문제

NSSCrollView (MyScrollView)에 NSView (MyView)를 감싸고 있습니다. 축소/출력 버튼을 사용하여 사용자는 MyView의 스케일을 변경할 수 있습니다. 사용자가 현재 MyView의 특정 지점으로 스크롤 된 경우 확대 / 축소가 발생한 후 화면에 해당 부분을 유지하고 싶습니다.

다음과 같이 보이는 코드가 있습니다.

    // 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) 그렇지 않다면, 내가 "긴 길"접근 방식에서 내가 잘못하고있는 일을 볼 수 있습니까?

감사!

도움이 되었습니까?

해결책

스케일링 후 동일한 스크롤 위치를 유지하는 것은 쉽지 않습니다. 결정해야 할 한 가지는 "동일"이 의미하는 바입니다. 스케일링 후에도 제자리에 유지되기 전에 가시 영역의 상단, 중간 또는 하단을 원하십니까?

또는 더 직관적으로, 당신은 시작할 때 문서를 스크롤하는 백분율과 동일하게 보이는 rect의 백분율을 유지하는 위치를 원합니까 (예 : 스크롤러 엄지 손가락의 중심이 위로 이동하지 않거나 움직이지 않아 규모가 낮아지면 엄지 손가락이 자라거나 줄어 듭니다).

후자의 효과를 원한다면 한 가지 방법은 NSSCrollView의 수직 스크롤러 및 HorizOntalScroller를 얻은 다음 'floatValue's를 읽는 것입니다. 이것들은 0에서 1로 정규화되며, 여기서 '0'은 문서의 맨 위에 있고 1은 끝에 있음을 의미합니다. 이를 위해 스크롤러에게 문의하는 데있어 좋은 점은 문서가 NSSCrollView보다 짧은 경우 스크롤러가 여전히 'floatValue'에 대한 모든 경우에 제정신 답변을 반환 하므로이 사실을 특수 신호 할 필요가 없다는 것입니다.

크기를 조정 한 후 NSSCrollView의 스크롤 위치를 규모 이전의 비율로 설정하십시오. 그러나 슬프게도 여기에 손을 조금 흔들리는 곳이 있습니다. 나는 내 코드에서 한동안이 작업을 수행하지 않았지만, 기억대로 NSSCrollers 'FloatValue를 직접 설정할 수는 없습니다. 스크롤처럼 보이지만 실제로 NSSCrollView에 영향을 미치지는 않습니다.

따라서 문서에서 원하는 비율에 따라 문서의 새로운 상단 왼쪽 지점을 계산하려면 수학을 작성해야합니다. 이제 ScrollView의 ContentView보다 짧습니다. Scroll to Point 0, 그렇지 않으면 문서의 아래로 (ContentView -Height of DocumentView의 높이)의 점으로 스크롤하십시오. " X 축은 물론 비슷합니다.

또한, 나는 당신이 여기서 -sclay에 전화를 걸 필요가 없으며 일반적으로 그것을 부르지 말아야합니다. (-SetneedSdisplay : 최대.)

-wil

다른 팁

나는 당신이 너무 많이 입력하는 것을 좋아한다고 생각합니다… ;-)

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

이것은 오래된 질문이지만, 이것을 찾는 사람이 내 대답이 유용하다는 것을 알기를 바랍니다 ...

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];
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top