赞
踩
媒体 / 图片 / wx.cropImage (qq.com)
- wx.chooseMedia({
- count: 1,
- mediaType: ['image'],
- sourceType: ['album', 'camera'],
- success: (res) => {
- var tempFiles = res.tempFiles;
- var pathList = that.data.pathList;
- wx.cropImage({
- src: tempFiles[0].tempFilePath, // 图片路径
- cropScale: '1:1', // 裁剪比例
- success: function (res) {
- if (!/(\.jpg|\.png|\.jpeg)$/.test(res.tempFilePath.toLowerCase())) {
- wx.showToast({
- title: '请上传jpg、png或jpeg格式的图片',
- icon: 'none',
- });
- return;
- }
- var tempFilePaths = res.tempFilePath;
- console.log('裁剪图',tempFilePaths)
-
- }
-
- })
-
- }
- })
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
小程序图片裁剪插件 image-cropper | 微信开放社区 (qq.com)
1、将插件项目中image-cropper文件内容复制到本地项目中的compoent中
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>
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
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, //触摸移动节流settimeout
- MOVE_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();
- //设置裁剪框大小>设置图片尺寸>绘制canvas
- this._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() {
- //初始化canvas
- if (!this.data.ctx) {
- this.data.ctx = wx.createCanvasContext("image-cropper", this);
- }
- },
- /**
- * 根据开发者设置的图片目标尺寸计算实际尺寸
- */
- _initImageSize() {
- //处理宽高特殊单位 %>px
- if (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);
- break
- case 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)
- break
- case 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);
- break
- case 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() {}
- }
- })
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
json:
- {
- "component": true,
- "usingComponents": {}
- }
wxss:根据自己需求调整
- .image-cropper {
- background: rgba(14, 13, 13, .8);
- position: fixed;
- top: 0;
- left: 0;
- width: 100vw;
- height: 100vh;
- z-index: 999;
- }
-
- .image-cropper .main {
- position: absolute;
- width: 100vw;
- height: 100vh;
- overflow: hidden;
- }
-
- .image-cropper .content {
- z-index: 9;
- position: absolute;
- width: 100vw;
- height: 100vh;
- display: flex;
- flex-direction: column;
- pointer-events: none;
- }
-
- .image-cropper .bg_black {
- background: rgba(0, 0, 0, 0.8) !important;
- }
-
- .image-cropper .bg_gray {
- background: rgba(0, 0, 0, 0.45);
- transition-duration: .35s;
- }
-
- .image-cropper .content>.content_top {
- pointer-events: none;
- }
-
- .image-cropper .content>.content_middle {
- display: flex;
- height: 200px;
- width: 100%;
- }
-
- .image-cropper .content_middle_middle {
- width: 200px;
- box-sizing: border-box;
- position: relative;
- transition-duration: .3s;
- }
-
- .image-cropper .content_middle_right {
- flex: auto;
- }
-
- .image-cropper .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 .image-cropper-canvas {
- position: fixed;
- background: white;
- width: 150px;
- height: 150px;
- z-index: 10;
- top: -200%;
- pointer-events: none;
- }
-
- .image-cropper .border {
- background: white;
- pointer-events: auto;
- position: absolute;
- }
-
- .image-cropper .border-top-left {
- left: -2.5px;
- top: -2.5px;
- height: 2.5px;
- width: 33rpx;
- }
-
- .image-cropper .border-top-right {
- right: -2.5px;
- top: -2.5px;
- height: 2.5px;
- width: 33rpx;
- }
-
- .image-cropper .border-right-top {
- top: -1px;
- width: 2.5px;
- height: 30rpx;
- right: -2.5px;
- }
-
- .image-cropper .border-right-bottom {
- width: 2.5px;
- height: 30rpx;
- right: -2.5px;
- bottom: -1px;
- }
-
- .image-cropper .border-bottom-left {
- height: 2.5px;
- width: 33rpx;
- bottom: -2.5px;
- left: -2.5px;
- }
-
- .image-cropper .border-bottom-right {
- height: 2.5px;
- width: 33rpx;
- bottom: -2.5px;
- right: -2.5px;
- }
-
- .image-cropper .border-left-top {
- top: -1px;
- width: 2.5px;
- height: 30rpx;
- left: -2.5px;
- }
-
- .image-cropper .border-left-bottom {
- width: 2.5px;
- height: 30rpx;
- left: -2.5px;
- bottom: -1px;
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
2、然后在要引用插件的页面json文件中添加image-cropper
- "usingComponents": {
- "image-cropper": "../image-cropper/image-cropper"
- },
3、在引用插件的wxml文件中引用组件,根据自己的需求更改要的效果
- <image-cropper
- id="image-cropper"
- limit_move="{{true}}"
- disable_rotate="{{true}}"
- width="{{width}}"
- height="{{height}}"
- imgSrc="{{src}}"
- bindload="cropperload"
- bindimageload="loadimage"
- bindtapcut="clickcut">
- </image-cropper>
- <view class='bottom'>
- <button catchtap='updateImage'>更换照片</button>
- <button type="primary" bindtap='submit'>确定裁剪</button>
- </view>
4、在引用插件的js中获取处理的图片
- Page({
- data: {
- src:'',
- width:250,//宽度
- height: 250,//高度
- },
- onLoad(options) {
- //获取到image-cropper实例
- this.cropper = this.selectComponent("#image-cropper");
- //开始裁剪
- this.setData({
- src:"xxx.jpg",//要裁剪的图片
- });
- wx.showLoading({
- title: '加载中'
- })
-
- },
-
- cropperload(e){
- console.log("cropper初始化完成");
- },
-
- loadimage(e){
- console.log("图片加载完成",e.detail);
- wx.hideLoading();
- //重置图片角度、缩放、位置
- this.cropper.imgReset();
- },
- clickcut(e) {
- wx.previewImage({
- current: e.detail.url,
- urls: [e.detail.url]
- })
- },
-
- //更换图片
- updateImage: function (e) {
- wx.chooseMedia({
- count: 1,
- mediaType: ['image'],
- sourceType: ['album', 'camera'],
- success: (res) => {
- var tempFiles = res.tempFiles[0].tempFilePath;
- console.log('图片路径',tempFiles)
- }
-
- })
- },
- submit() {
- this.cropper.getImg((obj) => {
- console.log('裁剪后的图片',obj.url)
- });
- },
- onShow: function() {
-
- },
- onHide: function() {
-
- },
- onUnload: function() {
-
- },
-
- })
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
基本就是这样,可以看看下面这几个大佬的文章,更为详细:
微信小程序中裁剪图片以及压缩到指定尺寸并上传_小程序裁剪图片-CSDN博客
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。