微信小程序canvas画布实现文字自由缩放、移动、旋转
本篇文章给大家带来的内容是关于小程序中canvas的拖拽功能详解,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
效果图
canvas拖拽移动详情介绍
创建canvas元素,获取画布信息
<canvas class="canvas_img" type="2d" id="myCanvas" bindtouchstart="handleCanvasStart" bindtouchmove="handleCanvasMove" bindtouchend="handleCanvasEnd" />
设置变量
data: {
canvas: null,
ctx: null,
dpr: 0, //像素比
fontSize: 18,
isDragging: null, // 1 移动 2 旋转 3 缩放
dataIndex: 0,
rectPadding: 15, //边距
dataList: [
{
type: 'text',
text: '可拖拽文字',
fontSize: 18,
fontWeight: 'normal',
fontStyle: 'normal',
startX: 1,
startY: 1,
x: 60, //x轴偏移量
y: 60, //Y轴偏移量
angle: 0, //旋转角度
}
],
},
获取画布
initData() {
// wx.showLoading()
const that = this
const query = wx.createSelectorQuery().in(this)
query.select('#myCanvas')
.fields({ node: true, size: true })
.exec(function (res) {
const canvas = res[0].node
const ctx = canvas.getContext('2d')
const dpr = wx.getWindowInfo().pixelRatio
canvas.width = res[0].width * dpr
canvas.height = res[0].height * dpr
ctx.scale(dpr, dpr)
that.setData({
canvas: canvas,
ctx: ctx,
dpr: dpr,
})
that.drawText()
ctx.restore(); // 恢复canvas状态
})
},
绘制画布文本
drawText() {
let that = this
const canvas = this.data.canvas
const ctx = this.data.ctx
let rectPadding = that.data.rectPadding;
ctx.save();
let bgImg = canvas.createImage();
bgImg.src = "../../img/3.png"
bgImg.onload = () => {
ctx.save()
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(bgImg, 0, 0, canvas.width, canvas.height);
that.data.dataList.forEach((text) => {
ctx.font = text.fontSize + "px Arial";
let textWidth = ctx.measureText(text.text).width;
let rectHeight = text.fontSize * 1.2; //文本高度
// 绘制文本框
ctx.lineWidth = 1;
ctx.strokeStyle = '#333';
// 重新映射位置
ctx.translate(textWidth / 2 + text.x, rectHeight / 2 + text.y);
// 旋转角度
ctx.rotate(text.angle);
ctx.beginPath();
ctx.rect(-textWidth / 2 - rectPadding, -rectHeight - rectPadding * 2, textWidth + rectPadding * 2, rectHeight + rectPadding * 2);
ctx.stroke();
// 填充文本框
ctx.fillStyle = '#ffffff';
// ctx.fill();
ctx.restore();
// 绘制文本
ctx.fillStyle = '#000000';
ctx.font = text.fontStyle + ' ' + text.fontWeight + ' ' + text.fontSize + "px Arial";
// 重新映射位置
ctx.translate(textWidth / 2 + text.x, rectHeight / 2 + text.y);
// 旋转角度
ctx.rotate(text.angle);
// 文本填充
ctx.fillText(text.text, -ctx.measureText(text.text).width / 2, -rectPadding);
ctx.setTransform(that.data.dpr, 0, 0, that.data.dpr, 0, 0);
ctx.save()
// 重新映射位置
ctx.translate(textWidth / 2 + text.x, rectHeight / 2 + text.y);
// 旋转角度
ctx.rotate(text.angle);
// 文本填充
ctx.fillText('旋转', -ctx.measureText('旋转').width / 2 , rectPadding+10);
ctx.setTransform(that.data.dpr, 0, 0, that.data.dpr, 0, 0);
ctx.save()
})
}
ctx.restore(); // 恢复canvas状态
},
监听手势开始事件
handleCanvasStart(e) {
let that = this
const ctx = that.data.ctx
var mouseX = e.touches[0].clientX - 0; //鼠标x轴坐标
var mouseY = e.touches[0].clientY - 0; //鼠标y轴坐标
let rectPadding = that.data.rectPadding;
that.data.dataList.forEach((item, i) => {
const textX = item.x; // 文本x轴坐标
const textY = item.y; // 文本y轴坐标
const width = ctx.measureText(item.text).width;
let rectHeight = item.fontSize * 1.2; //that.data.rectHeight;
const rotateWidth = ctx.measureText('旋转').width;
that.setData({
dataIndex: i
})
// 文字区域
if (mouseX > textX && mouseX < textX + width && mouseY > textY - 30 && mouseY < textY) {
dragging = item;
that.setData({
isDragging: 1
})
}
// 旋转区域
if (mouseX > textX + width / 2 - rectPadding && mouseX < textX + width / 2 - rectPadding + rotateWidth && mouseY > textY + rectHeight && mouseY < textY + rectHeight + rectPadding) {
dragging = item;
that.setData({
isDragging: 2
})
}
// 缩放区域
if (mouseX > textX + width - rectPadding && mouseX < textX +
width + rectPadding + 20 && mouseY > textY + rectHeight - 20 && mouseY < textY + rectHeight + rectPadding * 2) {
dragging = item;
dragging.startX = mouseX
dragging.startY = mouseY
that.setData({
isDragging: 3
})
}
})
},
监听手势移动
// 手势拖动
handleCanvasMove(e) {
const { x, y } = this.getCoordinates(e);
if (this.data.isDragging == 1) {
dragging.x = x - 50;
dragging.y = y;
this.drawText()
}
if (this.data.isDragging == 2) {
const { angle } = this.updateAngle(x, y);
dragging.angle = angle
this.drawText()
}
if (this.data.isDragging == 3) {
const { fontSize } = this.updateScale(dragging.startX, dragging.startY, x, y)
dragging.fontSize = fontSize
console.log(dragging)
this.drawText()
}
},
手势结束
handleCanvasEnd(e) {
this.setData({
isDragging: null
})
},
拖动坐标、放大缩小比例、旋转角度计算
// 获取鼠标坐标
getCoordinates(e) {
const canvas = this.data.canvas
return {
x: e.touches[0].clientX - 0,
y: e.touches[0].clientY - 0
};
},
// 旋转角度
updateAngle(x, y) {
let that = this
let angle = 0
const canvas = this.data.canvas
const dx = x - canvas.width / (2 * that.data.dpr);
const dy = y - canvas.height / (2 * that.data.dpr);
angle = Math.atan2(dy, dx);
return { angle }
},
// 缩放
updateScale(startX, startY, x, y) {
var widthDelta = x - startX;
const fontSize = this.data.fontSize + widthDelta / 10;
return { fontSize }
},
图片: 
1292

被折叠的 条评论
为什么被折叠?



