mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Widget coordinate transforms: localToGlobal(), globalToLocal()
This commit is contained in:
parent
d63f9be94f
commit
b5ee723305
@ -6,6 +6,7 @@ import 'dart:math' as math;
|
||||
|
||||
import 'package:sky/rendering/box.dart';
|
||||
import 'package:sky/rendering/object.dart';
|
||||
import 'package:vector_math/vector_math.dart';
|
||||
|
||||
class BlockParentData extends BoxParentData with ContainerParentDataMixin<RenderBox> { }
|
||||
|
||||
@ -248,6 +249,11 @@ class RenderBlockViewport extends RenderBlockBase {
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void applyPaintTransform(Matrix4 transform) {
|
||||
super.applyPaintTransform(transform);
|
||||
transform.translate(0.0, startOffset);
|
||||
}
|
||||
|
||||
void hitTestChildren(HitTestResult result, { Point position }) {
|
||||
defaultHitTestChildren(result, position: position + new Offset(0.0, -startOffset));
|
||||
}
|
||||
|
||||
@ -450,6 +450,42 @@ abstract class RenderBox extends RenderObject {
|
||||
_size = inDebugBuild ? new _DebugSize(value, this, debugCanParentUseSize) : value;
|
||||
}
|
||||
|
||||
void applyPaintTransform(Matrix4 transform) {
|
||||
if (parentData is BoxParentData) {
|
||||
Point position = (parentData as BoxParentData).position;
|
||||
transform.translate(position.x, position.y);
|
||||
}
|
||||
}
|
||||
|
||||
static Point _transformPoint(Matrix4 transform, Point point) {
|
||||
Vector3 position3 = new Vector3(point.x, point.y, 0.0);
|
||||
Vector3 transformed3 = transform.transform3(position3);
|
||||
return new Point(transformed3.x, transformed3.y);
|
||||
}
|
||||
|
||||
Point globalToLocal(Point point) {
|
||||
assert(attached);
|
||||
Matrix4 transform = new Matrix4.identity();
|
||||
RenderObject renderer = this;
|
||||
while(renderer != null) {
|
||||
renderer.applyPaintTransform(transform);
|
||||
renderer = renderer.parent;
|
||||
}
|
||||
/* double det = */ transform.invert();
|
||||
// TODO(abarth): Check the determinant for degeneracy.
|
||||
return _transformPoint(transform, point);
|
||||
}
|
||||
|
||||
Point localToGlobal(Point point) {
|
||||
List <RenderObject> renderers = <RenderObject>[];
|
||||
for (RenderObject renderer = this; renderer != null; renderer = renderer.parent)
|
||||
renderers.add(renderer);
|
||||
Matrix4 transform = new Matrix4.identity();
|
||||
for (RenderObject renderer in renderers.reversed)
|
||||
renderer.applyPaintTransform(transform);
|
||||
return _transformPoint(transform, point);
|
||||
}
|
||||
|
||||
Rect get paintBounds => Point.origin & size;
|
||||
void debugPaint(PaintingCanvas canvas, Offset offset) {
|
||||
if (debugPaintSizeEnabled)
|
||||
@ -550,7 +586,6 @@ class RenderProxyBox extends RenderBox with RenderObjectWithChildMixin<RenderBox
|
||||
if (child != null)
|
||||
canvas.paintChild(child, offset.toPoint());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class RenderConstrainedBox extends RenderProxyBox {
|
||||
@ -1261,6 +1296,11 @@ class RenderViewport extends RenderBox with RenderObjectWithChildMixin<RenderBox
|
||||
}
|
||||
}
|
||||
|
||||
void applyPaintTransform(Matrix4 transform) {
|
||||
super.applyPaintTransform(transform);
|
||||
transform.translate(-scrollOffset.dx, -scrollOffset.dy);
|
||||
}
|
||||
|
||||
void hitTestChildren(HitTestResult result, { Point position }) {
|
||||
if (child != null) {
|
||||
assert(child.parentData is BoxParentData);
|
||||
@ -1512,6 +1552,11 @@ class RenderTransform extends RenderProxyBox {
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void applyPaintTransform(Matrix4 transform) {
|
||||
super.applyPaintTransform(transform);
|
||||
transform.multiply(_transform);
|
||||
}
|
||||
|
||||
String debugDescribeSettings(String prefix) {
|
||||
List<String> result = _transform.toString().split('\n').map((s) => '$prefix $s\n').toList();
|
||||
result.removeLast();
|
||||
|
||||
@ -10,6 +10,7 @@ import 'package:sky/base/debug.dart';
|
||||
import 'package:sky/base/hit_test.dart';
|
||||
import 'package:sky/base/node.dart';
|
||||
import 'package:sky/base/scheduler.dart' as scheduler;
|
||||
import 'package:vector_math/vector_math.dart';
|
||||
|
||||
export 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path;
|
||||
export 'package:sky/base/hit_test.dart' show EventDisposition, HitTestTarget, HitTestEntry, HitTestResult;
|
||||
@ -412,6 +413,8 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
|
||||
void debugPaint(PaintingCanvas canvas, Offset offset) { }
|
||||
void paint(PaintingCanvas canvas, Offset offset) { }
|
||||
|
||||
void applyPaintTransform(Matrix4 transform) { }
|
||||
|
||||
|
||||
// EVENTS
|
||||
|
||||
|
||||
@ -369,6 +369,21 @@ abstract class Widget {
|
||||
return '$runtimeType($key; hashCode=$hashCode)';
|
||||
}
|
||||
|
||||
// This function can be safely called when the layout is valid.
|
||||
// For example Listener or SizeObserver callbacks can safely call
|
||||
// globalToLocal().
|
||||
Point globalToLocal(Point point) {
|
||||
assert(mounted);
|
||||
assert(root is RenderBox);
|
||||
return (root as RenderBox).globalToLocal(point);
|
||||
}
|
||||
|
||||
// See globalToLocal().
|
||||
Point localToGlobal(Point point) {
|
||||
assert(mounted);
|
||||
assert(root is RenderBox);
|
||||
return (root as RenderBox).localToGlobal(point);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user