Oli*_*lie 14 cocoa scroll zoom nsscrollview
我有一个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]];
Run Code Online (Sandbox Code Playgroud)
它似乎有点接近,但它不太正确,我无法弄清楚我做错了什么.我的两个问题是:
1)是否没有内置的东西:
[myView adjustScaleBy: 0.5 whilePreservingLocationInScrollview:myScrollView];
Run Code Online (Sandbox Code Playgroud)
2)如果没有,任何人都可以在我的"长途跋涉"方法中看到我做错了什么?
谢谢!
Wil*_*ley 11
在缩放后保持相同的滚动位置并不容易.您需要决定的一件事是"相同"是什么意思 - 在缩放之前,您是否希望缩放之前可见区域的顶部,中间或底部保持原位?
或者,更直观地说,您是否希望保持位置在可见矩形下方的百分比等于您在开始时向下滚动文档的百分比(例如,因此滚动条拇指的中心不会向上移动或在一个尺度下,拇指只是增长或缩小).
如果你想要后一个效果,一种方法是获取NSScrollView的verticalScroller和horizontalScroller,然后读取它们的'floatValue'.它们从0到1标准化,其中"0"表示您位于文档的顶部,1表示您已经结束.向滚动条询问这个问题的好处是,如果文档比NSScrollView短,滚动条仍然会在所有情况下为"floatValue"返回一个合理的答案,因此您不必特殊情况.
调整大小后,将NSScrollView的滚动位置设置为与缩放之前相同的百分比 - 但遗憾的是,这是我挥动手的位置.我在我的代码中暂时没有这样做,但是我记得你不能直接设置NSScrollers的'floatValue - 它们会LOOK滚动,但它们实际上不会影响NSScrollView.
所以,你必须写一些数学来根据你想要通过它的百分比来计算文档中新的左上角点 - 例如,它看起来像,"如果文档现在比scrollView的contentView短,滚动到0点,否则滚动到文档的((contentView的高度 - documentView的高度)*oldVerticalPercentage).X轴当然是类似的.
此外,我几乎肯定你不需要在这里打电话 - 并且通常不应该永远打电话给它.(-setNeedsDisplay:最多.)
-会
我认为你喜欢输入太多... ;-)
// 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);
Run Code Online (Sandbox Code Playgroud)
这是一个老问题,但我希望有人在寻找这个问题,我的答案很有用......
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];
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
9685 次 |
最近记录: |