- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
我有一个 3x3 矩阵 (startMatrix),它表示图像的实际 View (平移、旋转和缩放)。现在我创建一个新矩阵 (endMatrix),它有一个恒等矩阵、新的 x 和 y 坐标、新的 Angular 和新的比例,例如:
endMatrix = translate(identityMatrix, -x, -y);
endMatrix = rotate(endMatrix, angle);
endMatrix = scale(endMatrix, scale);
endMatrix = translate(endMatrix,(screen.width/2)/scale,screen.height/2)/scale);
和功能(标准的东西)
function scale(m,s) {
var n = new Matrix([
[s, 0, 0],
[0, s, 0],
[0, 0, s]
]);
return n.multiply(m);
}
function rotate(m, theta) {
var n = new Matrix([
[Math.cos(theta), -Math.sin(theta), 0],
[Math.sin(theta), Math.cos(theta), 0],
[0, 0, 1]
]);
return n.multiply(m);
}
function translate(m, x, y) {
var n = new Matrix([
[1, 0, x],
[0, 1, y],
[0, 0, 1]
]);
return n.multiply(m);
}
之后,我使用 css transform matrix3d(3d 仅用于硬件加速)转换图像。此转换使用 requestAnimationFrame 进行动画处理.
以我的startMatrix为例
和 endMatrix
线性组合看起来像:
t 从 0 到 1
变换矩阵线性组合的结果(得到的图像位置)是正确的,我现在的问题是:如果新 Angular 与实际 Angular 相差大约180度,则endMatrix值由正变为负(或另一种方式)。这会导致转换图像的动画中出现放大缩小效果。
有没有办法通过使用一个矩阵进行转换来防止这种情况发生?
最佳答案
如果您直接对矩阵值进行插值,将会出现问题,对于非常小的 Angular ,无法观察到不准确,但从长远来看,您将面临问题。即使您对矩阵进行归一化,更大的 Angular 也会使问题在视觉上变得明显。
2D 旋转非常简单,因此无需旋转矩阵方法也能很好地完成。最好的方法可能是使用四元数,但四元数可能更适合 3D 转换。
要采取的步骤是:
在动画开始时,您必须计算一次第 1 步的值,然后在每一帧应用第 2 步和第 3 步。
第一步:获取旋转、缩放、变换
假设起始矩阵为S,结束矩阵为E。
转换值只是最后一列,例如
var start_tx = S[0][2];
var start_ty = S[1][2];
var end_tx = E[0][2];
var end_ty = E[1][2];
例如,非倾斜 2D 矩阵的比例只是矩阵所跨越空间中任一基向量的长度
// scale is just the length of the rotation matrixes vector
var startScale = Math.sqrt( S[0][0]*S[0][0] + S[1][0]*S[1][0]);
var endScale = Math.sqrt( E[0][0]*E[0][0] + E[1][0]*E[1][0]);
最难的部分是获取矩阵的旋转值。好处是每次插值只需计算一次。
两个二维矩阵的旋转 Angular 可以根据矩阵列所创建的向量之间的 Angular 来计算。如果没有旋转,第一列的值 (1,0) 表示 x 轴,第二列的值 (0,1) 表示 y 轴。
一般矩阵S的x轴位置表示为
(S[0][0], S[0][1])
y轴指向方向
(S[1][0], S[1][1])
对于任何 2D 3x3 矩阵都是一样的,比如 E。
使用此信息,您可以仅使用标准向量数学来确定两个矩阵之间的旋转 Angular - 如果我们假设没有倾斜。
// normalize column vectors
var s00 = S[0][0]/ startScale; // x-component
var s01 = S[0][1]/ startScale; // y-component
var e00 = E[0][0]/ endScale; // x-component
var e01 = E[0][1]/ endScale; // y-component
// calculate dot product which is the cos of the angle
var dp_start = s00*1 + s01*0; // base rotation, dot prod against x-axis
var dp_between = s00*e00 + s01*e01; // between matrices
var startRotation = Math.acos( dp_start );
var deltaRotation = Math.acos( dp_between );
// if detect clockwise rotation, the y -comp of x-axis < 0
if(S[0][1]<0) startRotation = -1*startRotation;
// for the delta rotation calculate cross product
var cp_between = s00*e01 - s01*e00;
if(cp_between<0) deltaRotation = deltaRotation*-1;
var endRotation = startRotation + deltaRotation;
此处 startRotation 仅根据矩阵第一个值的 acos 计算得出。然而,第二列的第一个值,即 -sin(angle) 大于零,则矩阵已顺时针旋转, Angular 必须为负。必须这样做,因为 acos 只给出正值。
另一种思考方式是考虑叉积 s00*e01 - s01*e00,其中起始位置 (s00,s01) 是 x 轴,其中 s00 == 1 和 s01 == 0 以及结束位置 (e00, e01 ) 是 ( S[0][0], S[0][1] ) 创建叉积
1 * S[0][1] - 0 * S[0][0]
这是 S[0][1]。如果该值为负,则 x 轴已转向顺时针方向。
对于 endRotation,我们需要从 S 到 E 的增量旋转。这可以通过矩阵跨越的向量之间的点积类似地计算。同样,我们测试叉积以查看旋转方向是否为顺时针(负 Angular )。
第 2 步:插值
在动画期间获取新值是微不足道的插值:
var scale = startScale + t*(endScale-startScale);
var rotation = startRotation + t*(endRotation-startRotation);
var tx = start_tx + t*(end_tx-start_tx);
var ty = start_ty + t*(end_ty-start_ty);
第三步构造矩阵
对于每一帧构建最终矩阵,您只需将值放入转换矩阵矩阵
var cs = Math.cos(rotation);
var sn = Math.sin(rotation);
var matrix_values = [[scale*cs, -scale*sn, tx], [scale*sn, scale*cs, ty], [0,0,1]]
然后你有一个 2D 矩阵,它也很容易为任何 3D 硬件加速器提供数据。
免责声明:部分代码已经过测试,部分代码尚未经过测试,因此很可能会发现错误。
关于javascript - 变换矩阵线性组合的旋转动画导致放大缩小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35914137/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
我正在尝试创建一个可以像在 Excel 中一样放大和缩小的 QTableView。 此处提出了类似的问题:Zooming function on a QWidget 但是,我在 PyQt 而不是 C
如图所示。 我在 QScrollArea 中有 QWidget。QWidget 充当细胞图像和一些基于矢量的轮廓数据的渲染小部件。用户可以执行放大/缩小操作,简单地发生的是,它改变了 QPaint
双击 MKMapView 时:放大。 但是如何缩小呢? 最佳答案 总是使用两根手指来放大和缩小。在模拟器上,您需要按住选项键才能在模拟屏幕上显示“两根手指”(我认为这是 Alt 键,但我在 Mac 上
我有一些 javascript for {} 循环,我在整个项目中重复使用它们,它们都类似于: for (var i = 0; i < things.length; i++) { consol
我知道我可以使用C-x C- +进行放大/缩小,但这仅适用于当前文件。一旦我打开另一个文本,文本将恢复为默认值,一遍又一遍地做起来真的很累。如何保持当前emacs session 的全局缩放级别? 如
我对使用编译器工具自动化/简化 Angular 项目感兴趣,这可能适用于其他所有事情,但 Angular 注入(inject)和命名空间很尴尬,足以逃避编译器知识。执行此操作的最佳/专业方法是什么?
有没有办法在emacs上放大和缩小(动态改变字体大小,相当流畅)? 最佳答案 尝试 C-x C-+ 和 C-x C--;即 Control-x Control-减号/Control-再加上。 在一个组
我有一个Windows表单对象,其中包含3个对象,树 View ,richtextbox和tabcontrol。它们没有停靠在Windows窗体中,而是被 anchor 定(顶部+左侧)。 我已经编写
我想向 javascript-mode 添加功能,以便每当我在当前缓冲区上保存 Javascript 文件时,它都会在使用相对路径定义的目录中创建该文件的缩小文件,例如 ../foo 具有相同的文件名
这里有一些关于缩小.war文件的教程,甚至一些帖子。但是,最常见的技术(在Config.groovy中包含grails.war.resources = {})似乎对我不起作用。无论如何,grails会
如何使用 ScaleTransition缩小图像?我现在有这个,它只能放大。如果我误解了该方法,我不会,但我将其从 1 缩放到 0.8。由于某种原因,这种情况仍在扩大。 ScaleTransition
基本上,我想问ReplicaSets是否与CronJobs的suspend: "true"选项类似,但我愿意接受其他建议。 最佳答案 From the official Kubernetes doc
我想使用 boost::polygon 扩展/收缩带孔的多边形。所以澄清一点,我有一个单一的数据结构 boost::polygon::polygon_with_holes_data inPoly 其中
我有一个 map 列表: [%{~D[2019-02-11] => 7}, %{~D[2019-02-12] => 1}, %{~D[2019-02-15] => 1}] 我正在尝试将其变成一张大
我正在制作一个横幅,您可以使用jquery幻灯片功能缩放图像并且可以拖动图像。 除了一件事之外,它工作完美。当您使用图像下方的幻灯片放大图像时,效果非常好。您可以将图像拖动到您想要的位置。但当你想用幻
我们有一个 extjs 应用程序,其中我们布置的结构与 Sencha 推荐的结构不完全匹配。在我们的结构中,我们没有 app.js,但我们有一个 js,其中我们提到了自动加载和启动功能,示例如下以及文
我想在 Chrome/Firefox 中运行的应用程序是: 用 typescript 写 使用 React 使用 es 下一个功能(模块、导入等)编写 有一些导入是纯 js 文件 网页包 3 我可以在
我正在尝试像此处一样应用 Google map 的放大/缩小 - https://www.google.com/maps/@36.241201,-98.1261798,5.13z?hl=en我无法让它
我正在使用 Protractor ,需要缩小到 50%,我尝试了 StackOverflow 上发布的其他几个问题的解决方案,但没有任何效果。其中一些包括: browser.actions().key
我是一名优秀的程序员,十分优秀!