持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情
今天继续写写Canvas
代码来练练手
做一个拖拽文字的小练习,可以传入一些文字,用鼠标拖拽的方式将这些文字排列组合起来。
对于文字的拖拽,如果是使用Dom
去一个个定义文字元素,就只能使用绝对定位,不然就会影响到Dom树结构。所以我使用了画布。
第一步:先将canvas
画布给定义好,后续就要在这上面开始写代码了
<canvas id="wordcanvas" ref="canvas"></canvas>
画布:
第二步:在js中获取到canvas的dom元素,并且因为我之前只是使用%
设置画布,很容易造成拉伸模糊,所以需要对canvas的宽高重新进行设置。
import { ref, reactive, onMounted } from "vue";
const canvas = ref(null), textAppear = ref(null);
let canvasDom;
const drawText = (word, color, initPos) => {
const fatherDom = textAppear.value;
const size = fatherDom.getBoundingClientRect();
// 不让画布模糊
[canvasDom.width, canvasDom.height] = [size.width, size.height];
// 画布
let ctx = canvasDom.getContext("2d");
}
onMounted(()=>{
canvasDom = canvas.value;
drawText('拖拽文字', '#fff', { x: 100, y: 100 });
})
第三步:在获取到画布的Context
后,先配置一下filltext
文本的一些设置,然后将传入的word参数进行拆分,因为拖拽是以单个生词进行的,所以需要将其变成数组。在此数组中需要设置文字的位置和范围,文字大小因为是50px
,所以文字宽50px,高大约66px
// 文字
ctx.font = "50px Arial";
ctx.fillStyle = color;
ctx.textAlign = 'left';
ctx.textBaseline = 'bottom'
ctx.shadowColor = color;
ctx.shadowBlur = 5;
ctx.shadowOffsetX = 3;
ctx.shadowOffsetY = 3;
// 文字拆分
wordArray = word.split('').map((item, index)=>{
// 单个文字绘制
let x = initPos.x + 50 * index;
ctx.fillText(item, x, initPos.y);
return {
index: index,
pos: { x: x, y: initPos.y },
range: { w: [x, x + 50], h: [initPos.y - 66, initPos.y] },
content: item
}
})
此时在界面上就能出线之前传入的参数文本了
第四步:接下来就需要配合鼠标,将这些文字进行拖拽了。
这里我先创建了一个获取element
的offsetX/Y的方法
function getPointXY(e: any):xy {
return { x: e.offsetX, y: e.offsetY };
}
在这一步中,就需要canvas绑定鼠标监听事件中按下、抬起、移动这三个事件
配置鼠标按下事件(具体代码可参考上面的代码片段),这样就能知道鼠标按下位置,以及是否是点击中了文字,并且确定点击的文字是哪一个
// 点击的文字 鼠标按下的位置
let clickWord, mouse = {mousedownpos: {x: 0, y: 0}, mouseFlag: false};
// 鼠标按下
canvasDom.onmousedown = (e) => {
...
}
// 鼠标移动
canvasDom.onmousemove = (e) => {
...
}
// 鼠标抬起
canvasDom.onmouseup = (e)=>{
...
}
在onmousemove
移动事件中,根据鼠标是否按下mouseFlag
以及clickWord
不为空,判断可以进行拖拽,然后让该文字跟随鼠标位置进行移动
这里要注意,文字的位置并不能与鼠标
element
位置相同,需要进行进行计算,我写了movexy
方法。
之后就是清除画布,然后重新绘制文字的过程了。
鼠标抬起onmouseup
事件当中,需要将mouseFlag
和clickWord
重置,并且对之前的wordArray
中移动的文字数据进行相应的修正。
这样一个简单的文字拖拽功能就实现啦。
虽然这次的拖拽比较简单,但是其实可以根据个人需求进行扩展,比如说做一个拼图游戏,原理大致也差不多吧?