Prevent zooming from moving viewport rect out of bounds (#81)

The problem was that the calculation of the origin bounds was done before clamping the viewport rect size
This commit is contained in:
Jamie Wong
2018-07-01 00:07:04 -07:00
committed by GitHub
parent 16d02cf18f
commit 678e8b4e05
3 changed files with 34 additions and 40 deletions

View File

@@ -5,7 +5,7 @@ import {ReloadableComponent} from './reloadable'
import {CallTreeNode, Frame} from './profile'
import {Flamechart} from './flamechart'
import {Rect, Vec2, AffineTransform} from './math'
import {Rect, Vec2, AffineTransform, clamp} from './math'
import {formatPercent} from './utils'
import {FlamechartMinimapView} from './flamechart-minimap-view'
@@ -50,36 +50,30 @@ export class FlamechartView extends ReloadableComponent<FlamechartViewProps, Fla
)
}
private minConfigSpaceViewportRectWidth() {
return Math.min(
this.props.flamechart.getTotalWeight(),
3 * this.props.flamechart.getMinFrameWidth(),
)
}
private setConfigSpaceViewportRect = (viewportRect: Rect): void => {
const configSpaceDetailViewHeight = Sizes.DETAIL_VIEW_HEIGHT / Sizes.FRAME_HEIGHT
const configSpaceOriginBounds = new Rect(
new Vec2(0, -1),
Vec2.max(
new Vec2(0, 0),
this.configSpaceSize()
.minus(viewportRect.size)
.plus(new Vec2(0, configSpaceDetailViewHeight + 1)),
),
const configSpaceSize = this.configSpaceSize()
const width = clamp(
viewportRect.size.x,
Math.min(configSpaceSize.x, 3 * this.props.flamechart.getMinFrameWidth()),
configSpaceSize.x,
)
const configSpaceSizeBounds = new Rect(
new Vec2(this.minConfigSpaceViewportRectWidth(), viewportRect.height()),
new Vec2(this.configSpaceSize().x, viewportRect.height()),
const size = viewportRect.size.withX(width)
const origin = Vec2.clamp(
viewportRect.origin,
new Vec2(0, -1),
Vec2.max(
Vec2.zero,
configSpaceSize.minus(size).plus(new Vec2(0, configSpaceDetailViewHeight + 1)),
),
)
this.setState({
configSpaceViewportRect: new Rect(
configSpaceOriginBounds.closestPointTo(viewportRect.origin),
configSpaceSizeBounds.closestPointTo(viewportRect.size),
),
configSpaceViewportRect: new Rect(origin, viewportRect.size.withX(width)),
})
}

View File

@@ -56,6 +56,10 @@ export class Vec2 {
return new Vec2(Math.max(a.x, b.x), Math.max(a.y, b.y))
}
static clamp(v: Vec2, min: Vec2, max: Vec2) {
return new Vec2(clamp(v.x, min.x, max.x), clamp(v.y, min.y, max.y))
}
static zero = new Vec2(0, 0)
static unit = new Vec2(1, 1)

View File

@@ -8,7 +8,7 @@ import {CanvasContext} from './canvas-context'
import {FlamechartRenderer, FlamechartRowAtlasKey} from './flamechart-renderer'
import {Flamechart} from './flamechart'
import {RowAtlas} from './row-atlas'
import {Rect, AffineTransform, Vec2} from './math'
import {Rect, AffineTransform, Vec2, clamp} from './math'
import {FlamechartPanZoomView, FlamechartPanZoomViewProps} from './flamechart-pan-zoom-view'
import {noop, formatPercent} from './utils'
import {Hovertip} from './hovertip'
@@ -43,25 +43,21 @@ export class FlamechartWrapper extends ReloadableComponent<
private clampViewportToFlamegraph(viewportRect: Rect, flamegraph: Flamechart, inverted: boolean) {
const configSpaceSize = new Vec2(flamegraph.getTotalWeight(), flamegraph.getLayers().length)
let configSpaceOriginBounds = new Rect(
const width = clamp(
viewportRect.size.x,
Math.min(configSpaceSize.x, 3 * flamegraph.getMinFrameWidth()),
configSpaceSize.x,
)
const size = viewportRect.size.withX(width)
const origin = Vec2.clamp(
viewportRect.origin,
new Vec2(0, inverted ? 0 : -1),
Vec2.max(new Vec2(0, 0), configSpaceSize.minus(viewportRect.size).plus(new Vec2(0, 1))),
Vec2.max(Vec2.zero, configSpaceSize.minus(size).plus(new Vec2(0, 1))),
)
const minConfigSpaceViewportRectWidth = Math.min(
flamegraph.getTotalWeight(),
3 * flamegraph.getMinFrameWidth(),
)
const configSpaceSizeBounds = new Rect(
new Vec2(minConfigSpaceViewportRectWidth, viewportRect.height()),
new Vec2(configSpaceSize.x, viewportRect.height()),
)
return new Rect(
configSpaceOriginBounds.closestPointTo(viewportRect.origin),
configSpaceSizeBounds.closestPointTo(viewportRect.size),
)
return new Rect(origin, viewportRect.size.withX(width))
}
private setConfigSpaceViewportRect = (viewportRect: Rect) => {