focusOnChild method
void
focusOnChild(
- CanvasChildId id, {
- ScalingMode scalingMode = ScalingMode.keepScale,
- bool animate = true,
- double preferredHorizontalMargin = 16,
- Duration? duration,
- Size? childSize,
- dynamic forceRedraw = false,
Focus the viewport on a child by its ID, with a margin in screen-space. If it's already rendered, size will be picked up from the child widget. If not an offstage rendering will be used ( double render ) Preferred horizontal margin used for ScalingMode.fitInViewport.
Implementation
void focusOnChild(
CanvasChildId id, {
ScalingMode scalingMode = ScalingMode.keepScale,
bool animate = true,
double preferredHorizontalMargin = 16,
Duration? duration,
Size? childSize,
forceRedraw = false,
}) {
if (!_children.containsKey(id)) {
throw _ChildNotFoundException;
}
final childInfo = _children[id]!;
// try to figure out the size, take from render cache if available
// else do an offstage render
childSize ??= childInfo.lastRenderedSize != null && !forceRedraw
? childInfo.lastRenderedSize
: measureWidgetSize(_context, childInfo.widget);
/*
margin is symmatric on ltrb so
2mx + cx = screenWidth
2my + cy = screenHeight
where c is child size in screen space and m is margin
*/
double newScale = _scale;
Offset newGsTopLeft = _gsTopLeftOffset;
switch (scalingMode) {
case ScalingMode.keepScale:
// do nothing
break;
case ScalingMode.resetScale:
newScale = 1;
case ScalingMode.fitInViewport:
// the scale needs to be determined in this case
// and hence a margin is needed to constrain on x, to get the scale, we then center it along y
newScale = (canvasSize.width - 2 * preferredHorizontalMargin) / childSize!.width;
break;
}
final marginOffset = ((canvasSize.toOffset() - (childSize! * scale).toOffset()) / (2 * scale)).makeAtleast(0);
newGsTopLeft = childInfo.gsPosition - marginOffset;
if (animate) {
animateToOffsetAndScale(offset: newGsTopLeft, duration: duration, scale: newScale);
} else {
_gsTopLeftOffset = newGsTopLeft;
_scale = newScale;
markDirty();
}
}