Flutter 实现图片裁剪
实现原理很简单 ,自己绘制一个裁剪框, 根据手势 选择到适合的位置 ,然后将选中的区域绘制到一个新的图片上,从而完成裁剪



裁剪框的绘制 这里我是根据点来连线的 因为每个点上会绘制一个拉伸的标识符

List<Offset> points2 = [
Offset(startX, startY),
Offset(startX + cWidth, startY),
Offset(startX + cWidth, startY + cHeight),
Offset(startX, startY + cHeight),
Offset(startX, startY),
];
canvas.drawPoints(PointMode.polygon, points2, paint);//draw the clip box
paint.color = Colors.red;
// paint..style=PaintingStyle.stroke;
double radius = 10;
canvas.drawCircle(points2[0],radius,paint); //draw the drag point
canvas.drawCircle(points2[1],radius,paint);
canvas.drawCircle(points2[2],radius,paint);
// canvas.drawLine(Offset(points2[2].dx-radius, points2[2].dy-radius), Offset(points2[2].dx+radius, points2[2].dy+radius), paint);
canvas.drawCircle(points2[3],radius,paint);

源图片的绘制 ,根据屏幕大小 把图片缩放成适合长宽比例的图片

if (image != null) {
//draw the backgroud image
double dwidth = 0;
double dheight = 0;
if (image.width.toDouble() / width > image.height.toDouble() / height) {
dwidth = width;
dheight = image.height.toDouble() * dwidth / image.width.toDouble();
}
else {
dheight = height;
dwidth = image.width.toDouble() * dheight / image.height.toDouble();
}
if (points.length > 0) {
points[3] = Offset(dwidth, dheight);
}
canvas.drawImageRect(image,
Rect.fromLTWH(0, 0, image.width.toDouble(), image.height.toDouble()),
Rect.fromLTWH((width - dwidth) / 2,
(height - dheight) / 2, dwidth, dheight), paint);
}

绘制完后 就是根据手势的偏移量来计算裁剪框的大小位置
GestureDetector(
onPanDown: onPanDown,
onPanUpdate:onPanUpdate,
onPanEnd: onPanEnd,
),
List<Offset> _points = <Offset>[];
_points有4个值 [0] 代表down的坐标 [1]代表move的左边 [2]代表裁剪框的坐标 [3]代表源图大小
在touchDown的时候 先存储左边 然后我们要计算点的区域是 拉伸 还是移动 拉伸的话是以顶点为中心的放心

onPanDown(DragDownDetails details){
RenderBox referenceBox = context.findRenderObject();
Offset localPosition =
referenceBox.globalToLocal(details.globalPosition);
setState(() {
if(_points.length<3){
_points.add(localPosition);
_points.add(localPosition);
_points.add(Offset(0, 0));
_points.add(Offset(0, 0));
}
else{
_points[0]=localPosition;
_points[1]=localPosition;
}
dHeight = cHeight;
dWidth = cWidth;
double radius = 20;
if(hitPoint(Offset(_points[2].dx+cWidth, _points[2].dy+cHeight),radius , localPosition)){
downPosition =DownPosition.RIGHT_DOWN;
isDrag = false;
}
else if(hitPoint(Offset(_points[2].dx+cWidth, _points[2].dy),radius , localPosition)){
downPosition =DownPosition.RIGHT_UP;
isDrag = false;
}
else if(hitPoint(Offset(_points[2].dx, _points[2].dy+cHeight),radius , localPosition)){
downPosition =DownPosition.LEFT_DOWN;
isDrag = false;
}
else if(hitPoint(_points[2],radius , localPosition)){
downPosition =DownPosition.LEFT_UP;
isDrag = false;
}
});
}

移动的时候 因为 4个点的处理逻辑是不一样的 所以需要单独判断 这里也做了个最小区域

onPanUpdate(DragUpdateDetails details) {
RenderBox referenceBox = context.findRenderObject();
Offset localPosition =
referenceBox.globalToLocal(details.globalPosition);
if(isDrag){
setState(() {
_points[1]=localPosition;
});
}
else{
setState(() {
if(downPosition==DownPosition.RIGHT_DOWN){
cWidth = dWidth+localPosition.dx - _points[1].dx;
cHeight = dHeight +localPosition.dy-_points[1].dy;
}
else if(downPosition==DownPosition.LEFT_UP){
cWidth = dWidth-(localPosition.dx - _points[1].dx);
cHeight = dHeight-(localPosition.dy-_points[1].dy);
_points[2]=localPosition;
}
else if(downPosition==DownPosition.RIGHT_UP){
cWidth = dWidth+localPosition.dx - _points[1].dx;
cHeight = dHeight-(localPosition.dy-_points[1].dy);
_points[2]=Offset(_points[2].dx, localPosition.dy);
}
else if(downPosition==DownPosition.LEFT_DOWN){
cWidth = dWidth-(localPosition.dx - _points[1].dx);
cHeight = dHeight +localPosition.dy-_points[1].dy;
_points[2]=Offset(localPosition.dx, _points[2].dy);
}
if(cWidth<20){
cWidth=20;
};
if(cHeight<20){
cHeight=20;
}
});
}
}

手指抬起的时候将一些坐标重置下

onPanEnd(DragEndDetails details){
setState(() {
isDrag = true;
double startX = _points[1].dx - _points[0].dx+_points[2].dx;
double startY = _points[1].dy - _points[0].dy+_points[2].dy;
if(startX<0)
startX = 0;
else if(startX+cWidth>width){
startX = width-cWidth;
}
if(startY<0)
startY=0;
else if(startY + cHeight>height){
startY = height-cHeight;
}
_points[0]=Offset(0, 0);
_points[1]=Offset(0, 0);
_points[2] = Offset(startX<0?0:startX, startY<0?0:startY);
});
}
Flutter 实现图片裁剪的更多相关文章
- iOS常见用户头像的圆形图片裁剪常见的几种方法
在开发中,基本上APP的用户头像的处理都需要把用户所上传的方形图片,处理为圆形图片.在这里就总结三种常见的处理圆形图片的方法. 1.使用位图上下文 2.使用UIView的layer进行处理 3.使用r ...
- Cropper – 简单的 jQuery 图片裁剪插件
Cropper 是一个简单的 jQuery 图像裁剪插件.它支持选项,方法,事件,触摸(移动),缩放,旋转.输出的裁剪数据基于原始图像大小,这样你就可以用它们来直接裁剪图像. 如果你尝试裁剪跨域图像, ...
- 自己积累的一些Emgu CV代码(主要有图片格式转换,图片裁剪,图片翻转,图片旋转和图片平移等功能)
using System; using System.Drawing; using Emgu.CV; using Emgu.CV.CvEnum; using Emgu.CV.Structure; na ...
- web开发实战--图片裁剪和上传
前言: 最近的开发中, 有一个上传头像的任务. 由于头像本身的特殊性, 其一般流程为选择图片, 编辑裁剪区域, 再继而上传图片操作. 看似简单的东西, 实则是挺麻烦的一件事. 借助这次开发机会, 来具 ...
- PHP图片裁剪_图片缩放_PHP生成缩略图
在制作网页过程中,为了排版整齐美观,对网页中的图片处理成固定大小尺寸的图片,或是要截去图片边角中含有水印的图片,对于图片量多,每天更新大量图,靠人工PS处理是不现实的,那么有没有自动处理图片的程序了! ...
- Croppic – 免费开源的 jQuery 图片裁剪插件
Croppic 这款开源的 jQuery 图片裁剪插件能够满足网站开发人员各种不同的使用需要.只需要简单的上传图片,就可以实现你想要的图像缩放和裁剪功能.因为使用了 HTML5 FormData 对 ...
- Android大图片裁剪终极解决方案(上:原理分析)
转载声明:Ryan的博客文章欢迎您的转载,但在转载的同时,请注明文章的来源出处,不胜感激! :-) http://my.oschina.net/ryanhoo/blog/86842 约几个月前,我正 ...
- apiCloud中图片裁剪模块FNImageClip的使用
思路 1.获取需裁剪图片的地址 2.跳转到裁剪页面 3.裁剪成功返回新图片地址 4.替换原有图片地址 增加修饰和事件 str += '<li class="tu image" ...
- ASP.NET MVC在服务端把异步上传的图片裁剪成不同尺寸分别保存,并设置上传目录的尺寸限制
我曾经试过使用JSAjaxFileUploader插件来把文件.照片以异步的方式上传,就像"MVC文件图片ajax上传轻量级解决方案,使用客户端JSAjaxFileUploader插件01- ...
随机推荐
- GIT 安装和升级
git 安装: http://git-scm.com/download/mac git 升级: $ git clone git://git.kernel.org/pub/scm/git/git.git
- Sql注入基本思路
Sql注入基本思路 利用mysql自己动手 登录 使用show databases;查看数据库,sql注入主要用到的是information_schema这个库(mysql中大小写不敏感) infor ...
- plupload如何限制上传文件数量,限制只能上传单个文件
1 完整代码 $(function() { $("#uploader").pluploadQueue({ runtimes : 'html5,gears,flash,silverl ...
- JS高级:面向对象的构造函数
1 创建对象的方式 1.1 字面量的方式创建对象 var p1 = { name: '张三', run: function () { console.log(this.name + '跑'); } } ...
- linux下node.js 查版本号和更新 how to update node
我用的Mac,不是windows,不太清楚那个怎么搞. Linux下就是终端直接命令 //查版本号 node --version // v6.10.1 我很久没更了 //更新 //先清理Npm的cac ...
- Windows安装VMware并在VMware中安装Ubuntu
安装 VMware 去官方下载 VMware 安装包,一路默认到底即可 VMware 安装Ubuntu 参考链接:VMware12安装虚拟机教程.Ubuntu16.04安装教程 VM1 ...
- JVM 线上故障排查基本操作--内容问题排查
内存问题排查 说完了 CPU 的问题排查,再说说内存的排查,通常,内存的问题就是 GC 的问题,因为 Java 的内存由 GC 管理.有2种情况,一种是内存溢出了,一种是内存没有溢出,但 GC 不健康 ...
- 解决java.lang.NoSuchMethodException: tk.mybatis.mapper.provider.base.BaseSelectProvider
今天在集成Mapper时 出现如下错误 java.lang.NoSuchMethodException: tk.mybatis.mapper.provider.base.BaseSelectProvi ...
- 在CentOS 7中 使用 Nginx 反代 .Net Core
很久没弄 .Net Core 了,然后忽然发现Windows自带的 Hyper-V 虚拟机貌似挺好用的 .Net Core 之前都是用 Jexus 来做服务器,忽然想用下Nginx来试试 1.在 Ce ...
- Oracle spatial空间查询的选择度分析
在上一篇中,我用一个案例演示了对于数值或字符串类型的字段,选择度的计算方法.并证明了当字段值的选择度不同时,将会影响CBO选择最终的执行计划.对于可排序的字段类型,选择度计算模型已经有很多人写博客介绍 ...