基于HTML5+JS实现本地图片裁剪并上传功能
程序员文章站
2022-07-22 17:04:44
最近做了一个项目,这个项目中需要实现的一个功能是:用户自定义头像(用户在本地选择一张图片,在本地将图片裁剪成满足系统要求尺寸的大小)。这个功能的需求是:头像最初剪切为一个正...
最近做了一个项目,这个项目中需要实现的一个功能是:用户自定义头像(用户在本地选择一张图片,在本地将图片裁剪成满足系统要求尺寸的大小)。这个功能的需求是:头像最初剪切为一个正方形。如果选择的图片小于规定的头像要求尺寸,那么这整张图片都会作为头像。如果大于规定的尺寸,那么用户可以选择要裁剪的区域。用户点击确定按钮,就将裁剪得到的图片数据发送到服务器,在后端将图片数据保存成一个文件。
要完成上述功能,涉及到的知识有:ajax,canvas和html5中的files接口。我将实现这个功能的代码封装到了4个模块中,分别是ajax.js,preview.js,shear.js和customerimg.js。
ajax.js:用于发送ajax请求。
preview.js:用于图片预览
shear.js:用于裁剪图片
customer.js:自定义头像。在这个模块中药引入ajax.js,preview.js和shear.js
我使用webpack进行打包。我还使用了jquery和jquery-ui。
我从这个项目中抽离出了这个功能。下面是这个功能的详细代码。
1.html代码
<div class="m-warp" id="warp"> <div class="item"> <input type="file" name="img" id="img" hidden> <label for="img">选择图片</label> </div> <div class="item clearfix"> <div class="col col-1"> <div class="preview" id="preview"> <div class="mask"></div> <canvas class="cvsmove" id="cvsmove"></canvas> </div> </div> <div class="thum col-2 col"> <p>预览</p> <img src="" id="thum"> <p class="f-text-l f-martop-20"> <button class="shear" id="submit">确定</button> </p> </div> </div> </div>
2.css代码
.clearfix:after{ content: ""; display: block; clear: both; height: 0; overflow: hidden; visibility: hidden; } img{ vertical-align: middle; max-width:100% } .m-warp{ width: 800px; } .item{ margin-top: 20px; } .col{ float: left; } .col-1{ position: relative; width: 450px; height: 450px; outline: 1px solid #333; } .preview{ display: inline-block; } .col-2{ width: 300px; margin-left: 50px; } label{ display: block; text-align: center; width: 100px; font-size: 16px; color: #fff; background-color: #888888; height: 30px; line-height: 30px; } .mask{ position: absolute; z-index: 1; top:0; left: 0; bottom: 0; right: 0; background-color: rgba(0,0,0,.4); } .cvsmove{ position: absolute; z-index: 2; outline: 2px dotted #333; cursor: move; display: none; }
有了css和html的运行结果如下:
3.js代码
customerimg.js
var $ = require('jquery'); var ajax = require('./ajax.js'); var preview = require('./preview.js'); var shear = require('./shear.js'); /** * 自定义头像 * @constructor */ function customerimg() { this.issupport = null; this.previewbox = null; this.warp = null; } /** * 入口 * @param warp 操作区域 jquery节点 */ customerimg.prototype.start = function (warp) { var info,me,warpbox; me = this; this.issupport = this.__issupport(); if(!this.issupport) { info = $('<p>你的浏览器不支持自定义头像,可更换高版本的浏览器自定义头像</p>'); $('body').html(info); return this; } //判断操作区域示范存在 if(warp && warp.length > 0){ this.warp = warp; }else{ return this; } //预览 preview.start(warp,shear.start.bind(shear,warp)); this.previewbox = warp.find('#preview'); //确定 warp .find('#submit') .unbind('click') .on('click',me.__submit.bind(me)); }; /** * 提交 * @private */ customerimg.prototype.__submit = function () { var cvsmove,data,fd; cvsmove = this.previewbox.find('#cvsmove'); data = cvsmove[0].todataurl('image/jpg',1); fd = { 'customerimg':data }; ajax.upload(fd); }; /** * 判断是否支持自定义头像 * @returns {boolean} * @private */ customerimg.prototype.__issupport = function () { var canvas,context; canvas= document.createelement('canvas'); if(typeof filereader === 'function'&& canvas.getcontext && canvas.todataurl){ return true; }else{ return false; } }; var customerimg = new customerimg(); module.exports = customerimg;
preview.js
/** * created by star on 2017/3/7. */ var $ = require('jquery'); /** * 预览类 * @constructor */ function preview() { this.boxelem = null; this.callback = null; this.type = null; } /** * 入口 * @param boxelem 操作区域 * @param callback 预览结束的回调函数 */ preview.prototype.start = function (boxelem,callback) { var choosefile,me; me = this; if(! boxelem || boxelem.length <= 0) return this; this.boxelem = boxelem; if(typeof callback === 'function'){ this.callback = callback; } if(this.__issupport()){ choosefile = boxelem.find('input[type="file"]'); choosefile .on('change',me.filechange.bind(me)) } }; /** * 选择图片的事件处理程序 * @param event */ preview.prototype.filechange = function (event) { var target,reader,file,me,type; target = event.target; me = this; file = target.files[0]; type = file.type; this.type = type; if(type !== 'image/png' && type !== 'image/jpg' && type !== 'image/jpeg'){ alert('文件格式不正确'); return this; } reader = new filereader(); if(file){ reader.readasdataurl(file); } reader.onload = function () { me.show(reader); } }; /** * 显示从本地选择的图片 * @param reader filereader对象 */ preview.prototype.show = function (reader) { var preview,img,me; preview = this.boxelem.find('#preview'); img = preview.find('#preimg'); me = this; if(img.length <= 0){ preview.append($('<img id="preimg">')); } img = preview.find('#preimg'); //确保图片加载完成后再执行回调 img.on('load',function () { if(me.callback){ me.callback(me.type); } }); img.attr('src',reader.result); }; /** * 是否支持预览 * @returns {boolean} * @private */ preview.prototype.__issupport = function () { return typeof filereader === 'function'; }; var preview = new preview(); module.exports = preview;
shear.js
var $ = require('jquery'); //由于要使用jquery-ui,所以将$暴露到window上。 window.$ = $; require('./jquery-ui.min.js'); /** * 切割 * @constructor */ function shear() { this.previewbox = null; this.cvsmove = null; this.maxw = 200; this.maxh = 200; this.thum = null; this.filetype = 'image/jpeg'; } /** * 入口 * @param previewbox 预览元素的父元素 * @param filetype 裁剪的图片的类型 如:'image/jpg' * @returns {shear} */ shear.prototype.start = function (previewbox,filetype) { if(!arguments.length) return this; var me = this; this.previewbox = previewbox; if(filetype){ this.filetype = filetype; } this.thum = this.previewbox.find('#thum'); this.cvsmove = this.previewbox.find('#cvsmove'); this.showcanvas(); return this; }; /** * 显示出canvas */ shear.prototype.showcanvas = function () { var preimg,h,w,me,cvsh,cvsw,rateh,ratew,naturalh,naturalw,preview; me = this; preimg = this.previewbox.find('#preimg'); preview = this.previewbox.find('#preview'); naturalh = preimg[0].naturalheight; naturalw = preimg[0].naturalwidth; //将canvas显示出来 this.cvsmove.show(); //将canvas置于(0,0) this.cvsmove .css({ "left":'0', 'top':'0' }); h = preimg.height(); w = preimg.width(); //规定裁剪出的图片尺寸为200px*200px //要保证裁剪的图片不变形 if(h < this.maxh || w < this.maxw){ this.cvsmove[0].width = cvsw = math.min(h,w); this.cvsmove[0].height = cvsh = math.min(h,w); }else{ this.cvsmove[0].width= cvsw = this.maxw; this.cvsmove[0].height= cvsh = this.maxh; } rateh = h/naturalh; ratew = w/naturalw; this.__drawimg(preimg,0,0,cvsw/ratew,cvsh/rateh,0,0,cvsw,cvsh); //使用jquery-ui中的功能使canvas可以移动 this.cvsmove.draggable( { containment: "parent", drag:function (event,ui) { var left,top; left = ui.position.left; top = ui.position.top; //canvas每次移动都有从新绘制图案 me.__drawimg(preimg,left/ratew,top/rateh,cvsw/ratew,cvsh/rateh,0,0,cvsw,cvsh); } } ) }; /** * 在canvas上显示图片 * @param myimg 要显示的图片节点 * @param sx 图片的起点在原图片上的x坐标 * @param sy 图片的起点在原图上的y坐标 * @param sw 在原图上的宽度 * @param sh 在原图上的高度 * @param dx 起点在canvas上的x坐标 * @param dy 起点在canvas上的y坐标 * @param dw 在canvas上的宽度 * @param dh 在canvas上的高度 * @private */ shear.prototype.__drawimg = function (myimg,sx,sy,sw,sh,dx,dy,dw,dh) { var cxt,thum,me; me = this; cxt = this.cvsmove[0].getcontext('2d'); cxt.drawimage(myimg[0],sx,sy,sw,sh,dx,dy,dw,dh); thum = this.thum; //将canvas上的图案显示到右侧 thum .attr('src',this.cvsmove[0].todataurl(me.filetype,1)) .width(this.maxw) .height(this.maxh) }; var shear = new shear(); module.exports = shear;
ajax.js
var $ = require('jquery'); function ajax() { } /** * 上传图片数据 */ ajax.prototype.upload = function (data) { $.ajax({ type:'post', data:data, datatype:'json', url:'/test/php/upload.php', success:function (result) { if(result.status){ location.reload(); }else{ alert(result.msg); } } }); }; var ajax = new ajax(); module.exports = ajax;
最后在另一个文件中,调用customerimg对象的start方法
var $ = require('jquery'); var customerimg =require('./customerimg.js'); customerimg.start($('#warp'));
webpack的配置文件如下:
var webpack = require('webpack'); module.exports = { entry:{ 'customerimg':'./js/test.js', 'jquery':['jquery'] }, output:{ filename:'[name].js', library:'jquery', librarytarget:'umd' }, plugins:[ new webpack.optimize.commonschunkplugin({ name:'jquery', filename:'jquery.js' }) ] };
效果:
4.php代码
if(!empty($_post) && isset($_post['customerimg'])){ $img = $_post['customerimg']; $imgdata = explode(',', $img); $uniname = md5 ( uniqid ( microtime ( true ), true ) ); $a = file_put_contents('./../uploads/'.$uniname.'.jpg', base64_decode($imgdata[1])); }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
基于asp.net实现图片在线上传并在线裁剪功能
-
vue-cli结合Element-ui基于cropper.js封装vue实现图片裁剪组件功能
-
cropper js基于vue的图片裁剪上传功能的实现代码
-
基于HTML5+JS实现本地图片裁剪并上传功能
-
vue.js 实现图片本地预览 裁剪 压缩 上传功能
-
基于cropper.js封装vue实现在线图片裁剪组件功能
-
基于Html5 canvas实现裁剪图片和马赛克功能及又拍云上传图片 功能
-
基于asp.net实现图片在线上传并在线裁剪功能
-
vue-cli结合Element-ui基于cropper.js封装vue实现图片裁剪组件功能
-
vue.js 实现图片本地预览 裁剪 压缩 上传功能