add tap & long-press event
This commit is contained in:
parent
52d70a0e07
commit
a3fa7f319d
2 changed files with 64 additions and 4 deletions
|
|
@ -73,6 +73,10 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||||
animSpeed: 1.0,
|
animSpeed: 1.0,
|
||||||
sensorControl: SensorControl.Orientation,
|
sensorControl: SensorControl.Orientation,
|
||||||
onViewChanged: onViewChanged,
|
onViewChanged: onViewChanged,
|
||||||
|
onTap: (longitude, latitude, tilt) => print('onTap: $longitude, $latitude, $tilt'),
|
||||||
|
onLongPressStart: (longitude, latitude, tilt) => print('onLongPressStart: $longitude, $latitude, $tilt'),
|
||||||
|
onLongPressMoveUpdate: (longitude, latitude, tilt) => print('onLongPressMoveUpdate: $longitude, $latitude, $tilt'),
|
||||||
|
onLongPressEnd: (longitude, latitude, tilt) => print('onLongPressEnd: $longitude, $latitude, $tilt'),
|
||||||
child: Image.asset('assets/panorama.jpg'),
|
child: Image.asset('assets/panorama.jpg'),
|
||||||
hotspots: [
|
hotspots: [
|
||||||
Hotspot(
|
Hotspot(
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,10 @@ class Panorama extends StatefulWidget {
|
||||||
this.croppedFullWidth = 1.0,
|
this.croppedFullWidth = 1.0,
|
||||||
this.croppedFullHeight = 1.0,
|
this.croppedFullHeight = 1.0,
|
||||||
this.onViewChanged,
|
this.onViewChanged,
|
||||||
|
this.onTap,
|
||||||
|
this.onLongPressStart,
|
||||||
|
this.onLongPressMoveUpdate,
|
||||||
|
this.onLongPressEnd,
|
||||||
this.child,
|
this.child,
|
||||||
this.hotspots,
|
this.hotspots,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
@ -102,9 +106,21 @@ class Panorama extends StatefulWidget {
|
||||||
/// Original full height from which the image was cropped.
|
/// Original full height from which the image was cropped.
|
||||||
final double croppedFullHeight;
|
final double croppedFullHeight;
|
||||||
|
|
||||||
/// It is called when the view direction has changed, sending the new longitude and latitude values back.
|
/// This event will be called when the view direction has changed, it contains latitude and longitude about the current view.
|
||||||
final Function(double longitude, double latitude, double tilt) onViewChanged;
|
final Function(double longitude, double latitude, double tilt) onViewChanged;
|
||||||
|
|
||||||
|
/// This event will be called when the user has tapped, it contains latitude and longitude about where the user tapped.
|
||||||
|
final Function(double longitude, double latitude, double tilt) onTap;
|
||||||
|
|
||||||
|
/// This event will be called when the user has started a long press, it contains latitude and longitude about where the user pressed.
|
||||||
|
final Function(double longitude, double latitude, double tilt) onLongPressStart;
|
||||||
|
|
||||||
|
/// This event will be called when the user has drag-moved after a long press, it contains latitude and longitude about where the user pressed.
|
||||||
|
final Function(double longitude, double latitude, double tilt) onLongPressMoveUpdate;
|
||||||
|
|
||||||
|
/// This event will be called when the user has stopped a long presses, it contains latitude and longitude about where the user pressed.
|
||||||
|
final Function(double longitude, double latitude, double tilt) onLongPressEnd;
|
||||||
|
|
||||||
/// Specify an Image(equirectangular image) widget to the panorama.
|
/// Specify an Image(equirectangular image) widget to the panorama.
|
||||||
final Image child;
|
final Image child;
|
||||||
|
|
||||||
|
|
@ -137,6 +153,26 @@ class _PanoramaState extends State<Panorama> with SingleTickerProviderStateMixin
|
||||||
Stream<Null> _stream;
|
Stream<Null> _stream;
|
||||||
ImageStream _imageStream;
|
ImageStream _imageStream;
|
||||||
|
|
||||||
|
void _handleTapUp(TapUpDetails details) {
|
||||||
|
final Vector3 o = positionToLatLon(details.localPosition.dx, details.localPosition.dy);
|
||||||
|
widget.onTap(degrees(o.x), degrees(-o.y), degrees(o.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleLongPressStart(LongPressStartDetails details) {
|
||||||
|
final Vector3 o = positionToLatLon(details.localPosition.dx, details.localPosition.dy);
|
||||||
|
widget.onLongPressStart(degrees(o.x), degrees(-o.y), degrees(o.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleLongPressMoveUpdate(LongPressMoveUpdateDetails details) {
|
||||||
|
final Vector3 o = positionToLatLon(details.localPosition.dx, details.localPosition.dy);
|
||||||
|
widget.onLongPressMoveUpdate(degrees(o.x), degrees(-o.y), degrees(o.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleLongPressEnd(LongPressEndDetails details) {
|
||||||
|
final Vector3 o = positionToLatLon(details.localPosition.dx, details.localPosition.dy);
|
||||||
|
widget.onLongPressEnd(degrees(o.x), degrees(-o.y), degrees(o.z));
|
||||||
|
}
|
||||||
|
|
||||||
void _handleScaleStart(ScaleStartDetails details) {
|
void _handleScaleStart(ScaleStartDetails details) {
|
||||||
_lastFocalPoint = details.localFocalPoint;
|
_lastFocalPoint = details.localFocalPoint;
|
||||||
_lastZoom = null;
|
_lastZoom = null;
|
||||||
|
|
@ -290,12 +326,28 @@ class _PanoramaState extends State<Panorama> with SingleTickerProviderStateMixin
|
||||||
return Matrix4.rotationY(radians(90.0 - lon))..rotateX(radians(lat));
|
return Matrix4.rotationY(radians(90.0 - lon))..rotateX(radians(lat));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector3 positionToLatLon(double x, double y) {
|
||||||
|
// transform viewport coordinate to NDC, values between -1 and 1
|
||||||
|
final Vector4 v = Vector4(2.0 * x / scene.camera.viewportWidth - 1.0, 1.0 - 2.0 * y / scene.camera.viewportHeight, 1.0, 1.0);
|
||||||
|
// create projection matrix
|
||||||
|
final Matrix4 m = scene.camera.projectionMatrix * scene.camera.lookAtMatrix;
|
||||||
|
// apply inversed projection matrix
|
||||||
|
m.invert();
|
||||||
|
v.applyMatrix4(m);
|
||||||
|
// apply perspective division
|
||||||
|
v.scale(1 / v.w);
|
||||||
|
// get rotation from two vectors
|
||||||
|
final Quaternion q = Quaternion.fromTwoVectors(v.xyz, Vector3(0.0, 0.0, -_radius));
|
||||||
|
// get euler angles from rotation
|
||||||
|
return quaternionToOrientation(q * Quaternion.axisAngle(Vector3(0, 1, 0), math.pi * 0.5));
|
||||||
|
}
|
||||||
|
|
||||||
Vector3 positionFromLatLon(double lat, double lon) {
|
Vector3 positionFromLatLon(double lat, double lon) {
|
||||||
// generate a transform matrix
|
// create projection matrix
|
||||||
final Matrix4 m = scene.camera.projectionMatrix * scene.camera.lookAtMatrix * matrixFromLatLon(lat, lon);
|
final Matrix4 m = scene.camera.projectionMatrix * scene.camera.lookAtMatrix * matrixFromLatLon(lat, lon);
|
||||||
// apply transform
|
// apply projection atrix
|
||||||
final Vector4 v = Vector4(0.0, 0.0, -_radius, 1.0)..applyMatrix4(m);
|
final Vector4 v = Vector4(0.0, 0.0, -_radius, 1.0)..applyMatrix4(m);
|
||||||
// transform homogeneous coordinates to NDC and remaps to the viewport
|
// apply perspective division and transform NDC to the viewport coordinate
|
||||||
return Vector3(
|
return Vector3(
|
||||||
(1.0 + v.x / v.w) * scene.camera.viewportWidth / 2,
|
(1.0 + v.x / v.w) * scene.camera.viewportWidth / 2,
|
||||||
(1.0 - v.y / v.w) * scene.camera.viewportHeight / 2,
|
(1.0 - v.y / v.w) * scene.camera.viewportHeight / 2,
|
||||||
|
|
@ -387,6 +439,10 @@ class _PanoramaState extends State<Panorama> with SingleTickerProviderStateMixin
|
||||||
? GestureDetector(
|
? GestureDetector(
|
||||||
onScaleStart: _handleScaleStart,
|
onScaleStart: _handleScaleStart,
|
||||||
onScaleUpdate: _handleScaleUpdate,
|
onScaleUpdate: _handleScaleUpdate,
|
||||||
|
onTapUp: widget.onTap == null ? null : _handleTapUp,
|
||||||
|
onLongPressStart: widget.onLongPressStart == null ? null : _handleLongPressStart,
|
||||||
|
onLongPressMoveUpdate: widget.onLongPressMoveUpdate == null ? null : _handleLongPressMoveUpdate,
|
||||||
|
onLongPressEnd: widget.onLongPressEnd == null ? null : _handleLongPressEnd,
|
||||||
child: pano,
|
child: pano,
|
||||||
)
|
)
|
||||||
: pano;
|
: pano;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue