在画布上绘制CSS转换(缩放、旋转、向左、向右)
Draw CSS transformation (Scale, Rotate, Left, Right) on Canvas
我正在从用户的网络相机上拍摄照片,并将其绘制在画布上。我使用CSS构建了视频控件,如缩放视频、旋转视频、向左/向右移动。它适用于直播,但当我在画布上拍照和画画时,这些功能(旋转、缩放)不适用。我知道,因为我没有修改Canvas,所以它不适用。
所以,我想知道如何使用相同的CSS代码在画布上绘制[旋转、缩放、向左/向右移动]。(或者可能是Canvas上下文特定的代码)。
转换变得容易
不幸的是,给出的答案未能描述缩放、平移和旋转函数的正确用法。这些函数将现有的变换相乘,因此结果是相对的而不是绝对的。例如,从默认转换
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处。要转换到所需的坐标(100100),需要首先应用逆变换,这将导致ctx.translate(-25, -25)
由于无法确定当前变换,因此很难计算逆变换并应用逆变换,以便在画布坐标中工作。
setTransform
画布2D API提供了一个函数ctx.setTransform()
,该函数用新的转换替换当前转换。它不是相对的,而是绝对的。这使您能够确定当前的转换,并大大简化了转换图像(或任何正在绘制的图像)的过程
通用函数
在这里旋转缩放和定位图像是一个通用功能。
争论
- ctx:要绘制到的2D画布上下文
- image:要绘制的图像
- x,y:放置中心的绝对画布坐标坐标,从画布左上角开始以像素为单位测量
- centerX,centerY:图像原点相对于坐标图像的坐标(以像素为单位)。如果图像为100乘100,则将centerX、centerY设置为50,50将围绕图像中心缩放和旋转,并在自变量x和y给出的坐标处绘制该中心。如果centerX和centerY给定为0,0,则图像将围绕左上角旋转和缩放
- 比例:绘制图像的比例。值1表示无刻度,2表示两倍大的0.5是其大小的一半。负数反转图像在x和y方向
- 旋转:以弧度表示的旋转量,0表示否旋转然后以90度顺时针步进是CCD_ 4,
Math.PI
、Math.PI * 1.5
,返回起始Math.PI * 2
它的作用
该函数设置具有所需比例和平移的绝对变换。将旋转应用于该变换,然后绘制图像偏移,以将中心X、中心Y放置在所需坐标处。最后,函数将转换设置回默认值。如果您对所有转换都使用函数或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
);
您不能通过CSS来实现,但在画布上绘制时需要使用一些javascript。对于缩放,您需要半手动地处理它,使用canvas.getContext()
中上下文中drawImage
的参数。基本上,参数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);
在上面的文章中,它说,从(500500)到(15001500)提取区域,并将其"打印"到画布中。
旋转更为复杂,因为如果只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
或
var ctx = canvas.getContext("2d");
ctx.rotate(180 * Math.PI/180); //rotate 180 degrees
ctx.translate(-canvas.width,-canvas.height); // translate down and over
或
var ctx = canvas.getContext("2d");
ctx.rotate(270 * Math.PI/180); //rotate 270 degrees
ctx.translate(-canvas.width,0); // translate down and over
请注意,旋转发生在左上角周围。如果你想支持自由旋转,这一切都会变得更加复杂。
编辑:正如Blindman67在评论中正确指出的那样,转换应用于基于先前应用的任何转换的上下文的转换状态。我更新了代码示例,以澄清这是应用于干净上下文时的转换效果,而之前没有应用任何转换。
- 使用KineticJS变换(移动/缩放/旋转)形状
- CSS3 点击旋转和缩放
- 如何在D3中获得可缩放Icicle布局中文本标签的旋转
- 精灵缩放会导致三个.js的定位和旋转不正确
- 缩放、拖动和旋转时的图像定位
- CSS 图像查看器:图像旋转(和缩放)
- 在Openlayers 3中使标记与地图一起缩放/旋转
- 在画布上绘制CSS转换(缩放、旋转、向左、向右)
- 制作画布镜像、缩放和旋转
- Android 4.1+(Javascript浏览器):如何禁用旋转缩放
- HTML>根据窗口和图像大小旋转和缩放图像
- 如何旋转,调整大小和缩放图像从角落的画布
- Jquery自定义旋转木马内的图像缩放模式
- SVG旋转,缩放和翻译与鼠标
- 将横向iPad旋转为纵向iPad不会改变网页的缩放比例
- 缩放和旋转在拉斐尔.js
- js旋转,缩放不发生围绕对象的中心轴
- 仅在移动、缩放和旋转时渲染所选对象
- 当旋转或缩放改变时,在Raphaeljs中拖动路径
- 如何从矩阵SVG中提取位置,旋转和缩放