100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 微信小程序头像上传以及剪切(使用插件image-cropper)

微信小程序头像上传以及剪切(使用插件image-cropper)

时间:2023-06-15 21:54:07

相关推荐

微信小程序头像上传以及剪切(使用插件image-cropper)

image-cropper插件引入后,会有很多默认功能,所有需求基本都可以满足;

/wx-plugin/image-cropper

第一步:在组件中添加image-cropper

image-cropper.wxml文件

<view class='image-cropper' catchtouchmove='_preventTouchMove'><view class='main' bindtouchend="_cutTouchEnd" bindtouchstart="_cutTouchStart" bindtouchmove="_cutTouchMove" bindtap="_click"><view class='content'><view class='content_top bg_gray {{_flag_bright?"":"bg_black"}}' style="height:{{cut_top}}px;transition-property:{{_cut_animation?'':'background'}}"></view><view class='content_middle' style="height:{{height}}px;"><view class='content_middle_left bg_gray {{_flag_bright?"":"bg_black"}}' style="width:{{cut_left}}px;transition-property:{{_cut_animation?'':'background'}}"></view><view class='content_middle_middle' style="width:{{width}}px;height:{{height}}px;transition-duration: .3s;transition-property:{{_cut_animation?'':'background'}};"><view class="border border-top-left"></view><view class="border border-top-right"></view><view class="border border-right-top"></view><view class="border border-right-bottom"></view><view class="border border-bottom-right"></view><view class="border border-bottom-left"></view><view class="border border-left-bottom"></view><view class="border border-left-top"></view></view><view class='content_middle_right bg_gray {{_flag_bright?"":"bg_black"}}' style="transition-property:{{_cut_animation?'':'background'}}"></view></view><view class='content_bottom bg_gray {{_flag_bright?"":"bg_black"}}' style="transition-property:{{_cut_animation?'':'background'}}"></view></view><image bindload="imageLoad" bindtouchstart="_start" bindtouchmove="_move" bindtouchend="_end" style="width:{{img_width ? img_width + 'px' : 'auto'}};height:{{img_height ? img_height + 'px' : 'auto'}};transform:translate3d({{_img_left-img_width/2}}px,{{_img_top-img_height/2}}px,0) scale({{scale}}) rotate({{angle}}deg);transition-duration:{{_cut_animation?.4:0}}s;" class='img' src='{{imgSrc}}'></image></view><canvas canvas-id='image-cropper' disable-scroll="true" style="width:{{_canvas_width * export_scale}}px;height:{{_canvas_height * export_scale}}px;left:{{canvas_left}}px;top:{{canvas_top}}px" class='image-cropper-canvas'></canvas></view>

image-cropper.js

Component({properties: {/*** 图片路径*/'imgSrc': {type: String},/*** 裁剪框高度*/'height': {type: Number,value: 200},/*** 裁剪框宽度*/'width': {type: Number,value: 200},/*** 裁剪框最小尺寸*/'min_width': {type: Number,value: 100},'min_height': {type: Number,value: 100},/*** 裁剪框最大尺寸*/'max_width': {type: Number,value: 300},'max_height': {type: Number,value: 300},/*** 裁剪框禁止拖动*/'disable_width': {type: Boolean,value: false},'disable_height': {type: Boolean,value: false},/*** 锁定裁剪框比例*/'disable_ratio': {type: Boolean,value: false},/*** 生成的图片尺寸相对剪裁框的比例*/'export_scale': {type: Number,value: 3},/*** 生成的图片质量0-1*/'quality': {type: Number,value: 1},'cut_top': {type: Number,value: null},'cut_left': {type: Number,value: null},/*** canvas上边距(不设置默认不显示)*/'canvas_top': {type: Number,value: null},/*** canvas左边距(不设置默认不显示)*/'canvas_left': {type: Number,value: null},/*** 图片宽度*/'img_width': {type: null,value: null},/*** 图片高度*/'img_height': {type: null,value: null},/*** 图片缩放比*/'scale': {type: Number,value: 1},/*** 图片旋转角度*/'angle': {type: Number,value: 0},/*** 最小缩放比*/'min_scale': {type: Number,value: 0.5},/*** 最大缩放比*/'max_scale': {type: Number,value: 2},/*** 是否禁用旋转*/'disable_rotate': {type: Boolean,value: false},/*** 是否限制移动范围(剪裁框只能在图片内)*/'limit_move': {type: Boolean,value: false}},data: {el: 'image-cropper', //暂时无用info: wx.getSystemInfoSync(),MOVE_THROTTLE: null,//触摸移动节流settimeoutMOVE_THROTTLE_FLAG: true,//节流标识INIT_IMGWIDTH: 0, //图片设置尺寸,此值不变(记录最初设定的尺寸)INIT_IMGHEIGHT: 0, //图片设置尺寸,此值不变(记录最初设定的尺寸)TIME_BG: null,//背景变暗延时函数TIME_CUT_CENTER: null,_touch_img_relative: [{x: 0,y: 0}], //鼠标和图片中心的相对位置_flag_cut_touch: false,//是否是拖动裁剪框_hypotenuse_length: 0, //双指触摸时斜边长度_flag_img_endtouch: false, //是否结束触摸_flag_bright: true, //背景是否亮_canvas_overflow: true,//canvas缩略图是否在屏幕外面_canvas_width: 200,_canvas_height: 200,origin_x: 0.5, //图片旋转中心origin_y: 0.5, //图片旋转中心_cut_animation: false,//是否开启图片和裁剪框过渡_img_top: wx.getSystemInfoSync().windowHeight / 2, //图片上边距_img_left: wx.getSystemInfoSync().windowWidth / 2, //图片左边距watch: {//监听截取框宽高变化width(value, that) {if (value < that.data.min_width) {that.setData({width: that.data.min_width});}that._computeCutSize();},height(value, that) {if (value < that.data.min_height) {that.setData({height: that.data.min_height});}that._computeCutSize();},angle(value, that) {//停止居中裁剪框,继续修改图片位置that._moveStop();if (that.data.limit_move) {if (that.data.angle % 90) {that.setData({angle: Math.round(that.data.angle / 90) * 90});return;}}},_cut_animation(value, that) {//开启过渡300毫秒之后自动关闭clearTimeout(that.data._cut_animation_time);if (value) {that.data._cut_animation_time = setTimeout(() => {that.setData({_cut_animation: false});}, 300)}},limit_move(value, that) {if (value) {if (that.data.angle % 90) {that.setData({angle: Math.round(that.data.angle / 90) * 90});}that._imgMarginDetectionScale();!that.data._canvas_overflow && that._draw();}},canvas_top(value, that) {that._canvasDetectionPosition();},canvas_left(value, that) {that._canvasDetectionPosition();},imgSrc(value, that) {that.pushImg();},cut_top(value, that) {that._cutDetectionPosition();if (that.data.limit_move) {!that.data._canvas_overflow && that._draw();}},cut_left(value, that) {that._cutDetectionPosition();if (that.data.limit_move) {!that.data._canvas_overflow && that._draw();}}}},attached() {this.data.info = wx.getSystemInfoSync();//启用数据监听this._watcher();this.data.INIT_IMGWIDTH = this.data.img_width;this.data.INIT_IMGHEIGHT = this.data.img_height;this.setData({_canvas_height: this.data.height,_canvas_width: this.data.width,});this._initCanvas();this.data.imgSrc && (this.data.imgSrc = this.data.imgSrc);//根据开发者设置的图片目标尺寸计算实际尺寸this._initImageSize();//设置裁剪框大小>设置图片尺寸>绘制canvasthis._computeCutSize();//检查裁剪框是否在范围内this._cutDetectionPosition();//检查canvas是否在范围内this._canvasDetectionPosition();//初始化完成this.triggerEvent('load', {cropper: this});},methods: {/*** 上传图片*/upload() {let that = this;wx.chooseImage({count: 1,sizeType: ['original', 'compressed'],sourceType: ['album', 'camera'],success(res) {const tempFilePaths = res.tempFilePaths[0];that.pushImg(tempFilePaths);wx.showLoading({title: '加载中...'})}})},/*** 返回图片信息*/getImg(getCallback) {this._draw(() => {wx.canvasToTempFilePath({width: this.data.width * this.data.export_scale,height: Math.round(this.data.height * this.data.export_scale),destWidth: this.data.width * this.data.export_scale,destHeight: Math.round(this.data.height) * this.data.export_scale,fileType: 'png',quality: this.data.quality,canvasId: this.data.el,success: (res) => {getCallback({url: res.tempFilePath,width: this.data.width * this.data.export_scale,height: this.data.height * this.data.export_scale});}}, this)});},/*** 设置图片动画* {* x:10,//图片在原有基础上向下移动10px* y:10,//图片在原有基础上向右移动10px* angle:10,//图片在原有基础上旋转10deg* scale:0.5,//图片在原有基础上增加0.5倍* }*/setTransform(transform) {if (!transform) return;if (!this.data.disable_rotate) {this.setData({angle: transform.angle ? this.data.angle + transform.angle : this.data.angle});}var scale = this.data.scale;if (transform.scale) {scale = this.data.scale + transform.scale;scale = scale <= this.data.min_scale ? this.data.min_scale : scale;scale = scale >= this.data.max_scale ? this.data.max_scale : scale;}this.data.scale = scale;let cutX = this.data.cut_left;let cutY = this.data.cut_top;if (transform.cutX) {this.setData({cut_left: cutX + transform.cutX});this.data.watch.cut_left(null, this);}if (transform.cutY) {this.setData({cut_top: cutY + transform.cutY});this.data.watch.cut_top(null, this);}this.data._img_top = transform.y ? this.data._img_top + transform.y : this.data._img_top;this.data._img_left = transform.x ? this.data._img_left + transform.x : this.data._img_left;//图像边缘检测,防止截取到空白this._imgMarginDetectionScale();//停止居中裁剪框,继续修改图片位置this._moveDuring();this.setData({scale: this.data.scale,_img_top: this.data._img_top,_img_left: this.data._img_left});!this.data._canvas_overflow && this._draw();//可以居中裁剪框了this._moveStop();//结束操作},/*** 设置剪裁框位置*/setCutXY(x, y) {this.setData({cut_top: y,cut_left: x});},/*** 设置剪裁框尺寸*/setCutSize(w, h) {this.setData({width: w,height: h});this._computeCutSize();},/*** 设置剪裁框和图片居中*/setCutCenter() {let cut_top = (this.data.info.windowHeight - this.data.height) * 0.5;let cut_left = (this.data.info.windowWidth - this.data.width) * 0.5;//顺序不能变this.setData({_img_top: this.data._img_top - this.data.cut_top + cut_top,cut_top: cut_top, //截取的框上边距_img_left: this.data._img_left - this.data.cut_left + cut_left,cut_left: cut_left, //截取的框左边距});},_setCutCenter() {let cut_top = (this.data.info.windowHeight - this.data.height) * 0.5;let cut_left = (this.data.info.windowWidth - this.data.width) * 0.5;this.setData({cut_top: cut_top, //截取的框上边距cut_left: cut_left, //截取的框左边距});},/*** 设置剪裁框宽度-即将废弃*/setWidth(width) {this.setData({width: width});this._computeCutSize();},/*** 设置剪裁框高度-即将废弃*/setHeight(height) {this.setData({height: height});this._computeCutSize();},/*** 是否锁定旋转*/setDisableRotate(value) {this.data.disable_rotate = value;},/*** 是否限制移动*/setLimitMove(value) {this.setData({_cut_animation: true,limit_move: !!value});},/*** 初始化图片,包括位置、大小、旋转角度*/imgReset() {this.setData({scale: 1,angle: 0,_img_top: wx.getSystemInfoSync().windowHeight / 2,_img_left: wx.getSystemInfoSync().windowWidth / 2,})},/*** 加载(更换)图片*/pushImg(src) {if (src) {this.setData({imgSrc: src});//发现是手动赋值直接返回,交给watch处理return;}// getImageInfo接口传入 src: '' 会导致内存泄漏if (!this.data.imgSrc) return;wx.getImageInfo({src: this.data.imgSrc,success: (res) => {this.data.imageObject = res;//图片非本地路径需要换成本地路径if (this.data.imgSrc.search(/tmp/) == -1) {this.setData({imgSrc: res.path});}//计算最后图片尺寸this._imgComputeSize();if (this.data.limit_move) {//限制移动,不留空白处理this._imgMarginDetectionScale();}this._draw();},fail: (err) => {this.setData({imgSrc: ''});}});},imageLoad(e) {setTimeout(() => {this.triggerEvent('imageload', this.data.imageObject);}, 1000)},/*** 设置图片放大缩小*/setScale(scale) {if (!scale) return;this.setData({scale: scale});!this.data._canvas_overflow && this._draw();},/*** 设置图片旋转角度*/setAngle(angle) {if (!angle) return;this.setData({_cut_animation: true,angle: angle});this._imgMarginDetectionScale();!this.data._canvas_overflow && this._draw();},_initCanvas() {//初始化canvasif (!this.data.ctx) {this.data.ctx = wx.createCanvasContext("image-cropper", this);}},/*** 根据开发者设置的图片目标尺寸计算实际尺寸*/_initImageSize() {//处理宽高特殊单位 %>pxif (this.data.INIT_IMGWIDTH && typeof this.data.INIT_IMGWIDTH == "string" && this.data.INIT_IMGWIDTH.indexOf("%") != -1) {let width = this.data.INIT_IMGWIDTH.replace("%", "");this.data.INIT_IMGWIDTH = this.data.img_width = this.data.info.windowWidth / 100 * width;}if (this.data.INIT_IMGHEIGHT && typeof this.data.INIT_IMGHEIGHT == "string" && this.data.INIT_IMGHEIGHT.indexOf("%") != -1) {let height = this.data.img_height.replace("%", "");this.data.INIT_IMGHEIGHT = this.data.img_height = this.data.info.windowHeight / 100 * height;}},/*** 检测剪裁框位置是否在允许的范围内(屏幕内)*/_cutDetectionPosition() {let _cutDetectionPositionTop = () => {//检测上边距是否在范围内if (this.data.cut_top < 0) {this.setData({cut_top: 0});}if (this.data.cut_top > this.data.info.windowHeight - this.data.height) {this.setData({cut_top: this.data.info.windowHeight - this.data.height});}}, _cutDetectionPositionLeft = () => {//检测左边距是否在范围内if (this.data.cut_left < 0) {this.setData({cut_left: 0});}if (this.data.cut_left > this.data.info.windowWidth - this.data.width) {this.setData({cut_left: this.data.info.windowWidth - this.data.width});}};//裁剪框坐标处理(如果只写一个参数则另一个默认为0,都不写默认居中)if (this.data.cut_top == null && this.data.cut_left == null) {this._setCutCenter();} else if (this.data.cut_top != null && this.data.cut_left != null) {_cutDetectionPositionTop();_cutDetectionPositionLeft();} else if (this.data.cut_top != null && this.data.cut_left == null) {_cutDetectionPositionTop();this.setData({cut_left: (this.data.info.windowWidth - this.data.width) / 2});} else if (this.data.cut_top == null && this.data.cut_left != null) {_cutDetectionPositionLeft();this.setData({cut_top: (this.data.info.windowHeight - this.data.height) / 2});}},/*** 检测canvas位置是否在允许的范围内(屏幕内)如果在屏幕外则不开启实时渲染* 如果只写一个参数则另一个默认为0,都不写默认超出屏幕外*/_canvasDetectionPosition() {if (this.data.canvas_top == null && this.data.canvas_left == null) {this.data._canvas_overflow = false;this.setData({canvas_top: -5000,canvas_left: -5000});} else if (this.data.canvas_top != null && this.data.canvas_left != null) {if (this.data.canvas_top < - this.data.height || this.data.canvas_top > this.data.info.windowHeight) {this.data._canvas_overflow = true;} else {this.data._canvas_overflow = false;}} else if (this.data.canvas_top != null && this.data.canvas_left == null) {this.setData({canvas_left: 0});} else if (this.data.canvas_top == null && this.data.canvas_left != null) {this.setData({canvas_top: 0});if (this.data.canvas_left < -this.data.width || this.data.canvas_left > this.data.info.windowWidth) {this.data._canvas_overflow = true;} else {this.data._canvas_overflow = false;}}},/*** 图片边缘检测-位置*/_imgMarginDetectionPosition(scale) {if (!this.data.limit_move) return;let left = this.data._img_left;let top = this.data._img_top;var scale = scale || this.data.scale;let img_width = this.data.img_width;let img_height = this.data.img_height;if (this.data.angle / 90 % 2) {img_width = this.data.img_height;img_height = this.data.img_width;}left = this.data.cut_left + img_width * scale / 2 >= left ? left : this.data.cut_left + img_width * scale / 2;left = this.data.cut_left + this.data.width - img_width * scale / 2 <= left ? left : this.data.cut_left + this.data.width - img_width * scale / 2;top = this.data.cut_top + img_height * scale / 2 >= top ? top : this.data.cut_top + img_height * scale / 2;top = this.data.cut_top + this.data.height - img_height * scale / 2 <= top ? top : this.data.cut_top + this.data.height - img_height * scale / 2;this.setData({_img_left: left,_img_top: top,scale: scale})},/*** 图片边缘检测-缩放*/_imgMarginDetectionScale() {if (!this.data.limit_move) return;let scale = this.data.scale;let img_width = this.data.img_width;let img_height = this.data.img_height;if (this.data.angle / 90 % 2) {img_width = this.data.img_height;img_height = this.data.img_width;}if (img_width * scale < this.data.width) {scale = this.data.width / img_width;}if (img_height * scale < this.data.height) {scale = Math.max(scale, this.data.height / img_height);}this._imgMarginDetectionPosition(scale);},_setData(obj) {let data = {};for (var key in obj) {if (this.data[key] != obj[key]) {data[key] = obj[key];}}this.setData(data);return data;},/*** 计算图片尺寸*/_imgComputeSize() {let img_width = this.data.img_width,img_height = this.data.img_height;if (!this.data.INIT_IMGHEIGHT && !this.data.INIT_IMGWIDTH) {//默认按图片最小边 = 对应裁剪框尺寸img_width = this.data.imageObject.width;img_height = this.data.imageObject.height;if (img_width / img_height > this.data.width / this.data.height) {img_height = this.data.height;img_width = this.data.imageObject.width / this.data.imageObject.height * img_height;} else {img_width = this.data.width;img_height = this.data.imageObject.height / this.data.imageObject.width * img_width;}} else if (this.data.INIT_IMGHEIGHT && !this.data.INIT_IMGWIDTH) {img_width = this.data.imageObject.width / this.data.imageObject.height * this.data.INIT_IMGHEIGHT;} else if (!this.data.INIT_IMGHEIGHT && this.data.INIT_IMGWIDTH) {img_height = this.data.imageObject.height / this.data.imageObject.width * this.data.INIT_IMGWIDTH;}this.setData({img_width: img_width,img_height: img_height});},//改变截取框大小_computeCutSize() {if (this.data.width > this.data.info.windowWidth) {this.setData({width: this.data.info.windowWidth,});} else if (this.data.width + this.data.cut_left > this.data.info.windowWidth) {this.setData({cut_left: this.data.info.windowWidth - this.data.cut_left,});};if (this.data.height > this.data.info.windowHeight) {this.setData({height: this.data.info.windowHeight,});} else if (this.data.height + this.data.cut_top > this.data.info.windowHeight) {this.setData({cut_top: this.data.info.windowHeight - this.data.cut_top,});}!this.data._canvas_overflow && this._draw();},//开始触摸_start(event) {this.data._flag_img_endtouch = false;if (event.touches.length == 1) {//单指拖动this.data._touch_img_relative[0] = {x: (event.touches[0].clientX - this.data._img_left),y: (event.touches[0].clientY - this.data._img_top)}} else {//双指放大let width = Math.abs(event.touches[0].clientX - event.touches[1].clientX);let height = Math.abs(event.touches[0].clientY - event.touches[1].clientY);this.data._touch_img_relative = [{x: (event.touches[0].clientX - this.data._img_left),y: (event.touches[0].clientY - this.data._img_top)}, {x: (event.touches[1].clientX - this.data._img_left),y: (event.touches[1].clientY - this.data._img_top)}];this.data._hypotenuse_length = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));}!this.data._canvas_overflow && this._draw();},_move_throttle() {//安卓需要节流if (this.data.info.platform == 'android') {clearTimeout(this.data.MOVE_THROTTLE);this.data.MOVE_THROTTLE = setTimeout(() => {this.data.MOVE_THROTTLE_FLAG = true;}, 1000 / 40)return this.data.MOVE_THROTTLE_FLAG;} else {this.data.MOVE_THROTTLE_FLAG = true;}},_move(event) {if (this.data._flag_img_endtouch || !this.data.MOVE_THROTTLE_FLAG) return;this.data.MOVE_THROTTLE_FLAG = false;this._move_throttle();this._moveDuring();if (event.touches.length == 1) {//单指拖动let left = (event.touches[0].clientX - this.data._touch_img_relative[0].x),top = (event.touches[0].clientY - this.data._touch_img_relative[0].y);//图像边缘检测,防止截取到空白this.data._img_left = left;this.data._img_top = top;this._imgMarginDetectionPosition();this.setData({_img_left: this.data._img_left,_img_top: this.data._img_top});} else {//双指放大let width = (Math.abs(event.touches[0].clientX - event.touches[1].clientX)),height = (Math.abs(event.touches[0].clientY - event.touches[1].clientY)),hypotenuse = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)),scale = this.data.scale * (hypotenuse / this.data._hypotenuse_length),current_deg = 0;scale = scale <= this.data.min_scale ? this.data.min_scale : scale;scale = scale >= this.data.max_scale ? this.data.max_scale : scale;//图像边缘检测,防止截取到空白this.data.scale = scale;this._imgMarginDetectionScale();//双指旋转(如果没禁用旋转)let _touch_img_relative = [{x: (event.touches[0].clientX - this.data._img_left),y: (event.touches[0].clientY - this.data._img_top)}, {x: (event.touches[1].clientX - this.data._img_left),y: (event.touches[1].clientY - this.data._img_top)}];if (!this.data.disable_rotate) {let first_atan = 180 / Math.PI * Math.atan2(_touch_img_relative[0].y, _touch_img_relative[0].x);let first_atan_old = 180 / Math.PI * Math.atan2(this.data._touch_img_relative[0].y, this.data._touch_img_relative[0].x);let second_atan = 180 / Math.PI * Math.atan2(_touch_img_relative[1].y, _touch_img_relative[1].x);let second_atan_old = 180 / Math.PI * Math.atan2(this.data._touch_img_relative[1].y, this.data._touch_img_relative[1].x);//当前旋转的角度let first_deg = first_atan - first_atan_old,second_deg = second_atan - second_atan_old;if (first_deg != 0) {current_deg = first_deg;} else if (second_deg != 0) {current_deg = second_deg;}}this.data._touch_img_relative = _touch_img_relative;this.data._hypotenuse_length = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));//更新视图this.setData({angle: this.data.angle + current_deg,scale: this.data.scale});}!this.data._canvas_overflow && this._draw();},//结束操作_end(event) {this.data._flag_img_endtouch = true;this._moveStop();},//点击中间剪裁框处理_click(event) {if (!this.data.imgSrc) {//调起上传this.upload();return;}this._draw(() => {let x = event.detail ? event.detail.x : event.touches[0].clientX;let y = event.detail ? event.detail.y : event.touches[0].clientY;if ((x >= this.data.cut_left && x <= (this.data.cut_left + this.data.width)) && (y >= this.data.cut_top && y <= (this.data.cut_top + this.data.height))) {//生成图片并回调wx.canvasToTempFilePath({width: this.data.width * this.data.export_scale,height: Math.round(this.data.height * this.data.export_scale),destWidth: this.data.width * this.data.export_scale,destHeight: Math.round(this.data.height) * this.data.export_scale,fileType: 'png',quality: this.data.quality,canvasId: this.data.el,success: (res) => {this.triggerEvent('tapcut', {url: res.tempFilePath,width: this.data.width * this.data.export_scale,height: this.data.height * this.data.export_scale});}}, this)}});},//渲染_draw(callback) {if (!this.data.imgSrc) return;let draw = () => {//图片实际大小let img_width = this.data.img_width * this.data.scale * this.data.export_scale;let img_height = this.data.img_height * this.data.scale * this.data.export_scale;//canvas和图片的相对距离var xpos = this.data._img_left - this.data.cut_left;var ypos = this.data._img_top - this.data.cut_top;//旋转画布this.data.ctx.translate(xpos * this.data.export_scale, ypos * this.data.export_scale);this.data.ctx.rotate(this.data.angle * Math.PI / 180);this.data.ctx.drawImage(this.data.imgSrc, -img_width / 2, -img_height / 2, img_width, img_height);this.data.ctx.draw(false, () => {callback && callback();});}if (this.data.ctx.width != this.data.width || this.data.ctx.height != this.data.height) {//优化拖动裁剪框,所以必须把宽高设置放在离用户触发渲染最近的地方this.setData({_canvas_height: this.data.height,_canvas_width: this.data.width,}, () => {//延迟40毫秒防止点击过快出现拉伸或裁剪过多setTimeout(() => {draw();}, 40);});} else {draw();}},//裁剪框处理_cutTouchMove(e) {if (this.data._flag_cut_touch && this.data.MOVE_THROTTLE_FLAG) {if (this.data.disable_ratio && (this.data.disable_width || this.data.disable_height)) return;//节流this.data.MOVE_THROTTLE_FLAG = false;this._move_throttle();let width = this.data.width,height = this.data.height,cut_top = this.data.cut_top,cut_left = this.data.cut_left,size_correct = () => {width = width <= this.data.max_width ? width >= this.data.min_width ? width : this.data.min_width : this.data.max_width;height = height <= this.data.max_height ? height >= this.data.min_height ? height : this.data.min_height : this.data.max_height;},size_inspect = () => {if ((width > this.data.max_width || width < this.data.min_width || height > this.data.max_height || height < this.data.min_height) && this.data.disable_ratio) {size_correct();return false;} else {size_correct();return true;}};height = this.data.CUT_START.height + ((this.data.CUT_START.corner > 1 && this.data.CUT_START.corner < 4 ? 1 : -1) * (this.data.CUT_START.y - e.touches[0].clientY));switch (this.data.CUT_START.corner) {case 1:width = this.data.CUT_START.width + this.data.CUT_START.x - e.touches[0].clientX;if (this.data.disable_ratio) {height = width / (this.data.width / this.data.height)}if (!size_inspect()) return;cut_left = this.data.CUT_START.cut_left - (width - this.data.CUT_START.width);breakcase 2:width = this.data.CUT_START.width + this.data.CUT_START.x - e.touches[0].clientX;if (this.data.disable_ratio) {height = width / (this.data.width / this.data.height)}if (!size_inspect()) return;cut_top = this.data.CUT_START.cut_top - (height - this.data.CUT_START.height)cut_left = this.data.CUT_START.cut_left - (width - this.data.CUT_START.width)breakcase 3:width = this.data.CUT_START.width - this.data.CUT_START.x + e.touches[0].clientX;if (this.data.disable_ratio) {height = width / (this.data.width / this.data.height)}if (!size_inspect()) return;cut_top = this.data.CUT_START.cut_top - (height - this.data.CUT_START.height);breakcase 4:width = this.data.CUT_START.width - this.data.CUT_START.x + e.touches[0].clientX;if (this.data.disable_ratio) {height = width / (this.data.width / this.data.height)}if (!size_inspect()) return;break}if (!this.data.disable_width && !this.data.disable_height) {this.setData({width: width,cut_left: cut_left,height: height,cut_top: cut_top,})} else if (!this.data.disable_width) {this.setData({width: width,cut_left: cut_left})} else if (!this.data.disable_height) {this.setData({height: height,cut_top: cut_top})}this._imgMarginDetectionScale();}},_cutTouchStart(e) {let currentX = e.touches[0].clientX;let currentY = e.touches[0].clientY;let cutbox_top4 = this.data.cut_top + this.data.height - 30;let cutbox_bottom4 = this.data.cut_top + this.data.height + 20;let cutbox_left4 = this.data.cut_left + this.data.width - 30;let cutbox_right4 = this.data.cut_left + this.data.width + 30;let cutbox_top3 = this.data.cut_top - 30;let cutbox_bottom3 = this.data.cut_top + 30;let cutbox_left3 = this.data.cut_left + this.data.width - 30;let cutbox_right3 = this.data.cut_left + this.data.width + 30;let cutbox_top2 = this.data.cut_top - 30;let cutbox_bottom2 = this.data.cut_top + 30;let cutbox_left2 = this.data.cut_left - 30;let cutbox_right2 = this.data.cut_left + 30;let cutbox_top1 = this.data.cut_top + this.data.height - 30;let cutbox_bottom1 = this.data.cut_top + this.data.height + 30;let cutbox_left1 = this.data.cut_left - 30;let cutbox_right1 = this.data.cut_left + 30;if (currentX > cutbox_left4 && currentX < cutbox_right4 && currentY > cutbox_top4 && currentY < cutbox_bottom4) {this._moveDuring();this.data._flag_cut_touch = true;this.data._flag_img_endtouch = true;this.data.CUT_START = {width: this.data.width,height: this.data.height,x: currentX,y: currentY,corner: 4}} else if (currentX > cutbox_left3 && currentX < cutbox_right3 && currentY > cutbox_top3 && currentY < cutbox_bottom3) {this._moveDuring();this.data._flag_cut_touch = true;this.data._flag_img_endtouch = true;this.data.CUT_START = {width: this.data.width,height: this.data.height,x: currentX,y: currentY,cut_top: this.data.cut_top,cut_left: this.data.cut_left,corner: 3}} else if (currentX > cutbox_left2 && currentX < cutbox_right2 && currentY > cutbox_top2 && currentY < cutbox_bottom2) {this._moveDuring();this.data._flag_cut_touch = true;this.data._flag_img_endtouch = true;this.data.CUT_START = {width: this.data.width,height: this.data.height,cut_top: this.data.cut_top,cut_left: this.data.cut_left,x: currentX,y: currentY,corner: 2}} else if (currentX > cutbox_left1 && currentX < cutbox_right1 && currentY > cutbox_top1 && currentY < cutbox_bottom1) {this._moveDuring();this.data._flag_cut_touch = true;this.data._flag_img_endtouch = true;this.data.CUT_START = {width: this.data.width,height: this.data.height,cut_top: this.data.cut_top,cut_left: this.data.cut_left,x: currentX,y: currentY,corner: 1}}},_cutTouchEnd(e) {this._moveStop();this.data._flag_cut_touch = false;},//停止移动时需要做的操作_moveStop() {//清空之前的自动居中延迟函数并添加最新的clearTimeout(this.data.TIME_CUT_CENTER);this.data.TIME_CUT_CENTER = setTimeout(() => {//动画启动if (!this.data._cut_animation) {this.setData({_cut_animation: true});}this.setCutCenter();}, 1000)//清空之前的背景变化延迟函数并添加最新的clearTimeout(this.data.TIME_BG);this.data.TIME_BG = setTimeout(() => {if (this.data._flag_bright) {this.setData({_flag_bright: false});}}, 2000)},//移动中_moveDuring() {//清空之前的自动居中延迟函数clearTimeout(this.data.TIME_CUT_CENTER);//清空之前的背景变化延迟函数clearTimeout(this.data.TIME_BG);//高亮背景if (!this.data._flag_bright) {this.setData({_flag_bright: true});}},//监听器_watcher() {Object.keys(this.data).forEach(v => {this._observe(this.data, v, this.data.watch[v]);})},_observe(obj, key, watchFun) {var val = obj[key];Object.defineProperty(obj, key, {configurable: true,enumerable: true,set: (value) => {val = value;watchFun && watchFun(val, this);},get() {if (val && '_img_top|img_left||width|height|min_width|max_width|min_height|max_height|export_scale|cut_top|cut_left|canvas_top|canvas_left|img_width|img_height|scale|angle|min_scale|max_scale'.indexOf(key) != -1) {let ret = parseFloat(parseFloat(val).toFixed(3));if (typeof val == "string" && val.indexOf("%") != -1) {ret += '%';}return ret;}return val;}})},_preventTouchMove() {}}})

image-cropper.css

.image-cropper{background:rgba(14, 13, 13,.8);position: fixed;top:0;left:0;width:100vw;height:100vh;z-index: 1;}.main{position: absolute;width:100vw;height:100vh;overflow: hidden;}.content{z-index: 9;position: absolute;width:100vw;height:100vh;display: flex;flex-direction:column;pointer-events:none;}.bg_black{background: rgba(0, 0, 0, 0.8)!important;}.bg_gray{background: rgba(0, 0, 0, 0.45);transition-duration: .35s;}.content>.content_top{pointer-events:none;}.content>.content_middle{display: flex;height: 200px;width:100%;}.content_middle_middle{width:200px;box-sizing:border-box;position: relative;transition-duration: .3s;}.content_middle_right{flex: auto;}.content>.content_bottom{flex: auto;}.image-cropper .img{z-index: 2;top:0;left:0;position: absolute;border:none;width:100%;backface-visibility: hidden;transform-origin:center;}.image-cropper-canvas{position: fixed;background: white;width:150px;height:150px;z-index: 10;top:-200%;pointer-events:none;}.border{background: white;pointer-events:auto;position:absolute;}.border-top-left{left:-2.5px;top:-2.5px;height:2.5px;width:33rpx;}.border-top-right{right:-2.5px;top:-2.5px;height:2.5px;width:33rpx;}.border-right-top{top:-1px;width:2.5px;height:30rpx;right:-2.5px;}.border-right-bottom{width:2.5px;height:30rpx;right:-2.5px;bottom:-1px;}.border-bottom-left{height:2.5px;width:33rpx;bottom:-2.5px;left:-2.5px;}.border-bottom-right{height:2.5px;width:33rpx;bottom:-2.5px;right:-2.5px;}.border-left-top{top:-1px;width:2.5px;height:30rpx;left:-2.5px;}.border-left-bottom{width:2.5px;height:30rpx;left:-2.5px;bottom:-1px;}

image-cropper.json

{"component": true}

之后就是在需要的地方引入该组件,例如需要在test界面引用:

test.wxml

<image-cropper id="image-cropper" bindload="cropperload" bindimageload="loadimage" bindtapcut="clickcut" limit_move="{{limit_move}}" disable_rotate="{{disable_rotate}}" width="{{width}}" height="{{height}}" imgSrc="{{src}}" angle="{{angle}}" disable_width="{{disable_width}}" max_width="{{max_width}}" max_height="{{max_height}}" disable_height="{{disable_height}}" disable_ratio="{{disable_ratio}}"></image-cropper><view class='bottom'><text class="btnBox" catchtap='cancel'>取消</text><view class="btnBox imageBox" catchtap='reset'><image src="../../../image/resetIcon.png"></image></view><view class="btnBox imageBox" catchtouchstart='rotate' catchtouchend='end'><image src="../../../image/whirlIcon.png"></image></view><!-- <button class="btnBox" catchtouchstart='rotate' catchtouchend='end' data-type="rotate">旋转</button> --><!-- <button class="btnBox" catchtap='reset'>重置</button> --><button class="btnBox btnColor" bindtap='submit'>确定</button></view>

test.js

//获取应用实例const app = getApp()Page({data: {src: '',width: 250,//宽度height: 250,//高度max_width: 400,max_height: 400,disable_rotate: true,//是否禁用旋转disable_ratio: true,//锁定比例limit_move: true,//是否限制移动},onLoad: function (options) {this.cropper = this.selectComponent("#image-cropper");//开始裁剪this.setData({src: options.src,});},cropperload(e) {console.log('cropper加载完成');},loadimage(e) {wx.hideLoading();console.log('图片');this.cropper.imgReset();},clickcut(e) {console.log(e.detail);//图片预览wx.previewImage({current: e.detail.url, // 当前显示图片的http链接urls: [e.detail.url] // 需要预览的图片http链接列表})},setWidth(e) {this.setData({width: e.detail.value < 10 ? 10 : e.detail.value});this.setData({cut_left: this.cropper.data.cut_left});},setHeight(e) {this.setData({height: e.detail.value < 10 ? 10 : e.detail.value});this.setData({cut_top: this.cropper.data.cut_top});},setCutTop(e) {this.setData({cut_top: e.detail.value});this.setData({cut_top: this.cropper.data.cut_top});},setCutLeft(e) {this.setData({cut_left: e.detail.value});this.setData({cut_left: this.cropper.data.cut_left});},switchChangeDisableHeight(e) {this.setData({disable_height: e.detail.value});},submit() {this.cropper.getImg((obj) => {console.log(obj.url);var that = this;wx.uploadFile({url: app.func.rootDocment + 'app/accounts/changeAvatar?ob-token=' + wx.getStorageSync('token'),filePath: obj.url,name: 'file',success: function (res) {wx.showToast({title: '修改成功',icon: 'none',duration: 2000})app.globalData.imgSrc = obj.url;wx.navigateBack({delta: -1})},fail: function (error) {wx.showToast({title: '修改失败',icon: 'none',duration: 2000})},})// app.globalData.imgSrc = obj.url;// wx.navigateBack({// delta: -1// })});},rotate() {//在用户旋转的基础上旋转90°this.cropper.setAngle(this.cropper.data.angle += 90);},end(e) {clearInterval(this.data[e.currentTarget.dataset.type]);},reset(){this.cropper.imgReset();},cancel(){wx.navigateBack({delta: -1})}})

test.js

.top{position: absolute;width:100%;top:10rpx;display: flex;flex-flow:wrap;z-index: 10;color:white;justify-content:space-around;}page{background:rgb(14, 13, 13);}view{font-size: 30rpx;}.bottom{position: absolute;width:100%;bottom:50rpx;display: flex;z-index: 10;align-items: center;flex-wrap:wrap;height:100rpx;}.bottom .btnBox{display: inline-block;font-size:28rpx;z-index:2;height:60rpx;line-height:60rpx;width:15%;margin:0rpx 5%;text-align:center;color:#fff;}.imageBox image{width:40rpx;height:40rpx;margin-top:10rpx;}.btnColor{background:#2ba940;}.input{display: flex;height: 50rpx;width:50%;}.input>.label{min-width:150rpx;font-size: 30rpx;height: 50rpx;line-height: 50rpx;}.input>input{margin-left:10rpx;text-align: center;max-width:160rpx;border:1px solid rgb(255, 255, 255);height: 50rpx;line-height: 50rpx;min-height: 50rpx;box-sizing: border-box;}

test.json

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。