加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 资源网站 > 资源 > 正文

微信小程序内拖动图片实现移动、放大、旋转的方法

发布时间:2020-12-14 20:04:24 所属栏目:资源 来源:网络整理
导读:屏幕就像是数学上的坐标轴,且在第四象限,以屏幕左上角为圆点,X轴向右为正向左为负,Y轴向下为正向上为负(这点和数学上相反的)以圆点为基点画个距离圆点上下50宽高100的矩形来演示canvas基本用法 微信小程序这里提供了两个API wx.createContext() 创建并

屏幕就像是数学上的坐标轴,且在第四象限,以屏幕左上角为圆点,X轴向右为正向左为负,Y轴向下为正向上为负(这点和数学上相反的)以圆点为基点画个距离圆点上下50宽高100的矩形来演示canvas基本用法

微信小程序这里提供了两个API

wx.createContext() 创建并返回绘图上下文context对象

  • getActions 获取当前context上存储的绘图动作,对应wx.drawCanvas(object)中的actions
  • clearActions 清空当前的存储绘图动作

wx.drawCanvas(object) 绘制

  • canvasId 画布标识,传入的cavas-id,这里的标识可以为Number,也可以是String
  • actions 绘图动作数组,由wx.createContext创建的context,调用getActions方法导出绘图动作数组。

最近接到一个任务,在微信小程序内拖动图片组件实现移动、放大、旋转,并记录这些图片的移动位置,放大比例,旋转角度,在一个画布上生成一张图片,最后保存到手机相册。

我的具体实现思路是这样的:

一共三个功能,可以先把功能分为图片 拖动 和图片旋转缩放, 把图片的缩放和旋转做在了一起。

1.图片移动:可移动的图片肯定是要动态生成的,所以不能写死,应该是个数组,具备很多的属性。

例如:(并不是我项目的真实数据)

事件绑定图片上或者图片的父级,绑定bindtouchstart bindtouchmove事件。再bindtouchstart事件里,获取手指点击的某一个图片的点击坐标,并记录在这个图片对象的属性里面,在bindtouchmove事件里,移动的时候记录移动后的坐标,并算出俩次滑动的距离差值,追加给图片对象的left、top、x、y上,最后把本次滑动的坐标赋值给bindtouchmove事件里拿到的坐标,作为老坐标。这样就可以实现图片的滑动。

注:代码里的 items 只是我定义的一个全局变量,是一个空数组,在onLoad函数里 items = this.data.itemLits;

这样就不会频繁的去setData,我只需要处理items,处理完之后,再this.setData({itemLits:items})

items[index].lx = e.touches[0].clientX; // 记录点击时的坐标值 items[index].ly = e.touches[0].clientY; this.setData({ //赋值 itemList: items })

},WraptouchMove: function (e) {
//移动时的坐标值也写图片的属性里
items[index]._lx = e.touches[0].clientX;
items[index]._ly = e.touches[0].clientY;

//追加改动值
items[index].left += items[index]._lx - items[index].lx; // x方向
items[index].top += items[index]._ly - items[index].ly;  // y方向
items[index].x += items[index]._lx - items[index].lx;
items[index].y += items[index]._ly - items[index].ly;

//把新的值赋给老的值
items[index].lx = e.touches[0].clientX; 
items[index].ly = e.touches[0].clientY;
this.setData({//赋值就移动了
  itemList: items
})

}

2.图片的旋转和缩放,因为图片上已经有了touch事件,所以解决办法采用常规的在图片的一角添加一个控件解决这个问题,控件大致如图:

左边控件是删除按钮,右边控件则是手指按着旋转切缩放图片的控件,绑定bindtouchstart bindtouchmove事件。

index也是设置的全局变量。

if (e.currentTarget.dataset.id == items[i].id) { console.log('e.currentTarget.dataset.id',e.currentTarget.dataset.id) index = i; console.log(items[index]) items[index].active = true; } } //获取作为移动前角度的坐标 items[index].tx = e.touches[0].clientX; items[index].ty = e.touches[0].clientY; //移动前的角度 items[index].anglePre = this.countDeg(items[index].x,items[index].y,items[index].tx,items[index].ty) //获取图片半径 items[index].r = this.getDistancs(items[index].x,items[index].left,items[index].top)

},// 触摸移动事件
touchMove: function (e) {
//记录移动后的位置
items[index]._tx = e.touches[0].clientX;
items[index]._ty = e.touches[0].clientY;
//移动的点到圆心的距离 因为圆心的坐标是相对与父元素定位的 ,所有要减去父元素的OffsetLeft和OffsetTop来计算移动的点到圆心的距离
items[index].disPtoO = this.getDistancs(items[index].x,items[index]._tx - this.sysData.windowWidth
0.125,items[index]._ty - 10)

items[index].scale = items[index].disPtoO / items[index].r; //手指滑动的点到圆心的距离与半径的比值作为图片的放大比例
items[index].oScale = 1 / items[index].scale;//图片放大响应的右下角按钮同比缩小

//移动后位置的角度
items[index].angleNext = this.countDeg(items[index].x,items[index]._tx,items[index]._ty)
//角度差
items[index].new_rotate = items[index].angleNext - items[index].anglePre;

//叠加的角度差
items[index].rotate += items[index].new_rotate;
items[index].angle = items[index].rotate; //赋值

//用过移动后的坐标赋值为移动前坐标
items[index].tx = e.touches[0].clientX;
items[index].ty = e.touches[0].clientY;
items[index].anglePre = this.countDeg(items[index].x,items[index].ty)

//赋值setData渲染
this.setData({
  itemList: items
})

}

页面上是这样写的:

-->

这样一来就解决了微信小程序内拖动图片实现移动、放大、旋转的问题,操作也比较顺滑,也耗费我近四天的时间才把我的小程序上线,代码有点混乱,如果各位大佬有什么意见可以给我留言,我的小程序名字是:水逆转运符文,以后会持续改进。

2018/5/7补充一条生成图片时,组件的属性:

我的失误,忘了附上角度计算函数 countDeg :

= 0)//左下角,3象限 { angle = -(180 - angle) } else if (ox > 0 && oy < 0)//右上角,1象限 { angle = angle; } else if (ox > 0 && oy > 0)//右下角,2象限 { angle = 180 - angle; }
return angle;

}

计算触摸点到圆心的距离:

点击配件时的事件(因为再我测试在canvas中,图片不能是网络路径,所以需要下载): 【18/6/22】

300) { speed = -speed } yy += speed; let _this = this; let newTpdata = {}; newTpdata.id = data.id; newTpdata.itemid = data.itemid; newTpdata.top = 100 + yy; newTpdata.left = 100; newTpdata.width = _this.sysData.windowWidth / 4; newTpdata.scale = 1; newTpdata.angle = 0; newTpdata.rotate = 0; newTpdata.active = true; for (let i = 0; i < items.length; i++) { items[i].active = false; } if (isDownload) { wx.downloadFile({ url: data.image,success: res => { newTpdata.image = res.tempFilePath; items.push(newTpdata); _this.setData({ itemList: items }) wx.hideLoading(); } }) } else { newTpdata.image = data.image; items.push(newTpdata); _this.setData({ itemList: items }) wx.hideLoading(); } }

我的项目中生成canvas用到的代码 (绘图是通过保存按钮触发)

<div class="jb51code">
<pre class="brush:js;">
save: function() {
this.setData({
showCanvas: true,canvasHeight: this.sysData.windowHeight 0.85
})
let obj = this.data.item;
/

canvasWidth值为canvas宽度;
this.data.canvasPre是占屏幕宽度的百分比(80)
/
let canvasWidth = this.sysData.windowWidth
this.data.canvasPre / 100; //
/
num为canvas内背景图占canvas的百分比,若全背景num =1
this.sysData.windowWidth
0.75为可移动区的宽度
prop值为canvas内背景的宽度与可移动区域的宽度的比,如一致,则prop =1;
/
let prop = (canvasWidth
num) / (this.sysData.windowWidth 0.75);
maskCanvas.save();
maskCanvas.beginPath();
//一张白图
maskCanvas.setFillStyle('#fff');
maskCanvas.fillRect(0,this.sysData.windowWidth,this.data.canvasHeight)
maskCanvas.closePath();
maskCanvas.stroke();
//图头像
let image = {
w: canvasWidth
num 0.287,h: canvasWidth num 0.287,r: canvasWidth num 0.287 / 2
};
//画背景 hCw 为 1.7781 背景图的高宽比
maskCanvas.drawImage(obj.bgImg,canvasWidth
(1 - num) / 2,10,canvasWidth num,canvasWidth num hCw)
//画底图
maskCanvas.drawImage('../../images/xcx.png',canvasWidth
num hCw + 15,this.data.canvasHeight 0.15)
//画原
maskCanvas.save();
maskCanvas.beginPath();
maskCanvas.arc(canvasWidth / 2,canvasWidth num hCw obj.userTop / 100 + 10 + image.w / 2,image.r,Math.PI 2,false);
// maskCanvas.stroke()
maskCanvas.clip(); //截取
//画头像
maskCanvas.drawImage(obj.avatarUrl,(canvasWidth - image.w) / 2,canvasWidth num hCw obj.userTop / 100 + 10,image.w,image.h)
maskCanvas.closePath();
maskCanvas.restore();
//绘制文字
maskCanvas.save();
maskCanvas.beginPath();
let fontSize = this.sysData.screenWidth / 375
15;
let textColor = obj.color || '#000';
maskCanvas.setFontSize(parseInt(fontSize) prop)
maskCanvas.setFillStyle(textColor)
maskCanvas.setTextAlign('center')
maskCanvas.fillText(obj.nickName,canvasWidth / 2,obj.titleTop / 100
canvasWidth num hCw + 10 0.9 prop + fontSize * prop);
maskCanvas.closePath();
maskCanvas.stroke();
/**

  • x
  • y
  • scale
  • prop
  • width
  • height
  • /
    //画组件
    items.forEach((currentValue,index)=>{
    maskCanvas.save();
    maskCanvas.translate(canvasWidth
    (1 - num) / 2,10);
    maskCanvas.beginPath();
    maskCanvas.translate(currentValue.x prop,currentValue.y prop); //圆心坐标
    maskCanvas.rotate(currentValue.angle Math.PI / 180); // 旋转值
    maskCanvas.translate(-(currentValue.width
    currentValue.scale prop / 2),-(currentValue.height currentValue.scale prop / 2))
    maskCanvas.drawImage(currentValue.image,currentValue.width
    currentValue.scale prop,currentValue.height currentValue.scale * prop);
    maskCanvas.restore();
    })
    maskCanvas.draw(false,(e)=> {
    wx.canvasToTempFilePath({
    canvasId: 'maskCanvas',success: res => {
    this.setData({
    canvasTemImg: res.tempFilePath
    })
    }
    },this)
    })
    }

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程之家。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读