| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571 |
- /**
- * name : vue 的图片裁减压缩处理
- * author : 陈威
- * date : 2017/6/20
- * dependence :
- * cropper 第三方的一个裁剪库
- * exif 获取图片源信息,解决ios图片旋转的问题
- * */
- import Cropper from 'cropperjs'
- // import Exif from 'exif-js'
- export default {
- install( Vue ){
- //初始化方法
- Vue.prototype.initilize = function( opt ){
- let self = this;
- self.botNav = false; //隐藏底部导航
- this.options = opt;
- //创建dom
- this.createElement();
- this.resultObj = opt.resultObj;
- //初始化裁剪对象
- this.cropper = new Cropper( this.preview , {
- aspectRatio : opt.aspectRatio || 1 ,
- autoCropArea : opt.autoCropArea || 0.8 ,
- viewMode : 1,
- guides : opt.aspectRatio == 'Free' ? false : true ,
- cropBoxResizable : opt.aspectRatio == 'Free' ? false : true ,
- cropBoxMovable : opt.aspectRatio == 'Free' ? false : true ,
- dragCrop : opt.aspectRatio == 'Free' ? false : true ,
- background : false,
- checkOrientation : true ,
- checkCrossOrigin : true ,
- zoomable : false,
- zoomOnWheel : false ,
- center : false ,
- toggleDragModeOnDblclick : false ,
- ready : function () {
- // console.log(self.cropper.rotate(90))
- if( opt.aspectRatio == 'Free' ){
- let cropBox = self.cropper.cropBox;
- cropBox.querySelector('span.cropper-view-box').style.outline = 'none';
- self.cropper.disable();
- }
- }
- });
- }
- //创建一些必要的DOM,用于图片裁剪
- Vue.prototype.createElement = function () {
- //初始化图片为空对象
- this.preview = null;
- let str = '<div><img id="clip_image" src="originUrl"></div><button type="button" id="cancel_clip">取消</button><button type="button" id="clip_button">确定</button>';
- str+= '<div class="crop_loading"><div class="crop_content"><img style="margin: 0 auto" src="./static/loading.gif"><div class="crop_text">图片上传中</div></div></div>';
- str+= '<div class="crop_success"><div class="crop_success_text">上传成功</div></div></div>';
- let body = document.getElementsByTagName('body')[0];
- this.reagion = document.createElement('div');
- this.reagion.id = 'clip_container';
- this.reagion.className = 'container';
- this.reagion.innerHTML = str;
- //添加创建好的DOM元素
- body.appendChild(this.reagion);
- this.preview = document.getElementById('clip_image');
- //绑定一些方法
- this.initFunction();
- }
- //初始化一些函数绑定
- Vue.prototype.initFunction = function () {
- let self =this;
- this.clickBtn = document.getElementById('clip_button');
- this.cancelBtn = document.getElementById('cancel_clip');
- //确定事件
- this.addEvent( this.clickBtn , 'click' , function () {
- self.crop();
- })
- //取消事件
- this.addEvent( this.cancelBtn , 'click' , function () {
- self.destoried();
- })
- //清空input的值
- this.addEvent( this.fileObj , 'click' , function () {
- this.value = '';
- })
- }
- //外部接口,用于input['file']对象change时的调用
- Vue.prototype.clip = function ( e , opt ) {
- console.log(Vue.prototype.clip)
- let self = this;
- this.fileObj = e.srcElement;
- let files = e.target.files || e.dataTransfer.files;
- if (!files.length) return false; //不是图片直接返回
- //调用初始化方法
- this.initilize( opt );
- //获取图片文件资源
- this.picValue = files[0];
- //去获取拍照时的信息,解决拍出来的照片旋转问题
- // Exif.getData( files[0] , function(){
- // self.Orientation = Exif.getTag( files[0], 'Orientation');
- // console.log(self.Orientation)
- // });
- // console.log(this.picValue)
-
- //调用方法转成url格式
- this.originUrl = this.getObjectURL( this.picValue );
- //每次替换图片要重新得到新的url
- if(this.cropper){
- this.cropper.replace(this.originUrl);
- }
- return this.picValue
- }
- //图片转码方法
- Vue.prototype.getObjectURL = function(file) {
- let url = null ;
- // console.log(file)
- if (window.createObjectURL!=undefined) { // basic
- url = window.createObjectURL(file) ;
- } else if (window.URL!=undefined) { // mozilla(firefox)
- url = window.URL.createObjectURL(file) ;
- } else if (window.webkitURL!=undefined) { // webkit or chrome
- url = window.webkitURL.createObjectURL(file) ;
- }
- return url ;
- }
- //点击确定进行裁剪
- Vue.prototype.crop = function () {
- let self = this;
- let image = new Image();
- let croppedCanvas;
- let roundedCanvas;
- // Crop
- document.querySelector('.crop_loading').style.display = 'block';
- setTimeout(function () {
- croppedCanvas = self.cropper.getCroppedCanvas();
- // Round
- roundedCanvas = self.getRoundedCanvas(croppedCanvas);
- let imgData = roundedCanvas.toDataURL();
- image.src = imgData;
- //判断图片是否大于100k,不大于直接上传,反之压缩
- if( imgData.length < (100 * 1024) ){
- self.resultObj.src = imgData;
- //图片上传
- self.postImg( imgData );
- // console.log(imgData)
- localStorage.setItem('ba64dataA',imgData)
- // console.log(imgData)
- }else{
- image.onload = function () {
- //压缩处理
- let data = self.compress( image , self.Orientation );
- self.resultObj.src = data;
- //图片上传
- self.postImg( data );
- localStorage.setItem('ba64dataA',data)
- }
- }
- },20)
- }
- //获取裁剪图片资源
- Vue.prototype.getRoundedCanvas = function(sourceCanvas) {
- let canvas = document.createElement('canvas');
- let context = canvas.getContext('2d');
- let width = sourceCanvas.width;
- let height = sourceCanvas.height;
- canvas.width = width;
- canvas.height = height;
- context.imageSmoothingEnabled = true;
- context.drawImage(sourceCanvas, 0, 0, width, height);
- context.globalCompositeOperation = 'destination-in';
- context.beginPath();
- context.rect(0 , 0 , width , height );
- context.fill();
- return canvas;
- }
- //销毁原来的对象
- Vue.prototype.destoried = function () {
- let self = this;
- this.loadingShow = false
- //移除事件
- this.removeEvent( this.clickBtn , 'click' , null );
- this.removeEvent( this.cancelBtn , 'click' , null );
- this.removeEvent( this.fileObj , 'click' , null );
- //移除裁剪框
- this.reagion.parentNode.removeChild(this.reagion);
- //销毁裁剪对象
- this.cropper.destroy();
- this.cropper = null;
- }
- //图片上传
- Vue.prototype.postImg = function( imageData ) {
- //这边写图片的上传
- let self = this;
- self.destoried();
- window.setTimeout( function () {
- document.querySelector('.crop_loading').style.display = 'none';
- document.querySelector('.crop_success').style.display = 'block';
- //裁剪完后摧毁对象
- self.destoried();
- },3000)
- this.loadingShow = true;
- // 判断是用户是选择的病害还是昆虫
- if (localStorage.getItem('insect') !== null) {
- //计时器
- // var totalTime = 10;
- // let timer = window.setInterval(() => {
- // totalTime--;
- // console.log(totalTime)
- // if (totalTime <= 0) {
- // window.clearInterval(timer);
- // this.$message({
- // type: "error",
- // message: "识别失败,您可以尝试图片上传!"
- // });
- // this.loadingShow = false;
- // // 识别失败发送记录
- // if (localStorage.getItem("insect") !== null) {
- // var classify = "insect";
- // } else if (localStorage.getItem("plant") !== null) {
- // var classify = "plant";
- // }
- // let form = new FormData();
- // form.append("file", this.picValue);
- // form.append("name", "1");
- // form.append("prevention", "");
- // form.append("course", "");
- // form.append("ret", classify);
- // form.append('img_urls', '');
- // form.append('addr', '');
- // form.append('lng', '');
- // form.append('lat', '');
- // this
- // .$axios({
- // method: "post",
- // url: "/record",
- // data: form,
- // headers: {
- // "Content-Type": "multipart/form-data"
- // }
- // })
- // .then(res => {
- // alert('已传输识别失败数据')
- // console.log('已传输识别失败数据')
- // })
- // .catch(error => {
- // alert('传输失败')
- // console.log('传输失败')
- // });
- // // const timeA = setInterval(() => {
- // // location.reload();
- // // }, 1500);
- // }
- // }, 1000);
- let form = new FormData();
- form.append("img_addr", this.picValue);
- this.$axios({
- method: "post",
- url: "/app_insect",
- anync: true,
- data: form,
- headers: {
- "Content-Type": "multipart/form-data"
- }
- }).then(res => {
- self.botNav = true; //隐藏底部导航
- // window.clearInterval(timer); //销毁计时器
- if (
- res.data.msg === "识别失败_!" ||
- res.data.msg === "" ||
- res.data.data === null
- ) {
- this.$message({
- type: "error",
- message: "识别失败!"
- });
- this.$router.push({name: 'show',params: {data: form.get('img_addr')}})
- localStorage.setItem('recordID', '1')
- this.loadingShow = false;
- } else {
- this.$notify({
- title: "成功",
- message: "识别成功",
- type: "success"
- });
- localStorage.setItem("axiosData", JSON.stringify(res.data.data[0]));
- }
- this.$router.push({name: 'show',params: {data: form.get('img_addr')}})
- localStorage.setItem('recordID', '1')
- this.loadingShow = false;
- }).catch(error => {
- // window.clearInterval(timer); //销毁计时器
- this.$message({
- type: "error",
- message: "识别失败!"
- });
- this.$router.push({name: 'show',params: {data: form.get('img_addr')}})
- localStorage.setItem('recordID', '1')
- this.loadingShow = false;
- })
- } else if (localStorage.getItem('plant') !== null) {
- //计时器
- // var totalTime = 10;
- // let timer = window.setInterval(() => {
- // totalTime--;
- // console.log(totalTime)
- // if (totalTime <= 0) {
- // window.clearInterval(timer);
- // this.$message({
- // type: "error",
- // message: "识别失败,您可以尝试图片上传!"
- // });
- // this.loadingShow = false;
- // // 识别失败发送记录
- // if (localStorage.getItem("insect") !== null) {
- // var classify = "insect";
- // } else if (localStorage.getItem("plant") !== null) {
- // var classify = "plant";
- // }
- // let form = new FormData();
- // form.append("file", this.picValue);
- // form.append("name", "1");
- // form.append("prevention", "");
- // form.append("course", "");
- // form.append("ret", classify);
- // form.append('img_urls', '');
- // form.append('addr', '');
- // form.append('lng', '');
- // form.append('lat', '');
- // this
- // .$axios({
- // method: "post",
- // url: "/record",
- // data: form,
- // headers: {
- // "Content-Type": "multipart/form-data"
- // }
- // })
- // .then(res => {
- // console.log('已传输识别失败数据')
- // alert('已传输识别失败数据')
- // })
- // .catch(error => {
- // alert('已传输识别失败数据')
- // console.log('传输失败')
- // });
-
- // // const timeA = setInterval(() => {
- // // location.reload();
- // // }, 1500);
- // }
- // }, 1000);
- let form = new FormData();
- form.append("img_addr", this.picValue);
- this.$axios({
- method: "post",
- url: "/app_plant",
- anync: true,
- data: form,
- headers: {
- "Content-Type": "multipart/form-data"
- }
- }).then(res => {
- self.botNav = true; //隐藏底部导航
- // window.clearInterval(timer); //销毁计时器
- if (
- res.data.msg === "识别失败_!" ||
- res.data.msg === "" ||
- res.data.data === null
- ) {
- this.$message({
- type: "error",
- message: "识别失败!"
- });
- this.loadingShow = false;
- this.$router.push({name: 'show',params: {data: form.get('img_addr')}})
- localStorage.setItem('recordID', '1')
- } else {
- this.$notify({
- title: "成功",
- message: "识别成功",
- type: "success"
- });
- localStorage.setItem("axiosData", JSON.stringify(res.data.data[0]));
- }
- this.$router.push({name: 'show',params: {data: form.get('img_addr')}})
- localStorage.setItem('recordID', '1')
- this.loadingShow = false;
- }).catch(error => {
- // window.clearInterval(timer); //销毁计时器
- this.$message({
- type: "error",
- message: "识别失败aaaaaaa!"
- });
- this.$router.push({name: 'show',params: {data: form.get('img_addr')}})
- localStorage.setItem('recordID', '1')
- this.loadingShow = false;
- })
- }
-
- }
- //图片旋转
- Vue.prototype.rotateImg = function( img , direction , canvas ) {
- //最小与最大旋转方向,图片旋转4次后回到原方向
- const min_step = 0;
- const max_step = 3;
- if (img == null )return;
- //img的高度和宽度不能在img元素隐藏后获取,否则会出错
- let height = img.height;
- let width = img.width;
- let step = 2;
- if (step == null) {
- step = min_step;
- }
- if ( direction == 'right') {
- step++;
- //旋转到原位置,即超过最大值
- step > max_step && (step = min_step);
- } else {
- step--;
- step < min_step && (step = max_step);
- }
- //旋转角度以弧度值为参数
- let degree = step * 90 * Math.PI / 180;
- let ctx = canvas.getContext('2d');
- switch (step) {
- case 0:
- canvas.width = width;
- canvas.height = height;
- ctx.drawImage(img, 0, 0);
- break;
- case 1:
- canvas.width = height;
- canvas.height = width;
- ctx.rotate(degree);
- ctx.drawImage(img, 0, -height);
- break;
- case 2:
- canvas.width = width;
- canvas.height = height;
- ctx.rotate(degree);
- ctx.drawImage(img, -width, -height);
- break;
- case 3:
- canvas.width = height;
- canvas.height = width;
- ctx.rotate(degree);
- ctx.drawImage(img, -width, 0);
- break;
- }
- }
- //图片压缩
- Vue.prototype.compress = function ( img , Orientation ) {
- let canvas = document.createElement("canvas");
- let ctx = canvas.getContext('2d');
- //瓦片canvas
- let tCanvas = document.createElement("canvas");
- let tctx = tCanvas.getContext("2d");
- let initSize = img.src.length;
- let width = img.width;
- let height = img.height;
- //如果图片大于四百万像素,计算压缩比并将大小压至400万以下
- let ratio;
- if ((ratio = width * height / 4000000) > 1) {
- console.log("大于400万像素")
- ratio = Math.sqrt(ratio);
- width /= ratio;
- height /= ratio;
- } else {
- ratio = 1;
- }
- canvas.width = width;
- canvas.height = height;
- // 铺底色
- // ctx.fillStyle = "#fff";
- ctx.fillStyle = "#000";
- ctx.fillRect(0, 0, canvas.width, canvas.height);
- //如果图片像素大于100万则使用瓦片绘制
- let count;
- if ((count = width * height / 1000000) > 1) {
- count = ~~(Math.sqrt(count) + 1); //计算要分成多少块瓦片
- // 计算每块瓦片的宽和高
- let nw = ~~(width / count);
- let nh = ~~(height / count);
- tCanvas.width = nw;
- tCanvas.height = nh;
- for (let i = 0; i < count; i++) {
- for (let j = 0; j < count; j++) {
- tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
- ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
- }
- }
- } else {
- ctx.drawImage(img, 0, 0, width, height);
- }
- //修复ios上传图片的时候 被旋转的问题
- if( Orientation != "" && Orientation != 1){
- switch(Orientation){
- case 6://需要顺时针(向左)90度旋转
- this.rotateImg(img,'left',canvas);
- break;
- case 8://需要逆时针(向右)90度旋转
- this.rotateImg(img,'right',canvas);
- break;
- case 3://需要180度旋转
- this.rotateImg(img,'right',canvas);//转两次
- this.rotateImg(img,'right',canvas);
- break;
- }
- }
- //进行最小压缩
- let ndata = canvas.toDataURL( 'image/jpeg' , 0.1);
- // console.log('压缩前:' + initSize);
- // console.log('压缩后:' + ndata.length);
- // console.log('压缩率:' + ~~(100 * (initSize - ndata.length) / initSize) + "%");
- tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
- // console.log(ndata)
- return ndata;
- }
- //添加事件
- Vue.prototype.addEvent = function ( obj , type , fn ) {
- if( obj.addEventListener ){
- obj.addEventListener( type , fn , false );
- }else{
- obj.attachEvent( 'on' + type , fn );
- }
- }
- //移除事件
- Vue.prototype.removeEvent = function ( obj , type , fn ) {
- if( obj.removeEventListener ){
- obj.removeEventListener( type , fn , false );
- }else{
- obj.detachEvent( 'on' + type , fn );
- }
- }
- }
- }
|