如何在一堆变换后获得原点的屏幕坐标 P5.js
How do I get the screen coordinates of origin after a bunch of transforms P5.js
我正在尝试追踪一个物体的位置,以便我可以在 p5.js
中在它后面画一条轨迹。
我正在使用 translate()
和 rotate()
函数在屏幕上移动对象,为了绘制轨迹,我打算在每次更新后将对象的位置存储在数组中.我知道在处理 3 the model X, Y and Z functions
中有一些类似我要求的东西,但据我所知,这些还没有在 javascript 版本中实现。
即使访问 canvas 的当前变换矩阵也被证明是有问题的,此时我正在考虑重新设计以省略 api 的变换部分,直到添加此功能。
所以我的问题基本上是:有没有办法在应用一堆变换后确定 (0, 0) 的屏幕 (canvas) 坐标?
我这里有这个问题的解决方案:
您应该在 push() 和 pop() 中进行所有转换,并将位置存储在它本身内部,以便获取位置每帧推入数组。
不,你不能在一系列变换后得到 (0,0) 的 canvas 坐标,因为 translate 将 canvas 的原点 (0,0) 移动到一个新的点,然后该点成为新的原点。
要绘制轨迹,您可以将对象位置向量的历史记录存储在一个数组中。你可以在你的动画对象的更新函数中实现它class。为此,您可以存储 P5Vector(this.pos.x, this.pos.y) 并在绘制循环中每次调用该函数时将其推入数组,然后您可以为遍历此数组的轨迹画一个圆或一条线。
假设history是一个包含动画对象最后100个位置(矢量对象)的数组,在绘制循环中你可以:
for(var i=0; i<obj.history.length; i++)
{
var loc = obj.history[i];
ellipse(loc.x, loc.y, 15, 15);
}
drawingContext实际上跟踪这个,你可以查询它并映射回p5坐标。如果您在内部循环中不需要它,那么它可能比跟踪额外堆栈中的所有内容更便宜,这与 Canvas 引擎正在做的事情并行。这是由规范定义的,因此您可以依赖它。
https://html.spec.whatwg.org/multipage/canvas.html#transformations(参见本章末尾定义转换语义的地方)。
2D 版本:
// a c e
// b d f
// 0 0 1
// x_new = a x + c y + e
// y_new = b x + d y + f
// origin - current point - is then at:
// x = a.0 + c.0 + e = e
// y = b.0 + c.0 + f = f
// However, the context has media coordinates, not p5. taking
// the distance between points lets use determine the
// scale assuming x and y scaling is the same.
let matrix = drawingContext.getTransform();
let x_0 = matrix['e'];
let y_0 = matrix['f'];
let x_1 = matrix['a'] + matrix['e'];
let y_1 = matrix['b'] + matrix['f'];
let media_per_unit = dist(x_0, y_0, x_1, y_1);
let p5_current_x = x_0 / media_per_unit;
let p5_current_y = y_0 / media_per_unit;
我正在尝试追踪一个物体的位置,以便我可以在 p5.js
中在它后面画一条轨迹。
我正在使用 translate()
和 rotate()
函数在屏幕上移动对象,为了绘制轨迹,我打算在每次更新后将对象的位置存储在数组中.我知道在处理 3 the model X, Y and Z functions
中有一些类似我要求的东西,但据我所知,这些还没有在 javascript 版本中实现。
即使访问 canvas 的当前变换矩阵也被证明是有问题的,此时我正在考虑重新设计以省略 api 的变换部分,直到添加此功能。
所以我的问题基本上是:有没有办法在应用一堆变换后确定 (0, 0) 的屏幕 (canvas) 坐标?
我这里有这个问题的解决方案:
您应该在 push() 和 pop() 中进行所有转换,并将位置存储在它本身内部,以便获取位置每帧推入数组。
不,你不能在一系列变换后得到 (0,0) 的 canvas 坐标,因为 translate 将 canvas 的原点 (0,0) 移动到一个新的点,然后该点成为新的原点。
要绘制轨迹,您可以将对象位置向量的历史记录存储在一个数组中。你可以在你的动画对象的更新函数中实现它class。为此,您可以存储 P5Vector(this.pos.x, this.pos.y) 并在绘制循环中每次调用该函数时将其推入数组,然后您可以为遍历此数组的轨迹画一个圆或一条线。
假设history是一个包含动画对象最后100个位置(矢量对象)的数组,在绘制循环中你可以:
for(var i=0; i<obj.history.length; i++)
{
var loc = obj.history[i];
ellipse(loc.x, loc.y, 15, 15);
}
drawingContext实际上跟踪这个,你可以查询它并映射回p5坐标。如果您在内部循环中不需要它,那么它可能比跟踪额外堆栈中的所有内容更便宜,这与 Canvas 引擎正在做的事情并行。这是由规范定义的,因此您可以依赖它。
https://html.spec.whatwg.org/multipage/canvas.html#transformations(参见本章末尾定义转换语义的地方)。
2D 版本:
// a c e
// b d f
// 0 0 1
// x_new = a x + c y + e
// y_new = b x + d y + f
// origin - current point - is then at:
// x = a.0 + c.0 + e = e
// y = b.0 + c.0 + f = f
// However, the context has media coordinates, not p5. taking
// the distance between points lets use determine the
// scale assuming x and y scaling is the same.
let matrix = drawingContext.getTransform();
let x_0 = matrix['e'];
let y_0 = matrix['f'];
let x_1 = matrix['a'] + matrix['e'];
let y_1 = matrix['b'] + matrix['f'];
let media_per_unit = dist(x_0, y_0, x_1, y_1);
let p5_current_x = x_0 / media_per_unit;
let p5_current_y = y_0 / media_per_unit;