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:
@@ -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)),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
4
math.ts
4
math.ts
@@ -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)
|
||||
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
Reference in New Issue
Block a user