我正在从用户的网络摄像头拍照并在Canvas上绘图。我使用CSS构建视频控件,如缩放视频,旋转,左/右移动。它正在应用于实时流,但是当我在Canvas上拍照并绘制时,这些功能(旋转,缩放)不适用。 我知道,因为我没有改变Canvas,这就是为什么它没有应用。
所以,任何想法如何使用相同的CSS代码在画布上绘制[旋转,缩放,左/右移动]。 (或者可能是特定于Canvas上下文的代码。)
答案 0 :(得分:1)
转型变得轻松。
不幸的是,给定的答案无法描述缩放,平移和旋转功能的正确用法。这些函数乘以现有的变换,因此结果是相对的而不是绝对的。例如,来自默认转换
ctx.setTransform(1, 0, 0, 1, 0, 0); // set the transformation to the default identity matrix
ctx.scale(2, 2); // scale the transform. Objects are now drawn 2 time larger
ctx.scale(2, 2); // This is applied to the existing scale
// objects are now draw 4 times as large not 2 times
ctx.rotate(Math.PI / 2); // rotate the transformation 90 deg clockwise
// objects are drawn with the x axis down the screen
ctx.rotate(Math.PI / 2); // Rotate a further 90 deg clockwise
// objects are drawn with the x axis from right to left
// and the y axis moves up
ctx.translate(x, y)
函数也是相对的,并且由于您提供的坐标由现有转换转换,因此更难处理。因此,如果在上面的代码之后应用给出100乘100的平移,则首先缩放并旋转4度和180度。结果位置将位于画布坐标x:-400和y:-400处。要转换为所需的坐标(100,100),首先需要应用逆变换,这将导致ctx.translate(-25, -25)
因为没有办法确切知道当前的变换,所以很难计算逆变换并应用它,这样你就可以在画布坐标中工作。
<强>的setTransform 强>
并非所有内容都丢失了画布2D API提供了一个函数ctx.setTransform()
,它用一个新的替换当前的转换。它不是相对的,而是绝对的。这使您可以确切地知道当前的转换并大大简化了转换图像(或任何正在绘制的内容)的过程
通用功能。
要旋转缩放和定位图像,这是一个通用功能,可以帮助您完成此操作。
参数
Math.PI / 2
,
Math.PI
,Math.PI * 1.5
,并回到起点Math.PI * 2
它的作用
该函数使用所需的比例和平移设置绝对变换。将旋转应用于该变换,然后绘制图像偏移以将centerX,centerY放置在所需的坐标处。最后,该函数将转换设置回默认值。如果您对所有转换使用函数或setTransform,则严格不需要这样做,但我已将其添加到不会使80%的现有代码陷入混乱,这些代码将依赖于默认转换为当前代码。
功能源代码。
function drawImage(ctx, image, x, y, centerX, centerY, scale, rotate){
ctx.setTransform(scale, 0, 0, scale, x, y); // resets transform and
// set scale and position
ctx.rotate(rotate); // apply the rotation to the above transformation
ctx.drawImage(image, -centerX, -centerY); // draw the image offset to its center
ctx.setTransform(1, 0, 0, 1, 0, 0); // restore the transformation to default.
}
或者更简单的版本不会将不需要的重置重置为默认转换
function drawImage(ctx, image, x, y, centerX, centerY, scale, rotate){
ctx.setTransform(scale, 0, 0, scale, x, y); // resets transform and
// set scale and position
ctx.rotate(rotate); // apply the rotation to the above transformation
ctx.drawImage(image, -centerX, -centerY); // draw the image offset to its center
}
或者假设您始终使用图像中心
function drawImageCentered(ctx, image, x, y, scale, rotate){
ctx.setTransform(scale, 0, 0, scale, x, y); // resets transform and
// set scale and position
ctx.rotate(rotate); // apply the rotation to the above transformation
ctx.drawImage(image, -image.width / 2, -image.height / 2); // draw the image offset to its center
}
<强>用法强>
// image; is a 200 by 200 pixel image
// ctx; is the canvas 2D context
// canvas; is the canvas element
// call the function
drawImage(
ctx, // the context
image, // the image to draw
canvas.width / 2, canvas.height / 2, //draw it at the center of the canvas
image.width / 2, image.height / 2, // at the image center
2, // scale to twice its size
Math.PI / 4 // and rotated clockwise 45 deg
);
答案 1 :(得分:0)
你不能通过CSS来做,但在绘制到画布时使用一些javascript。对于缩放,您需要使用drawImage
上下文中canvas.getContext()
的参数半手动处理它。基本上,参数2-5是(按顺序),x,y,宽度和高度的区域,您从中提取图像,参数6-9与它放入图像的方式相同。
例如,如果您的基本图像是2000x2000,并且您将其成像为1000x1000的画布:
以下内容只是将整个图像绘制成较小的图像。
var ctx = canvas.getContext("2d");
ctx.drawImage(img,0,0,2000,2000,0,0,1000,1000);
虽然这会将基本图像的中间1000x1000绘制到画布中(即2倍变焦):
var ctx = canvas.getContext("2d");
ctx.drawImage(img,500,500,1000,1000,0,0,1000,1000);
在上面,它说,从(500,500)到(1500,1500)提取区域并将其“打印”到画布中。
旋转更复杂,因为如果您只是rotate
图像并从画布的原点(0,0)绘制,则图像将在画布外结束。您还需要在画布上执行translate
。
var ctx = canvas.getContext("2d");
ctx.rotate(90 * Math.PI/180); //rotate 90 degrees
ctx.translate(0, -canvas.height); //translate down the height of the canvas
OR
var ctx = canvas.getContext("2d");
ctx.rotate(180 * Math.PI/180); //rotate 180 degrees
ctx.translate(-canvas.width,-canvas.height); // translate down and over
OR
var ctx = canvas.getContext("2d");
ctx.rotate(270 * Math.PI/180); //rotate 270 degrees
ctx.translate(-canvas.width,0); // translate down and over
请注意,旋转发生在左上角附近。如果你想支持自由轮换,这一切都会变得更复杂。
编辑:正如Blindman67在他的评论中正确指出的那样,变换适用于基于应用的任何先前变换的上下文的变换状态。我更新了代码示例,以阐明当应用于之前未应用转换的干净上下文时,这是转换的效果。