Flutter 手势缩放图片并且截取指定区域显示
2021-03-03 本文已影响0人
代瑶
![](https://img.haomeiwen.com/i8830165/b382a1b807003c2b.gif)
效果图如上, 我是看的maka编辑器,照着来的,结果光这个动画居然写了两三天,不过还好弄好了,带有边界检测,手势放大,放大的区域可以在阿里云生成指定大小的图片,效果很完美, 贴代码
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class ClipperImage2 extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _ClipperState();
}
}
class _ClipperState extends State {
String backgroundUrl = "https://img1.maka.im/materialStore/beijingshejia/tupianbeijinga/9/M_69F3SAO8/M_69F3SAO8_v1.jpg";
GlobalKey _contentGlobalKey = GlobalKey();
///图片的唯一KEY
GlobalKey _pictureGlobalKey = GlobalKey();
double viewWidth = 125;
double viewHeight = 196;
double imageOriginWidth = 750;
double imageOriginHeight = 1181;
double _currentScale = 1.0;
Offset _pictureDefOffset = Offset(100, 100);
Offset _dragViewOffset = Offset(100, 100);
double _lastViewScale = 1.0;
Offset _lastViewPoint;
@override
void didUpdateWidget(covariant StatefulWidget oldWidget) {
super.didUpdateWidget(oldWidget);
// _currentScale = 1.82;
}
@override
Widget build(BuildContext context) {
return GestureDetector(
key: _contentGlobalKey,
onScaleStart: _handleScaleStart,
onScaleUpdate: (d) => _handleScaleUpdate(context.size, d),
onScaleEnd: _handleScaleEnd,
child: Stack(
children: [
Positioned(
left: _dragViewOffset.dx,
top: _dragViewOffset.dy,
child: Transform.scale(
scale: _currentScale,
child: Image.network(
backgroundUrl,
key: _pictureGlobalKey,
width: viewWidth,
height: viewHeight,
fit: BoxFit.cover,
),
),
),
//
CustomPaint(
painter: DrawRectLight(Size(viewWidth, viewHeight), _pictureDefOffset),
size: Size(double.infinity, double.infinity),
),
//
Positioned(
bottom: 20,
left: 0,
right: 0,
child: InkWell(
onTap: saveClipperInfo,
child: Text(
"双指缩放调整图片大小",
style: TextStyle(fontSize: 14, color: Colors.white),
textAlign: TextAlign.center,
),
),
),
],
),
);
}
/* Offset _getRelativePosition() {
RenderBox imageRenderBox = _pictureGlobalKey.currentContext.findRenderObject();
RenderBox contentRenderBox = _contentGlobalKey.currentContext.findRenderObject();
Offset _relativePosition = imageRenderBox.globalToLocal(
_pictureDefOffset,
ancestor: contentRenderBox,
);
return _relativePosition;
}*/
void _handleScaleStart(ScaleStartDetails details) {
print('_handleScaleStart');
_lastViewScale = _currentScale;
_lastViewPoint = details.focalPoint;
}
void _handleScaleUpdate(Size size, ScaleUpdateDetails details) {
if (details.scale != 1) {
///缩放
double tempScale = _lastViewScale * details.scale;
//缩放可以保证不小于1, 放大到多大并不管
if (tempScale < 1) return;
//缩放生效
_currentScale = tempScale;
} else {
Offset tempPositionPoint = _dragViewOffset + (details.focalPoint - _lastViewPoint);
_dragViewOffset = tempPositionPoint;
_lastViewPoint = details.focalPoint;
}
///检测是否临界边界
double _correctDx = _dragViewOffset.dx;
double _correctDy = _dragViewOffset.dy;
double leftVerticalLine = (viewWidth * _currentScale - viewWidth) / 2 + _pictureDefOffset.dx;
double topVerticalLine = (viewHeight * _currentScale - viewHeight) / 2 + _pictureDefOffset.dy;
double rightVerticalLine = _pictureDefOffset.dx - (leftVerticalLine - _pictureDefOffset.dx);
double bottomHorizontalLine = _pictureDefOffset.dy - (topVerticalLine - _pictureDefOffset.dy);
if (_correctDx > leftVerticalLine) {
_correctDx = leftVerticalLine;
}
if (_correctDy > topVerticalLine) {
_correctDy = topVerticalLine;
}
if (_correctDx < rightVerticalLine) {
_correctDx = rightVerticalLine;
}
if(_correctDy < bottomHorizontalLine){
_correctDy = bottomHorizontalLine;
}
_dragViewOffset = Offset(_correctDx, _correctDy);
setState(() {});
}
void _handleScaleEnd(ScaleEndDetails details) {
setState(() {});
}
void saveClipperInfo() {
int clipWidth = (imageOriginWidth / _currentScale).round();
int clipHeight = (imageOriginHeight / _currentScale).round();
int offsetX = ((((viewWidth * _currentScale - viewWidth) / 2 + _pictureDefOffset.dx) - _dragViewOffset.dx) *
(imageOriginWidth / (viewWidth * _currentScale)))
.abs()
.round();
int offsetY = ((((viewHeight * _currentScale - viewHeight) / 2 + _pictureDefOffset.dy) - _dragViewOffset.dy) *
(imageOriginHeight / (viewHeight * _currentScale)))
.abs()
.round();
print(backgroundUrl +
"?x-oss-process=image/crop,"
"x_$offsetX,"
"y_$offsetY,"
"w_$clipWidth,"
"h_$clipHeight");
}
}
class DrawRectLight extends CustomPainter {
Size _pictureSize;
Offset _pictureOffset;
DrawRectLight(this._pictureSize, this._pictureOffset);
@override
void paint(Canvas canvas, Size size) {
var paint = Paint();
paint
..style = PaintingStyle.fill
..color = Color(0xaa000000);
///假设是中心点
canvas.clipRect(
Rect.fromLTRB(
_pictureOffset.dx,
_pictureOffset.dy,
_pictureOffset.dx + _pictureSize.width,
_pictureOffset.dy + _pictureSize.height,
),
clipOp: ClipOp.difference,
);
canvas.drawRect(Rect.fromLTRB(0, 0, size.width, size.height), paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}