123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- // component/cropper/cropper.js
- const device = wx.getSystemInfoSync();
- var twoPoint = {
- x1: 0,
- y1: 0,
- x2: 0,
- y2: 0
- }
- Component({
- /**
- * 组件的属性列表
- */
- properties: {
- ratio: {
- type: Number,
- observer: function (newVal, oldVal) {
- this.setData({
- width: device.windowWidth * 0.8,
- height: device.windowWidth * 0.8 / newVal
- })
- }
- },
- url: {
- type: String,
- observer ( newVal, oldVal ) {
- this.initImg( newVal )
- }
- }
- },
- /**
- * 组件的初始数据
- */
- data: {
- width: device.windowWidth * 0.8, //剪裁框的宽度
- height: device.windowWidth * 0.8 / (102 / 152), //剪裁框的长度
- originImg: null, //存放原图信息
- stv: {
- offsetX: 0, //剪裁图片左上角坐标x
- offsetY: 0, //剪裁图片左上角坐标y
- zoom: false, //是否缩放状态
- distance: 0, //两指距离
- scale: 1, //缩放倍数
- rotate: 0 //旋转角度
- },
- },
- /**
- * 组件的方法列表
- */
- methods: {
- uploadTap() {
- let _this = this
- wx.chooseImage({
- count: 1, // 默认9
- sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有
- sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
- success(res) {
- _this.initImg( res.tempFilePaths[0]);
- }
- })
- },
- rotate() {
- let _this = this;
- _this.setData({
- 'stv.rotate': _this.data.stv.rotate % 90 == 0 ? _this.data.stv.rotate = _this.data.stv.rotate + 90 : _this.data.stv.rotate = 0
- })
- },
- back(){
- this.triggerEvent("getBack", {})
- },
- // canvas剪裁图片
- cropperImg() {
- let _this = this;
- let ctx = wx.createCanvasContext('imgcrop',this);
- let cropData = _this.data.stv;
- ctx.save();
- // 缩放偏移值
- let x = (_this.data.originImg.width - _this.data.originImg.width * cropData.scale) / 2;
- let y = (_this.data.originImg.height - _this.data.originImg.height * cropData.scale) / 2;
- //画布中点坐标转移到图片中心
- let movex = (cropData.offsetX + x) * 2 + _this.data.originImg.width * cropData.scale;
- let movey = (cropData.offsetY + y) * 2 + _this.data.originImg.height * cropData.scale;
- ctx.translate(movex, movey);
- ctx.rotate(cropData.rotate * Math.PI / 180);
- ctx.translate(-movex, -movey);
-
- ctx.drawImage(_this.data.originImg.url, (cropData.offsetX + x) * 2, (cropData.offsetY + y) * 2, _this.data.originImg.width * 2 * cropData.scale, _this.data.originImg.height * 2 * cropData.scale);
- ctx.restore();
- ctx.draw(false, ()=> {
- wx.canvasToTempFilePath({
- canvasId: 'imgcrop',
- success(response) {
- _this.triggerEvent("getCropperImg", { url: response.tempFilePath, type: _this.data.originImg.type });
- },
- fail( e ) {
- wx.showToast({
- title: '生成图片失败',
- icon: 'none'
- })
- }
- }, this);
- });
- },
- initImg(url) {
- wx.showToast({
- icon: 'loading',
- mask: true
- });
- let _this = this;
- wx.getImageInfo({
- src: url,
- success(resopne) {
- let innerAspectRadio = resopne.width / resopne.height;
- if (innerAspectRadio < _this.data.width / _this.data.height) {
- _this.setData({
- originImg: {
- url: url,
- width: _this.data.width,
- height: _this.data.width / innerAspectRadio
- },
- stv: {
- offsetX: 0,
- offsetY: 0 - Math.abs((_this.data.height - _this.data.width / innerAspectRadio) / 2),
- zoom: false, //是否缩放状态
- distance: 0, //两指距离
- scale: 1, //缩放倍数
- rotate: 0
- },
- })
- } else {
- _this.setData({
- originImg: {
- url: url,
- height: _this.data.height,
- width: _this.data.height * innerAspectRadio
- },
- stv: {
- offsetX: 0 - Math.abs((_this.data.width - _this.data.height * innerAspectRadio) / 2),
- offsetY: 0,
- zoom: false, //是否缩放状态
- distance: 0, //两指距离
- scale: 1, //缩放倍数
- rotate: 0
- }
- })
- }
- }
- })
- },
- //事件处理函数
- touchstartCallback: function (e) {
- if (e.touches.length === 1) {
- let { clientX, clientY } = e.touches[0];
- this.startX = clientX;
- this.startY = clientY;
- this.touchStartEvent = e.touches;
- } else {
- let xMove = e.touches[1].clientX - e.touches[0].clientX;
- let yMove = e.touches[1].clientY - e.touches[0].clientY;
- let distance = Math.sqrt(xMove * xMove + yMove * yMove);
- twoPoint.x1 = e.touches[0].pageX * 2
- twoPoint.y1 = e.touches[0].pageY * 2
- twoPoint.x2 = e.touches[1].pageX * 2
- twoPoint.y2 = e.touches[1].pageY * 2
- this.setData({
- 'stv.distance': distance,
- 'stv.zoom': true, //缩放状态
- })
- }
- },
- //图片手势动态缩放
- touchmoveCallback: function (e) {
- let _this = this
- fn(_this, e)
- },
- touchendCallback: function (e) {
- //触摸结束
- if (e.touches.length === 0) {
- this.setData({
- 'stv.zoom': false, //重置缩放状态
- })
- }
- }
- }
- })
- /**
- * fn:延时调用函数
- * delay:延迟多长时间
- * mustRun:至少多长时间触发一次
- */
- var throttle = function (fn, delay, mustRun) {
- var timer = null,
- previous = null;
- return function () {
- var now = +new Date(),
- context = this,
- args = arguments;
- if (!previous) previous = now;
- var remaining = now - previous;
- if (mustRun && remaining >= mustRun) {
- fn.apply(context, args);
- previous = now;
- } else {
- clearTimeout(timer);
- timer = setTimeout(function () {
- fn.apply(context, args);
- }, delay);
- }
- }
- }
- var touchMove = function (_this, e) {
- //触摸移动中
- if (e.touches.length === 1) {
- //单指移动
- if (_this.data.stv.zoom) {
- //缩放状态,不处理单指
- return;
- }
- let { clientX, clientY } = e.touches[0];
- let offsetX = clientX - _this.startX;
- let offsetY = clientY - _this.startY;
- _this.startX = clientX;
- _this.startY = clientY;
- let { stv } = _this.data;
- stv.offsetX += offsetX;
- stv.offsetY += offsetY;
- stv.offsetLeftX = -stv.offsetX;
- stv.offsetLeftY = -stv.offsetLeftY;
- _this.setData({
- stv: stv
- });
- } else if (e.touches.length === 2) {
- //计算旋转
- let preTwoPoint = JSON.parse(JSON.stringify(twoPoint))
- twoPoint.x1 = e.touches[0].pageX * 2
- twoPoint.y1 = e.touches[0].pageY * 2
- twoPoint.x2 = e.touches[1].pageX * 2
- function vector(x1, y1, x2, y2) {
- this.x = x2 - x1;
- this.y = y2 - y1;
- };
- //计算点乘
- function calculateVM(vector1, vector2) {
- return (vector1.x * vector2.x + vector1.y * vector2.y) / (Math.sqrt(vector1.x * vector1.x + vector1.y * vector1.y) * Math.sqrt(vector2.x * vector2.x + vector2.y * vector2.y));
- }
- //计算叉乘
- function calculateVC(vector1, vector2) {
- return (vector1.x * vector2.y - vector2.x * vector1.y) > 0 ? 1 : -1;
- }
- let vector1 = new vector(preTwoPoint.x1, preTwoPoint.y1, preTwoPoint.x2, preTwoPoint.y2);
- let vector2 = new vector(twoPoint.x1, twoPoint.y1, twoPoint.x2, twoPoint.y2);
- let cos = calculateVM(vector1, vector2);
- let angle = Math.acos(cos) * 180 / Math.PI;
- let direction = calculateVC(vector1, vector2);
- let _allDeg = direction * angle;
- // 双指缩放
- let xMove = e.touches[1].clientX - e.touches[0].clientX;
- let yMove = e.touches[1].clientY - e.touches[0].clientY;
- let distance = Math.sqrt(xMove * xMove + yMove * yMove);
- let distanceDiff = distance - _this.data.stv.distance;
- let newScale = _this.data.stv.scale + 0.005 * distanceDiff;
- if (Math.abs(_allDeg) > 1) {
- _this.setData({
- 'stv.rotate': _this.data.stv.rotate + _allDeg
- })
- } else {
- //双指缩放
- let xMove = e.touches[1].clientX - e.touches[0].clientX;
- let yMove = e.touches[1].clientY - e.touches[0].clientY;
- let distance = Math.sqrt(xMove * xMove + yMove * yMove);
- let distanceDiff = distance - _this.data.stv.distance;
- let newScale = _this.data.stv.scale + 0.005 * distanceDiff;
- if (newScale < 0.2 || newScale > 2.5) {
- return;
- }
- _this.setData({
- 'stv.distance': distance,
- 'stv.scale': newScale,
- })
- }
- } else {
- return;
- }
- }
- //为touchMove函数节流
- const fn = throttle(touchMove, 10, 10);
|