Roc*_*lla 1 html javascript canvas transformation rotation
我想知道如何仅使用变换函数来旋转图像。根据我的理解,这是不可能的,因为您可以使用转换做的唯一事情如下:
来源:https ://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Transformations
我不知道其中任何一个如何能够旋转形状,这是否可能。我认为这一定是可能的,因为旋转实际上是一种类型转换。
变换是一组 6 个数字。6 个数字为 3 对,分别代表 x 轴的方向和比例、y 轴的方向和比例以及原点的位置。
默认变换(称为单位矩阵)的值ctx.setTransform(1, 0, 0, 1, 0, 0)
意味着
{x: 1, y: 0}
从左到右方向上每个 CSS 像素 1 个变换像素{x: 0, y: 1}
从上到下方向上每个 CSS 像素 1 个变换像素如果我们缩放变换,我们就会增加前两个向量的长度。要缩放 2,变换为ctx.setTransform(2, 0, 0, 2, 0, 0);
{x: 2, y: 0}
x 轴是 x 方向上从左到右每 2 个 CSS 像素 1 个变换像素{x: 0, y: 2}
y 轴是 y 方向从上到下每 2 个 CSS 像素 1 个变换像素如果我们想要将 256 x 256 的正方形图像旋转 90 度,则变换为ctx.setTransform(0, 1, -1, 0, 256, 0)
{x: 0, y: 1}
{x: -1, y: 0}
y 轴是从右到左负 x 方向上每个 CSS 像素 1 个变换像素因此如果我们运行
ctx.setTransform(0, 1, -1, 0, 256, 0);
ctx.drawImage(myImage, 0, 0, 256, 256); // will draw image rotated 90deg CW
Run Code Online (Sandbox Code Playgroud)
我们得到一个旋转的图像。
向量是具有 ax 和 y 值的两个值。该矢量定义方向和长度。
要将方向转换为向量,我们使用 sin 和 cos
const myDirection = angle;
const myDirectionAsRadians = angle * (Math.PI / 180); // convert angle to radians
const x = Math.cos(myDirectionAsRadians)
const y = Math.sin(myDirectionAsRadians)
Run Code Online (Sandbox Code Playgroud)
如果我们设置myDirection
为 90(度)然后x = 0
指向y = 1
画布
使用 sin 和 cos 可以创建任意方向的向量。它有一个特殊的属性,即它的长度始终为 1。我们将这样的向量称为单位向量。有时您可能会看到向量被标准化。这会将任意长度的向量转换为单位向量。它是通过将向量 x 和 y 除以它的长度来完成的。
function normalize(vector) {
const length = Math.hypot(vector.x, vector.y);
vector.x /= length;
vector.y /= length;
}
Run Code Online (Sandbox Code Playgroud)
注意,长度为零的向量x: 0, y:0
不能被归一化。不是因为它没有长度(长度为0)而是因为它没有方向。
我们可以定义角度和比例
const myDirection = -90;
const myDirectionAsRadians = -90 * (Math.PI / 180); // -90 as radians
const myScale = 2;
const x = Math.cos(myDirectionAsRadians) * myScale
const y = Math.sin(myDirectionAsRadians) * myScale
Run Code Online (Sandbox Code Playgroud)
现在,对于 -90 度,向量是x = 0
指向y = -2
上方且两个 CSS 像素长。
对于统一的缩放和旋转(图像始终是正方形),我们需要的只是一个向量。例如从上面的例子。x = 0
和y = -2
(指向上方)可以通过交换两个分量并否定新的 x 来顺时针旋转 90 度。例如xx = -y
,从左到右y = x
获取2 个 CSSxx = 2
像素。y = 0
这样我们就有了 x 轴和 y 轴的方向和比例。y 轴始终与 x 顺时针 90 度。
创建可旋转任意角度并缩放任意量的变换
function scaleAndRotate(scale, rotate) { // rotate is in radians
// get direction and length of x axis
const xAX = Math.cos(rotate) * scale;
const xAY = Math.sin(rotate) * scale;
// get direction and length of y axis that is 90 deg CW of x axis and same length
const [yAX, yAY] = [-xAY, xAX]; // swap and negate new x
// set the transform
ctx.setTransform(xAX, xAY, yAX, yAY, 0, 0);
}
Run Code Online (Sandbox Code Playgroud)
让我们创建一个函数,该函数将在画布上的任意位置绘制统一旋转和缩放的图像。我们将使用图像的中心作为参考点
function drawImageScaleRotate(img, x, y, scale, rotate) {
// define the direction and scale of x axis
const xAX = Math.cos(rotate) * scale;
const xAY = Math.sin(rotate) * scale;
// create the transform with yaxis at 90 CW of x axis and origin at x, y
ctx.setTransform(xAX, xAY, -xAY, xAX, x, y);
// Draw the image so that its center is at the new origin x, y
ctx.drawImage(img, -img.width / 2, -img.height / 2);
}
Run Code Online (Sandbox Code Playgroud)
当我们设置变换时,ctx.setTranform
我们替换现有的变换。此转换仍然有效。如果我们使用ctx.transform
, ctx.rotate
, ctx.scale
,ctx.translate
变换将应用于当前变换,您可以分阶段构建变换。
就 CPU 周期而言,转换函数相对昂贵。也就是说,使用 sin 和 cos 构建矩阵比使用ctx.scale
, ctx.rotate
,ctx.translate
从默认值开始执行相同的操作要快得多。
构建转换可能会变得很棘手,因为我们需要跟踪我们所处的阶段。
我们通常只使用这些函数来创建链接的变换,而不是变换单个图像(文本、路径或其他图像)。
例如坦克等游戏对象。坦克的车体发生变形(旋转和定位),然后炮塔随车体旋转,但通过使用具有额外的独立旋转ctx.rotate
。完整的解释超出了这个问题的范围。
由此我们可以创建一个简化的函数,该函数将绘制一个以任意位置为中心的图像,并且统一缩放和旋转
function drawImageScaleRotate(img, x, y, scale, rotate) {
const xAX = Math.cos(rotate) * scale;
const xAY = Math.sin(rotate) * scale;
ctx.setTransform(xAX, xAY, -xAY, xAX, x, y);
ctx.drawImage(img, -img.width / 2, -img.height / 2);
}
Run Code Online (Sandbox Code Playgroud)
要将转换重置为默认值,请使用ctx.resetTransform
“注释”尚未完全支持或使用ctx.setTransform(1,0,0,1,0,0);
使用上述函数是绘制动画旋转缩放图像的第二快方法,比 CSS + HTML 或 SVG 更快。您实际上可以用动画图像填充屏幕。
ctx.setTransform(0, 1, -1, 0, 256, 0);
ctx.drawImage(myImage, 0, 0, 256, 256); // will draw image rotated 90deg CW
Run Code Online (Sandbox Code Playgroud)
如果您想知道哪种是绘制动画内容最快的方法。那是通过 webGL。以上可以在大多数设备上以良好的帧速率绘制 1000 个缩放旋转图像。WebGL 可以轻松地同时绘制 10000 个(具有额外功能,例如彩色)。
归档时间: |
|
查看次数: |
2229 次 |
最近记录: |