首页 > 编程 > JavaScript > 正文

基于HTML5+JS实现本地图片裁剪并上传功能

2019-11-19 17:03:30
字体:
来源:转载
供稿:网友

最近做了一个项目,这个项目中需要实现的一个功能是:用户自定义头像(用户在本地选择一张图片,在本地将图片裁剪成满足系统要求尺寸的大小)。这个功能的需求是:头像最初剪切为一个正方形。如果选择的图片小于规定的头像要求尺寸,那么这整张图片都会作为头像。如果大于规定的尺寸,那么用户可以选择要裁剪的区域。用户点击确定按钮,就将裁剪得到的图片数据发送到服务器,在后端将图片数据保存成一个文件。

要完成上述功能,涉及到的知识有: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]));}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表