canvas绘图总结——拾取、Text的特殊处理方式

在实现canvas双缓冲绘图、拖动以及缩放后,又遇到新的问题,那就是如何实现拾取绘制的图形?

canvas的说明文档中写有context自带有判断坐标是否在绘制路径上或者在图形中的方法,如下:

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.rect(20,20,150,100);
ctx.stroke();
ctx.isPointInPath(20,50);//判断点是否在绘制区域中
ctx.isPointInStroke(20,50);//判断是否在绘制线上

但是如此判断有个问题,context只会在最后一次绘制的图形中进行判断,也就是如果我们绘制多个图形,它只会判断是否拾取到最后一个图形。这与我们预想不符,如何解决这个问题呢?

解决思路:在绘制多个图形时,每绘制一个图形就进行一次判断,判断是否拾取到该图形。

为了节约计算资源,设置一个bool变量来判断已经拾取到了图形。示例代码如下:

var pickup = {
	id: "",
	text: ""
};
var canvas = document.getElementById("canvas");
canvas.width = 500;
canvas.height = 500;
var ctx = canvas.getContext("2d");
updateGraphic({
	x: -100,
	y: -100
})
canvas.addEventListener('mousemove', function(event) {
	var bbox = canvas.getBoundingClientRect();
	//使坐标的原点位于canvas的左上角计算新的坐标
	let x = parseFloat((event.clientX - bbox.left * (canvas.width / bbox.width)).toFixed(2)); //
	let y = parseFloat((event.clientY - bbox.top * (canvas.height / bbox.height)).toFixed(2));
	updateGraphic({
		x: x,
		y: y
	});

});

function updateGraphic(point) {
	ctx.clearRect(0, 0, 500, 500); //清空canvas
	var isPickup = false;

	ctx.beginPath();//开始新的路径
	ctx.rect(20, 20, 150, 100);
	ctx.stroke();
	if (!isPickup && ctx.isPointInPath(point.x, point.y)) {
		pickup.id = "1";
		pickup.text = "拾取到矩形";
		isPickup = true;
		console.log(pickup)
	} else {
		pickup = {
			id: "",
			text: ""
		};
	}
	ctx.closePath();//关闭路径

	ctx.beginPath()
	ctx.moveTo(20, 200);
	ctx.lineTo(50, 300);
	ctx.stroke();
	if (!isPickup && ctx.isPointInStroke(point.x, point.y)) {
		pickup.id = "2";
		pickup.text = "拾取到线";
		isPickup = true;
		console.log(pickup)
	} else {
		pickup = {
			id: "",
			text: ""
		};
	}
	ctx.closePath();
}

随着鼠标的移动就会进行图形的刷新与判断是否拾取到图形。

特例:Text的拾取

在canvas绘图中几乎所有绘制的图形都可以拾取,但唯有一个不行,那就是Text。字符串在绘制完成后并不能通过上述的两个方法进行判断,但是实际工程中依然会遇到拾取字符串的需求。那么如何解决?

解决思路:在字符串上蒙一层透明的矩形,拾取矩形作为判断是否拾取到text的判断依据。

示例代码如下:

ctx.beginPath();
ctx.fillText("拾取测试", 50, 350);

if (!isPickup) {
	ctx.save(); //保存绘制的参数颜色/字体等
	ctx.strokeStyle = "transparent";
	let w = ctx.measureText("拾取测试").width;
	let h = 12; //默认字体大小
	let x = 50
	let y = 350 - 12 / 2; //居中判断

	ctx.rect(x, y, w, h);
	ctx.stroke();
	if (ctx.isPointInStroke(point.x, point.y)) {
		pickup.id = "3";
		pickup.text = "拾取字符串";
		isPickup = true;
		console.log(pickup)
	} else {
		pickup = {
			id: "",
			text: ""
		};
	}
	ctx.restore(); //还原绘制参数以免透明属性对整体造成影响
} else {
	pickup = {
		id: "",
		text: ""
	};
}
ctx.closePath();

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Canvas是HTML5新增的一个用于绘制图形的标签,可以通过JavaScript来控制Canvas进行图形的绘制。在进行Canvas绘制时,可以通过调整画布的位置、大小和旋转角度等属性,来控制绘制出来的图形的位置和形态。 下面我们就来介绍一下Canvas画布的移动、缩放和旋转: 1. 画布移动 画布移动可以通过Canvas提供的translate方法来实现。translate方法接收两个参数,分别表示x轴和y轴方向上的偏移量。偏移量为正值表示向右或向下移动,为负值表示向左或向上移动。 例如,我们可以通过下面的代码将画布向右移动50个像素,向下移动100个像素: ``` context.translate(50, 100); ``` 2. 画布缩放 画布缩放可以通过Canvas提供的scale方法来实现。scale方法接收两个参数,分别表示x轴和y轴方向上的缩放比例。缩放比例为大于1的值表示放大,小于1的值表示缩小。 例如,我们可以通过下面的代码将画布在x轴和y轴方向上都放大2倍: ``` context.scale(2, 2); ``` 3. 画布旋转 画布旋转可以通过Canvas提供的rotate方法来实现。rotate方法接收一个参数,表示旋转的角度,单位为弧度。 例如,我们可以通过下面的代码将画布旋转45度: ``` context.rotate(Math.PI / 4); ``` 需要注意的是,Canvas绘图的坐标系原点默认在画布的左上角,而移动、缩放和旋转操作都是相对于原点进行的。因此,在进行这些操作时,需要先将画布的原点移动到需要的位置,再进行操作。例如,如果需要将画布向右移动50个像素,需要先将原点移动到(50,0)的位置,再进行移动操作: ``` context.translate(50, 0); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值