资讯专栏INFORMATION COLUMN

js头像裁剪实现——canvas+Jcrop+jQuery

verano / 1631人阅读

摘要:表示的不一定是原生格式的数据。接口基于,继承了的功能并将其扩展使其支持用户系统上的文件。要从其他非对象和数据构造一个,请使用构造函数。要创建包含另一个数据的子集,请使用方法。要获取用户文件系统上的文件对应的对象,请参阅文档。

封好的插件不用写html啦,直接new一个就好了

GitHub地址:https://github.com/Joeoeoe/pr...
两张小猪佩奇的图也送给大家

本来感觉没什么好写的,还是写一下作为第一个插件的留念吧
应该存在很多性能问题或细节问题,望有大神指教

demo如图:

样式就在CSS文件里修改啦

目录

一.使用的工具,关键概念及思路
二.关键的实现操作
1.图片大小缩放
2.Jcrop的使用
3.canvas绘图实现裁剪
4..重新选择图片问题
三.不足之处
1.无法过滤图片太大的情况
2.调整图片大小不知是否过于繁琐

一.使用的工具,关键概念及思路 使用工具

简单介绍使用的库——Jcrop(需要配合jQuery用):Jcrop是一个jQuery图像裁剪插件,通过设置参数与调用API满足裁剪过程的需求,如:设置裁剪框的最大大小,裁剪时的幕布颜色等等,具体百度Jcrop吧

关键概念

Blob与File, 的files,FileReader,canvas下的CanvasRenderingContext2D.drawImage()

1.Blob与File:
直接MDN解释:
“Blob 对象表示一个不可变、原始数据的类文件对象。Blob 表示的不一定是JavaScript原生格式的数据。File 接口基于Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。
要从其他非blob对象和数据构造一个Blob,请使用 Blob() 构造函数。要创建包含另一个blob数据的子集blob,请使用 slice()方法。要获取用户文件系统上的文件对应的Blob对象,请参阅 File文档。”
简单地说:File可以取得系统里的文件,Blob不行

2. 的files:
input元素下有files属性,返回的是一个FileList对象(我理解为一个类数组),这个对象包含了许多File文件(作为元素)的列表(为input附加属性multiple 即可上传多个文件)

直接console.log看看吧

这是FileList

这是File

可是这样我们并没办法直接获取图片,接下来就要用FileReader了

3.FileReader:
MDN: FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。

var reader = new FileReader();
简而言之,即FileReader可以读取File或者Blob的内容
我们将使用reader.readAsDataURL()方法读取内容,此方法将读取内容放在reader.result属性中,这样我们就可以获得上传文件的数据了

把这串数据插进 的src就可以显示图片了

FileReader的具体属性与方法请大家看MDN吧

4.canvas下的CanvasRenderingContext2D.drawImage()方法:

此方法我们用于渲染裁剪出来的图片

这里我们举个例子说明下吧
var canvas = document.getElementById("canvas");
var canvasPen = canvas.getContext("2d");
我喜欢把canvas的2d上下文环境比作一支笔,这里的canvasPen就是CanvasRenderingContext2D了

方法参数的三种格式:
canvasPen.drawImage(image, dx, dy)
canvasPen.drawImage(image, dx, dy, dWidth, dHeight)
canvasPen.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
MDN说明:https://developer.mozilla.org...

这里我们根据应用需要我们用第三种参数格式,具体演示MDN已经说的很清楚啦

思路:

看完上面的关键概念我觉得大家可能也大概知道如何实现了吧
1.用 上传图片
2.FileReader获取文件信息
3.获取的data给予新建的img元素
4.img元素插入div,引入Jcrop插件
5.调用Jcrop的Api,获取虚线框的位置,长宽等
6.长宽位置等信息赋予drawImage进行绘图
7.canvas.toDataURL()方法,将内容导出为base64
8.上传后台

二.关键的实现操作 图片大小缩放
//图像缩小
while (self.shrinkPicWidth > areaWidth || self.shrinkPicHeight > areaHeight){
                    self.scale = Math.min(areaWidth/self.shrinkPicWidth , 
                    areaHeight/self.shrinkPicHeight);
                    self.shrinkPicWidth = self.shrinkPicWidth * self.scale;
                    self.shrinkPicHeight = self.shrinkPicHeight * self.scale;
                    self.resultScale = self.resultScale * self.scale;
                }

一个简单的循环,解释下各个变量
areaWidth/areaHeight:放上传图片区的宽和高
shrinkPicWidth/shrinkPicHeight: 比例缩小后图片的宽和高
scale:每次循环缩小比例
resultscScale:累计缩小的比例,最后的drawImage()方法需要用到

Jcrop的使用

这里摘取了完成代码后的一部分,下面逐一解释下吧

//要在图片加载完后使用脚本
insert_jcrop : function () {
    var self =this;
    //设为对象
    self.jcropObject = $.Jcrop("#target",{    //调用img的id为target
    allowSelect : false,
    bgColor : "black",
    minSize : [50,50],
    maxSize : [this.previewBoxWidth,this.previewBoxHeight],
    onChange : function () {
            self.render();
    },
    onSelect : function () {
            self.render();
    }
});

self.jcropObject = $.Jcrop( img的id , { 参数设置(用花括号括起来) } ) //具体参数大家就自行百度吧
"#target" : id被设为target的img,即能够调用Jcrop的img
render()函数:写在插件里的函数,用于渲染内容到canvas上,下面来介绍render函数

render()函数
render : function () {
        var self = this;
        self.previewCanvasPen.clearRect(0,0,self.previewBoxWidth,self.previewBoxHeight);

        self.startX = self.jcropObject.tellScaled()["x"] /self.resultScale;
        self.startY = self.jcropObject.tellScaled()["y"] /self.resultScale;
        self.clipWidth = self.jcropObject.tellScaled()["w"]/self.resultScale;
        self.clipHeight = self.jcropObject.tellScaled()["h"]/self.resultScale;
        self.previewCanvasPen.drawImage(self.img , self.startX , self.startY , self.clipWidth , self.clipHeight , 0 , 0 , self.previewBoxWidth , self.previewBoxHeight);
},

self.jcropObject.tellScaled()["x"] / self.jcropObject.tellScaled()["y"] : 裁剪区域起点的X与Y坐标

self.jcropObject.tellScaled()["w"] / self.clipHeight = self.jcropObject.tellScaled()["h"] :裁剪区域的宽与高

且每一个数值后都要 /self.resultScale
这是因为我们传递给self.previewCanvasPen的self.img是未缩小的img(即未乘resultScale的img),而我们放入裁剪区的图片是缩小后的,所以要得到相应的位置和长宽需要 /self.resultScale
然后再将所求数值传给drawImage()
右图为原图,如标注所示,选择框区域同理

然后渲染到canvas上就ok啦

三.不足之处

1.无法过滤图片太大的情况
2.调整图片大小不知是否过于繁琐
3.居中方式需要改进
4.暂时没想到

若有不足,望有指教

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95749.html

相关文章

  • 在Laravel项目中实现Ajax上传用户头像

    摘要:在编写程序的过程中,经常会遇到一个经典的文件上传场景上传头像图片。基于对最好的用户体验的追求,写一下之前在项目中实现在项目中的上传头像。 在编写web程序的过程中,经常会遇到一个经典的文件上传场景:上传头像(图片)。基于对最好的用户体验的追求,写一下之前在项目中实现在Laravel项目中的Ajax上传头像。 1.配置路由 在Laravel的routes.php中设置路由: Rou...

    shiina 评论0 收藏0
  • Web端裁剪图片方法

    摘要:由于在端,不能直接处理本地文件,因此可以在后台裁剪图片,或者利用的来处理。通过来访问生成的步骤获取裁剪坐标参照方法中的步骤步骤利用重绘图片首先要设置剪截后的图片大小相等的。 由于在Web端,JavaScript不能直接处理本地文件,因此可以在后台裁剪图片,或者利用html5的canvas来处理。 方法1:传送到后台剪切 步骤1:上传图片到后台,向前端返回图片URL 利用input标签,...

    ysl_unh 评论0 收藏0
  • jQuery插件分享】Cropper——一个简单方便的图片裁剪插件

    摘要:在裁剪框外拖动鼠标会生成一个新的裁剪框。这个是裁剪框的纵横比,默认是不限制的。初始化完成后是否自动显示裁剪框自动显示的裁剪框的大小。方法的使用格式为手动显示裁剪框。 插件介绍 这是一个我在写以前的项目的途中发现的一个国人写的jQuery图像裁剪插件,当时想实现用户资料的头像上传功能,并且能够预览图片,和对图片进行简单的裁剪、旋转,花了不少时间才看到了这个插件,感觉功能挺全面,代码实现起...

    阿罗 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<