们在使用 Canvas 绘制图形时,可能会想对绘制的图形进行变换,例如让图形旋转90度,或者让图像缩小放大等,这些效果都可以通过 Canvas API 的坐标轴变换处理功能来实现。
如果我们要想将图形进行旋转,例如下面这张图片:
可以通过 rotate() 方法来实现这个效果,rotate() 方法用于旋转当前的绘图,带有一个参数 angle,表示旋转角度。旋转的中心点是坐标的原点,是以顺时针方向进行旋转,如果想要以逆时针方向来旋转,可以将参数设置为负数。
示例:
例如上图的实现代码如下所示:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>HTML5学习(9xkd.com)</title>
</head>
<body>
<canvas id="mycanvas" width="250px" height="150px" style="border: 1px solid #000;"></canvas>
<script>
var can=document.getElementById("mycanvas");
var ctx=can.getContext("2d");
ctx.fillStyle="pink"; // 填充颜色
ctx.rotate(20*Math.PI/180);
ctx.fillRect(50, 30, 100, 50);
</script>
</body>
</html>
图形缩放可以使用 scale() 方法来实现,可以对图形进行放大或缩小设置。注意,这个函数有两个参数,第一个参数为水平方向的缩放倍数,第二个参数为垂直方向的缩放倍数。要将图形缩小,可以将参数值设置为0到1之间的小数,例如 0.5 表示将图形缩小一倍。或者也可以将参数值设置为百分数,例如 0.5=50%、1=100%、2=200% 等。
示例:
将图形放大一倍:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>HTML5学习(9xkd.com)</title>
</head>
<body>
<canvas id="mycanvas" width="250px" height="150px" style="border: 1px solid #000;"></canvas>
<script>
var can=document.getElementById("mycanvas");
var ctx=can.getContext("2d");
ctx.fillStyle="pink"; // 填充颜色
ctx.fillRect(50, 30, 100, 50);
ctx.scale(1.5, 1.5);
ctx.fillRect(50, 30, 100, 50);
</script>
</body>
</html>
在浏览器中的预览效果:
移动图形可以通过 translate() 方法来实现,这个方法中的第一个参数表示将坐标轴向右边移动若干个单位,第二个参数表示将坐标轴圆点向下移动若干个单位。
示例:
将图形水平移动50px,向下移动50px:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>HTML5学习(9xkd.com)</title>
</head>
<body>
<canvas id="mycanvas" width="250px" height="150px" style="border: 1px solid #000;"></canvas>
<script>
var can=document.getElementById("mycanvas");
var ctx=can.getContext("2d");
ctx.fillStyle="pink"; // 填充颜色
ctx.fillRect(50, 30, 100, 50);
ctx.translate(50, 50);
ctx.fillRect(50, 30, 100, 50);
</script>
</body>
</html>
在浏览器中的预览效果:
我们通过上述学习的三个方法,来实现下图所示效果:
实现代码如下所示:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>HTML5学习(9xkd.com)</title>
<script>
window.onload=function() {
var can=document.getElementById("mycanvas");
var ctx=can.getContext("2d");
ctx.translate(200, 10);
ctx.fillStyle="rgba(219,112,147, 0.7)";
for(var i=0; i < 50; i++){
ctx.translate(27, 27);
ctx.scale(0.95, 0.95);
ctx.rotate(Math.PI / 10);
ctx.fillRect(0, 0, 90, 50);
}
}
</script>
</head>
<body>
<canvas id="mycanvas" width="400" height="300" style="border: 1px solid #000;"></canvas>
</body>
</html>
我们在绘制图形的时候,经常会用到上述几个方法来进行图形变化,需要注意的是,这个变化的不是画布,而是画布上的画进行变化。
查看更多可以点击链接:https://www.9xkd.com/
家好,我是前端西瓜哥,今天来和大家说说 canvas 怎么做图形拾取。
图形拾取,指的是用户通过鼠标或手指在图形界面上能选中图形的能力。图形拾取技术是之后的高亮图形、拖拽图形、点击触发事件的基础。
canvas 作为一个过于朴实无华的绘制工具,我们想知道如何让 canvas 能像 HTML 一样,知道鼠标点中了哪个 “div”。
canvas 只提供 API 在画布上绘制形状,并不知道它之前画过的图形是什么,不会保存它们的坐标、宽高等信息。
所以如果你想让 canvas 支持将其中的图形进行编辑,比如拖拽和放大,那就必须自己去维护一棵节点树。
类似这样:
const tree = {
type: 'stage',
children: [
{
type: 'rect',
x: 10, y: 10, w: 100, h: 100,
fill: 'red',
},
{
type: 'circle',
x: 0, y: 0, radius: 80,
stroke: 'yellow',
}
],
};
然后 canvas 基于此去按层级绘制这些图形。
下面我们看看元素拾取的几种方案。
isPointInPath 是 canvas 原生提供的一个检测某个点是否在指定路径内的方法。
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
ctx.beginPath(); // 表示路径的开始
ctx.rect(30, 30, 100, 50);
ctx.stroke(); // 如果只是计算,可以不绘制出来
ctx.isPointInPath(40, 40); // true,在路径内
ctx.isPointInPath(10, 10); // false,不在路径内
线上 demo:
https://codesandbox.io/s/h7pxsm
优点:
缺点:
根据真正的 canvas 元素,额外创建一个大小相同离屏的缓存 canvas 元素。
每次我们在主 canvas 上绘制形状时,也在缓存 canvas 上绘制同样形状的纯色块,并用哈希表记录颜色和对应的图形对象,比如红色表示矩形 A,绿色表示矩形 B。
然后当我们在真实 canvas 上点击时,我们在 canvas 绑定事件,就可以拿到坐标位置 (x, y),再通过 offScreenCtx.getImageData(x, y, 1, 1) 方法得到缓存 canvas 的对应像素点的颜色值,然后找到它对应的图形对象,执行其注册的事件。
Konva 库使用了该方案。
写了个简单的线上 demo,你可以尝试点击上面那个 canvas 下的图形,看看控制台输出:
https://codesandbox.io/s/veivt3
优点:
缺点:
可以用计算机图形学的算法,去判断一个点是否在某个形状内。
比如:
(1)点是否在矩形内。
function isPointInRect(point, rect) {
return (
point.x >= rect.x &&
point.y >= rect.y &&
point.x <= rect.x + rect.width &&
point.y <= rect.y + rect.height
);
}
(2)点是否在圆形内。
export function isPointInCircle(point, circle) {
const dx = point.x - circle.x;
const dy = point.y - circle.y;
const dSquare = dx * dx + dy * dy;
return dSquare <= circle.radius * circle.radius;
}
还有其他的:通过 “射线法” 判断点是否在多边形等。
优点:
缺点:
总结一下,canvas 的图形拾取有三种方案:
我是前端西瓜哥,欢迎关注我,学习更多知识。
canvas
*请认真填写需求信息,我们会在24小时内与您取得联系。