前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >在RenderTransform上叠加一个ScaleAt

在RenderTransform上叠加一个ScaleAt

作者头像
黄腾霄
发布2020-06-10 11:06:06
5410
发布2020-06-10 11:06:06
举报
文章被收录于专栏:黄腾霄的博客

试着想有这么一个场景,当你滚动滚轮时,图像会以你的鼠标中心为缩放中心进行缩放


代码很简单,就是在缩放时,获取鼠标对元素的相对坐标,调用ScaleAt,然后添加到它现有的RenderTransform

代码语言:javascript
复制
var position = e.GetPosition(TestGrid);
var scale =  + e.Delta / (double)Math.Abs(e.Delta) * 0.1;     
var matrix = TestGrid.RenderTransform.Value;
matrix.ScaleAt(scale, scale, position.X, position.Y);
TestGrid.RenderTransform = new MatrixTransform(matrix);

然而结果却出现了偏差,除了开始的几次正常之外,后续的行为都不正常。

意外的,只要将matrix.ScaleAt(scale, scale, position.X, position.Y);改为

matrix.ScaleAtPrepend(scale, scale, position.X, position.Y);就能正常使用。

我们都知道ScaleAtPrepend意味着矩阵左乘。

那为什么叠加不是右乘而是左乘呢?

再仔细看实际上,错误原因出在ScaleAtPrependScaleAt都是以RenderTransform之前的位置坐标进行的缩放,而我们期望的GetPosition(TestGrid)却是以RenderTransform之后的坐标。

了解了原因,我们只需要将position乘以现有的矩阵就可以了

代码语言:javascript
复制
var position = e.GetPosition(TestGrid);
var scale =  + e.Delta / (double)Math.Abs(e.Delta) * 0.1;     
var matrix = TestGrid.RenderTransform.Value;
var position2 = position * matrix;
matrix.ScaleAt(scale, scale, position2.X, position2.Y);
TestGrid.RenderTransform = new MatrixTransform(matrix);

现在也符合期望了。

但是我们还有一个问题,为什么以原来”错误”的坐标进行左乘也能得到正确的结果呢?

我做一个推导,假设$M$为原有的变化矩阵,$P_0$为变化前的点,$P_1$为变化后的点,

那么有$P_1=P_0M$

令$S_{p_0}$表示以$P_0$为中心的缩放矩阵,$S_{p_1}$表示以$P_1$为中心的缩放矩阵

那么对于任意点$P_n$

有$\begin{array}{lr} P_nMS_{P_1}=(P_nM+P_1)S-P_1\=(P_nM+P_0M)S-P_0M\=((P_n+P_0)S-P_0)M\=P_nS_{P_0}M\end{array} $

得证两种方式的结果是一致的。

参考项目仓库 https://github.com/xinyuehtx/ScaleWithPointer


本文会经常更新,请阅读原文: https://xinyuehtx.github.io/post/%E5%9C%A8RenderTransform%E4%B8%8A%E5%8F%A0%E5%8A%A0%E4%B8%80%E4%B8%AAScaleAt.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名黄腾霄(包含链接: https://xinyuehtx.github.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-07-15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档