我在一个
Flutter
应用程序上工作,我在其中使用了 camera
插件。我想放大到 camera
预览的任意点(偏移量),例如放大到屏幕的左上角,然后为其拍照。使用CameraContoroller.setZoomLevel()
方法放大到camera
的中心!是否有可能实现我想要的行为?提前谢谢你!
这就是我想要实现的目标!
不幸的是,相机包可能无法实现您想要的行为。这是因为相机本身无法放大其视图的特定区域,因为缩放与硬件的工作方式。
但是有一些方法可以实现您的预期行为。尝试用 OverflowBox 和/或 ClipRect 包装您的 CameraPreview 并以某种方式定位预览,只有您想要放大的部分可见。 但请注意,您实际上只是以这种方式“缩放”,因为实际的相机视图不会改变(由此产生的切口可能质量更差)。
基本上,您是通过将图像裁剪到预期区域来创建缩放的错觉。
您可以查看具体的代码示例,了解如何在this answer中实现此功能。
请记住,如果您想拍摄“缩放”区域的照片,您必须再次裁剪生成的图像(因为实际的相机视图不会改变),如上述问题中所述。
你可以做到,但它有点不实用,通过在像
InteractiveViewer()
这样的可拖动/可缩放小部件中显示相机图像,然后用GestureDetector()
包裹它,然后制作一个功能,当你双击图像和拖到你想要的点。
即使在原生相机或任何其他相机上,也无法在特定视点进行相机变焦。
我检查过iphone、android甚至Dslr。由于您的相机硬件从一个分散的视角开始。如果不移动或校准相机,就不可能在特定点进行缩放。
问题只能在捕获快照并裁剪特定区域后才能解决,从而给人一种特定缩放的错觉。
然而,如果我们使用多个摄像头并从中制造出一种机制,这可以解决,唯一被忽略的原因是因为这个问题不是很重要。
要使用相机插件在 Flutter 应用中实现您想要的行为,您可以使用 CameraController.setZoomLevel() 方法放大预览中的特定点。但是,此方法仅将缩放级别作为参数,而不是偏移量。
一种可能的解决方案是使用 Transform.scale() 小部件放大预览,然后使用 RenderRepaintBoundary.toImage() 方法以所需的偏移量捕获图像。这是一个例子:
我正在尝试解决您的问题:
代码:
return Listener(
onPointerDown: (_) => _pointers++,
onPointerUp: (_) => _pointers--,
child: Zoom(
maxZoomWidth: 900,
maxZoomHeight: 900,
child: CameraPreview(
controller!,
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onScaleStart: _handleScaleStart,
onScaleUpdate: _handleScaleUpdate,
onTapDown: (TapDownDetails details) =>
onViewFinderTap(details, constraints),
);
}),
),
),
);
你只需要包裹
缩放
小工具
相机预览
工作正常
是的,使用
CameraController
和一些数学可以在您的 Flutter 应用程序中实现您想要的行为。以下是您可以遵循的步骤大纲:
value.aspectRatio
和预览大小计算相机预览的中心点。CameraController.setZoomLevel()
方法将缩放系数应用到相机。CameraController.setRotation()
方法设置相机的旋转以考虑偏移量。CameraController.takePicture()
方法拍摄照片。
下面是一些示例代码,演示了如何放大相机预览的任意点:import 'dart:math';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
class MyCamera extends StatefulWidget {
final List<CameraDescription> cameras;
MyCamera({required this.cameras});
@override
_MyCameraState createState() => _MyCameraState();
}
class _MyCameraState extends State<MyCamera> {
late CameraController _controller;
late Future<void> _initializeControllerFuture;
@override
void initState() {
super.initState();
// Select the first camera from the list of available cameras
final camera = widget.cameras.first;
// Create a CameraController instance
_controller = CameraController(
camera,
ResolutionPreset.high,
enableAudio: false,
);
// Initialize the controller asynchronously
_initializeControllerFuture = _controller.initialize();
}
@override
void dispose() {
// Dispose of the controller when the widget is disposed
_controller.dispose();
super.dispose();
}
void _takePicture() async {
try {
// Wait for the controller to be initialized
await _initializeControllerFuture;
// Calculate the center point of the preview
final size = MediaQuery.of(context).size;
final previewSize = _controller.value.previewSize!;
final previewCenter = Offset(previewSize.width / 2, previewSize.height / 2);
// Calculate the zoom factor and offset
final zoomFactor = 2.0;
final zoomOffset = Offset(-size.width / 4, -size.height / 4);
// Calculate the new center point after applying the zoom and offset
final newCenter = previewCenter.translate(zoomOffset.dx / zoomFactor, zoomOffset.dy / zoomFactor);
// Apply the zoom and rotation to the controller
await _controller.setZoomLevel(zoomFactor);
await _controller.setRotation(pi / 2);
// Wait for the camera to settle after applying the zoom and rotation
await Future.delayed(Duration(milliseconds: 500));
// Capture the picture
final image = await _controller.takePicture();
// Do something with the image
} catch (e) {
// Handle the error
print(e);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('My Camera'),
),
body: FutureBuilder<void>(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return CameraPreview(_controller);
} else {
return Center(child: CircularProgressIndicator());
}
},
),
floatingActionButton: FloatingActionButton(
onPressed: _take