// component/mygallery/mygallery.js Component({ options: { addGlobalClass: true }, properties: { imgUrls: { type: Array, value: [], observer(newVal) { this.setData({ currentImgs: newVal }); } }, title: { type: String, value: '' }, remark: { type: String, value: '' }, show: { type: Boolean, value: true, observer(newVal) { if (newVal) { let that = this; let query = this.createSelectorQuery().in(this); //必须要先创建一个查询 setTimeout(() => { query.select('.fyui-gallery__img').boundingClientRect(function (rect) { that.setData({ imgHeight: rect.height, imgWidth: rect.width, xLimit: [0, 0], yLimit: [0, 0], }); }).exec(); }, 500); } } }, current: { type: Number, value: 0 }, hideOnClick: { type: Boolean, value: true }, extClass: { type: String, value: '' } }, data: { currentImgs: [], tabList: [], pageList: [], showRemark: true, imgHeight: 0, //图片高度 imgWidth: 0, //图片宽度 xLimit: [], //缩放后x轴移动范围 yLimit: [], //缩放后y轴移动范围 translateX: 0, // 位移x坐标 单位px translateY: 0, // 位移y坐标 单位px distance: undefined, // 双指接触点距离 scale: 1, // 缩放倍数 endScale: 1, rotate: 0, // 旋转角度 oldRotate: 0, // 上一次旋转停止后的角度 startMove: { // 起始位移距离 x: 0, y: 0, }, startTouches: [] // 起始点touch数组 }, pageLifetimes: { // 组件所在页面的生命周期函数 show: function () { }, }, ready() { const data = this.data; this.setData({ currentImgs: data.imgUrls }); }, methods: { change(e) { this.setData({ current: e.detail.current }); this.triggerEvent('change', { current: e.detail.current }, {}); //图片复位 this.setData({ scale: 1, translateX: 0, translateY: 0, rotate: 0 }) }, deleteImg() { const data = this.data; const imgs = data.currentImgs; const url = imgs.splice(data.current, 1); this.triggerEvent('delete', { url: url[0], index: data.current }, {}); if (imgs.length === 0) { // @ts-ignore this.hideGallery(); return; } this.setData({ current: 0, currentImgs: imgs }); }, hideGallery() { const data = this.data; if (data.hideOnClick) { this.setData({ show: false, scale: 1, endScale: 1, showRemark: true, translateX: 0, translateY: 0, rotate: 0 }); this.triggerEvent('hide', {}, {}); } }, /** * 底部图片导航栏选择事件 */ swichNav(e) { var that = this; if (this.data.currentTab === e.target.dataset.current) { return false; } else { that.setData({ current: e.target.dataset.current, }) } }, /** * 底部图片导航栏、文本显隐事件 */ toggle() { const showRemark = !this.data.showRemark this.setData({ showRemark }) }, rotateImg(e) { const clockwise = e.currentTarget.dataset.clockwise let rotate = this.data.rotate if (clockwise) { rotate += 90 } else { rotate -= 90 } rotate = rotate > 360 ? rotate - 360 : rotate rotate = rotate < 0 ? rotate + 360 : rotate const imgWidth = this.data.imgHeight const imgHeight = this.data.imgWidth this.setData({rotate, imgWidth, imgHeight}) }, touchStart(e) { const touches = e.touches const { translateX, translateY } = this.data const { clientX, clientY } = touches[0] this.setData({ startMove:{ x: clientX - translateX, y: clientY - translateY } }) this.setData({ startTouches:touches, }) }, touchMove(e) { const touches = e.touches const { clientX: onePageX, clientY: onePageY } = touches[0] const { startMove, scale, distance: oldDistance, startTouches, oldRotate } = this.data if (touches.length === 2 && startTouches.length === 2) { // 双指缩放 const { pageX: twoPageX, pageY: twoPageY } = touches[1] // 求出当前双指距离 const distance = Math.sqrt((twoPageX - onePageX) ** 2 + (twoPageY - onePageY) ** 2) this.setData({distance}) // 双指旋转 let rotate = this.getAngle(touches[0], touches[1]) - this.getAngle(startTouches[0], startTouches[1]) + oldRotate // 如果大于360度,就减去360 rotate = rotate > 360 ? rotate - 360 : rotate this.setData({ scale: scale * (distance / (oldDistance || distance)), // rotate }) } else if (scale > 1 && startTouches.length !== 2) { // 单指拖拽 // const xL = this.data.xLimit // const yL = this.data.yLimit let x = onePageX - startMove.x let y = onePageY - startMove.y // if (x < xL[0]) { // x = xL[0] // } else if (x > xL[1]) { // x = xL[1] // } // if (y < yL[0]) { // y = yL[0] // } else if (y > yL[1]) { // y = yL[1] // } this.setData({ translateX: x, translateY: y }) } }, getAngle(p1, p2) { const x = p1.clientX - p2.clientX const y = p1.clientY- p2.clientY return Math.atan2(y, x) * 180 / Math.PI }, touchEnd() { // 保存当前旋转角度,清空双指距离 const oldRotate = this.data.rotate this.setData({ oldRotate, distance: undefined, }) // 最小缩放为1倍,同时图片移动复位 if (this.data.scale < 1) { this.setData({ scale: 1, translateX: 0, translateY: 0 }) } // 保存最后缩放的倍率 const s = this.data.scale this.setData({ endScale: s, }) // 计算当前缩放倍率下,图片可移动范围 const h = this.data.imgHeight const w = this.data.imgWidth const sH = h * s const sW = w * s const rH = (sH - h) / 2 const rW = (sW - w) / 2 const xLimit = [-rW, rW] const yLimit = [-rH, rH] this.setData({ xLimit, yLimit }) let that = this; let query = this.createSelectorQuery().in(this); //必须要先创建一个查询 query.select('.fyui-gallery__img').boundingClientRect(function (rect) { }).exec(); // 缩放后回归至当前移动位置 let translateX = this.data.translateX let translateY = this.data.translateY const xL = this.data.xLimit const yL = this.data.yLimit if (translateX < xL[0]) { translateX = xL[0] } else if (translateX > xL[1]) { translateX = xL[1] } if (translateY < yL[0]) { translateY = yL[0] } else if (translateY > yL[1]) { translateY = yL[1] } this.setData({ translateX, translateY}) }, } })