php在线拍照裁切,基于cropper.js封装vue实现在线图片裁剪组件的功能

这篇文章主要介绍了基于cropper.js封装vue实现在线图片裁剪组件功能,非常不错,具有参考借鉴价值,需要的朋友可以参考下

效果图如下所示,

432f44c8a80cdd5cdc185846c636c90e.png

github:demo下载

cropper.js

github:cropper.js

官网(demo)

cropper.js 安装npm或bower安装

npm install cropper

# or

bower install cropper

clone下载:下载地址

git clone https://github.com/fengyuanchen/cropper.git

引用cropper.js

主要引用cropper.js跟cropper.css两个文件

注意:必须先引入jquery文件,才能使用cropper.js插件

简单使用

构建截图所要用到的p容器

![](picture.jpg)

添加容器的样式,让img填充满整个容器(很重要)

/* Limit image width to avoid overflow the container */

img {

max-width: 100%; /* This rule is very important, please do not ignore this! */

}

调用cropper.js方法,初始化截图控件

$('#image').cropper({

aspectRatio: 16 / 9,

crop: function(e) {

// Output the result data for cropping image.

console.log(e.x);

console.log(e.y);

console.log(e.width);

console.log(e.height);

console.log(e.rotate);

console.log(e.scaleX);

console.log(e.scaleY);

}

});

其他详细api请参考:github:cropper.js

封装成vue组件

封装成vue组件中需解决的问题cropper.js相关

模拟input框点击选择图片并对选择的图片进行格式、大小限制

重新选择图片裁剪

确认裁剪并获取base64格式的图片信息vue相关

非父子组件之间的通信问题

模拟input框点击选择图片并对选择的图片进行格式、大小限制

构建一个隐藏的input标签,然后模拟点击此input,从而达到能选择图片的功能

//模拟点击

document.getElementById('myCropper-input').click();

给input绑定一个监听内容变化的方法,拿到上传的文件,并进行格式、大小校验

// imgCropperData: {

// accept: 'image/gif, image/jpeg, image/png, image/bmp',

// }

handleFile (e) {

let _this = this;

let inputDOM = this.$refs.inputer;

// 通过DOM取文件数据

_this.file = inputDOM.files[0];

// 判断文件格式

if (_this.imgCropperData.accept.indexOf(_this.file.type) == -1) {

_this.$Modal.error({

title: '格式错误',

content: '您选择的图片格式不正确!'

});

return;

}

// 判断文件大小限制

if (_this.file.size > 5242880) {

_this.$Modal.error({

title: '超出限制',

content: '您选择的图片过大,请选择5MB以内的图片!'

});

return;

}

var reader = new FileReader();

// 将图片将转成 base64 格式

reader.readAsDataURL(_this.file);

reader.onload = function () {

_this.imgCropperData.imgSrc = this.result;

_this.initCropper();

}

}

重新选择图片裁剪

当第一次选择图片之后,肯定会面临需要重选图片的问题,那么就会面临如何替换掉裁剪框中的图片,上面的步骤选择了图片后通过FileRender()方法拿到了图片的主要信息,现在就需要重新构建裁剪框就可以解决问题了,查看cropper.js给出的官方demo,发现官方是使用动态添加裁剪容器的方法,进行操作的,这里我们仿照官方进行实现。

// 初始化剪切

initCropper () {

let _this = this;

// 初始化裁剪区域

_this.imgObj = $('![](' + _this.imgCropperData.imgSrc + ')');

let $avatarPreview = $('.avatar-preview');

$('#myCropper-workspace').empty().html(_this.imgObj);

_this.imgObj.cropper({

aspectRatio: _this.proportionX / _this.proportionY,

preview: $avatarPreview,

crop: function(e) {

}

});

}

确认裁剪并获取base64格式的图片信息

let $imgData = _this.imgObj.cropper('getCroppedCanvas')

imgBase64Data = $imgData.toDataURL('image/png');

构造用于上传的数据

// 构造上传图片的数据

let formData = new FormData();

// 截取字符串

let photoType = imgBase64Data.substring(imgBase64Data.indexOf(",") + 1);

//进制转换

const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => {

const byteCharacters = atob(b64Data);

const byteArrays = [];

for(let offset = 0; offset < byteCharacters.length; offset += sliceSize) {

const slice = byteCharacters.slice(offset, offset + sliceSize);

const byteNumbers = new Array(slice.length);

for(let i = 0; i < slice.length; i++) {

byteNumbers[i] = slice.charCodeAt(i);

}

const byteArray = new Uint8Array(byteNumbers);

byteArrays.push(byteArray);

}

const blob = new Blob(byteArrays, {

type: contentType

});

return blob;

}

const contentType = 'image/jepg';

const b64Data2 = photoType;

const blob = b64toBlob(b64Data2, contentType);

formData.append("file", blob, "client-camera-photo.png")

formData.append("type", _this.imgType)

非父子组件之间的通信问题在之前的项目中,常用到父子组件之间的通信传参,一般用两种方法在router里面放置参数,然后通过调用route.params.xxx或者route.query.xxx进行获取

通过props进行通信

这里我们使用eventBus进行组件之间的通信

步骤

1.声明一个bus组件用于B组件把参数传递给A组件

//bus.js

import Vue from 'vue';

export default new Vue();

2.在A组件中引用bus组件,并实时监听其参数变化

// A.vue

import Bus from '../../components/bus/bus.js'

export default {

components: { Bus },

data () {},

created: function () {

Bus.$on('getTarget', imgToken => {

var _this = this;

console.log(imgToken);

...

});

}

}

3.B组件中同样引用bus组件,来把参数传给A组件

// B.vue

// 传参

Bus.$emit('getTarget', imgToken);

参考:

vue-$on

vue-$emit

vue.js之路(4)——vue2.0s中eventBus实现兄弟组件通信

vue选图截图插件完整代码

请点击按钮选择图片进行裁剪

![](!imgCropperData.imgUploadSrc ? '/images/thumbnail/thumbnail-img.jpg' : imgCropperData.imgUploadSrc)

![](!imgCropperData.imgUploadSrc ? '/images/thumbnail/thumbnail-img.jpg' : imgCropperData.imgUploadSrc)

![](!imgCropperData.imgUploadSrc ? '/images/thumbnail/thumbnail-img.jpg' : imgCropperData.imgUploadSrc)

选择图片

确认

var ezjsUtil = Vue.ezjsUtil;

import Bus from './bus/bus.js'

export default {

components: { Bus },

props: {

imgType: {

type: String

},

proportionX: {

type: Number

},

proportionY: {

type: Number

}

},

data () {

return {

imgCropperData: {

accept: 'image/gif, image/jpeg, image/png, image/bmp',

maxSize: 5242880,

file: null, //上传的文件

imgSrc: '', //读取的img文件base64数据流

imgUploadSrc: '', //裁剪之后的img文件base64数据流

},

imgObj: null,

hasSelectImg: false,

cropperLoading: false,

isShort: false,

}

},

created: function () {

let _this = this;

},

mounted: function () {

let _this = this;

// 初始化预览区域

let maxWidthNum = Math.floor(300 / _this.proportionX);

let previewWidth = maxWidthNum * _this.proportionX;

let previewHeight = maxWidthNum * _this.proportionY;

if (previewWidth / previewHeight <= 1.7) {

previewWidth = previewWidth / 2;

previewHeight = previewHeight / 2;

_this.isShort = true;

}

// 设置最大预览容器的宽高

$('.myCropper-preview-1').css('width', previewWidth + 'px');

$('.myCropper-preview-1').css('height', previewHeight + 'px');

// 设置中等预览容器的宽高

$('.myCropper-container .myCropper-preview .myCropper-preview-2').css('width',( previewWidth / 2) + 'px');

$('.myCropper-container .myCropper-preview .myCropper-preview-2').css('height', (previewHeight / 2) + 'px');

// 设置最小预览容器的宽高

$('.myCropper-container .myCropper-preview .myCropper-preview-3').css('width',( previewWidth / 4) + 'px');

$('.myCropper-container .myCropper-preview .myCropper-preview-3').css('height', (previewHeight / 4) + 'px');

},

methods: {

// 点击选择图片

btnClick () {

let _this = this;

// 模拟input点击选择文件

document.getElementById('myCropper-input').click();

},

// 选择之后的回调

handleFile (e) {

let _this = this;

let inputDOM = this.$refs.inputer;

// 通过DOM取文件数据

_this.file = inputDOM.files[0];

// 判断文件格式

if (_this.imgCropperData.accept.indexOf(_this.file.type) == -1) {

_this.$Modal.error({

title: '格式错误',

content: '您选择的图片格式不正确!'

});

return;

}

// 判断文件大小限制

if (_this.file.size > 5242880) {

_this.$Modal.error({

title: '超出限制',

content: '您选择的图片过大,请选择5MB以内的图片!'

});

return;

}

var reader = new FileReader();

// 将图片将转成 base64 格式

reader.readAsDataURL(_this.file);

reader.onload = function () {

_this.imgCropperData.imgSrc = this.result;

_this.initCropper();

}

},

// 初始化剪切

initCropper () {

let _this = this;

// 初始化裁剪区域

_this.imgObj = $('![](' + _this.imgCropperData.imgSrc + ')');

let $avatarPreview = $('.avatar-preview');

$('#myCropper-workspace').empty().html(_this.imgObj);

_this.imgObj.cropper({

aspectRatio: _this.proportionX / _this.proportionY,

preview: $avatarPreview,

crop: function(e) {

}

});

_this.hasSelectImg = true;

},

// 确认

crop_ok () {

let _this = this, imgToken = null, imgBase64Data = null;

// 判断是否选择图片

if (_this.hasSelectImg == false) {

_this.$Modal.error({

title: '裁剪失败',

content: '请选择图片,然后进行裁剪操作!'

});

return false;

}

// 确认按钮不可用

_this.cropperLoading = true;

let $imgData = _this.imgObj.cropper('getCroppedCanvas')

imgBase64Data = $imgData.toDataURL('image/png');

// 构造上传图片的数据

let formData = new FormData();

// 截取字符串

let photoType = imgBase64Data.substring(imgBase64Data.indexOf(",") + 1);

//进制转换

const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => {

const byteCharacters = atob(b64Data);

const byteArrays = [];

for(let offset = 0; offset < byteCharacters.length; offset += sliceSize) {

const slice = byteCharacters.slice(offset, offset + sliceSize);

const byteNumbers = new Array(slice.length);

for(let i = 0; i < slice.length; i++) {

byteNumbers[i] = slice.charCodeAt(i);

}

const byteArray = new Uint8Array(byteNumbers);

byteArrays.push(byteArray);

}

const blob = new Blob(byteArrays, {

type: contentType

});

return blob;

}

const contentType = 'image/jepg';

const b64Data2 = photoType;

const blob = b64toBlob(b64Data2, contentType);

formData.append("file", blob, "client-camera-photo.png")

formData.append("type", _this.imgType)

// ajax上传

$.ajax({

url: _this.$nfs.uploadUrl,

method: 'POST',

data: formData,

// 默认为true,设为false后直到ajax请求结束(调完回掉函数)后才会执行$.ajax(...)后面的代码

async: false,

// 下面三个,因为直接使用FormData作为数据,contentType会自动设置,也不需要jquery做进一步的数据处理(序列化)。

cache: false,

contentType: false,

processData: false,

type: _this.imgType,

success: function(res) {

let imgToken = res.data.token;

_this.cropperLoading = false;

// 传参

Bus.$emit('getTarget', imgToken);

},

error: function(error) {

_this.cropperLoading = false;

_this.$Modal.error({

title: '系统错误',

content: '请重新裁剪图片进行上传!'

});

}

});

},

}

}

.myCropper-container {

height: 400px;

}

.myCropper-container #myCropper-input {

width: 0px;

height: 0px;

}

.myCropper-container #myCropper-workspace {

width: 500px;

height: 400px;

border: 1px solid #dddee1;

float: left;

}

// 裁剪图片未选择图片的提示文字

.myCropper-container #myCropper-workspace .myCropper-words{

text-align: center;

font-size: 18px;

padding-top: 180px;

}

// 裁剪图片的预览区域

.myCropper-container .myCropper-preview-long {

width: 300px;

}

.myCropper-container .myCropper-preview-short {

width: 200px;

}

.myCropper-container .myCropper-preview {

float: left;

height: 400px;

margin-left: 10px;

}

.myCropper-container .myCropper-preview .myCropper-preview-1 {

border-radius: 5px;

overflow: hidden;

border: 1px solid #dddee1;

box-shadow: 3px 3px 3px #dddee1;

img {

width: 100%;

height: 100%;

}

}

.myCropper-container .myCropper-preview .myCropper-preview-2 {

margin-top: 20px;

border-radius: 5px;

overflow: hidden;

border: 1px solid #dddee1;

box-shadow: 3px 3px 3px #dddee1;

img {

width: 100%;

height: 100%;

}

}

.myCropper-container .myCropper-preview .myCropper-preview-3 {

margin-top: 20px;

border-radius: 5px;

overflow: hidden;

border: 1px solid #dddee1;

box-shadow: 3px 3px 3px #dddee1;

img {

width: 100%;

height: 100%;

}

}

// 按钮

.myCropper-btn {

float: left;

margin-top: 20px;

margin-right: 10px;

}

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值