无处不在的前端矩阵变换(上)

简介: 在前端开发中不论CSS3也好,SVG也好,还是Canvas,无论多复杂的图形,都是由一个个点组成的。一个元素渲染后就可以得到一张位图,然后对这个位图上每一点进行变换,就可以得到新的一张位图,从而产生了视觉上的平移translate、旋转rotate、缩放scale、拉伸skew 等效果。这一切都是变换矩阵的功劳。

2d与3d矩阵变换公式



CSS3中的2d矩阵变换


  • CSS3中的 transform: translate(tx, ty) 等价于 transform: matrix(1,0,0,1,tx,ty)


  • CSS3中的 transform:rotate(θ) 等价于 transform: matrix(cosθ,sinθ,-sinθ,cosθ,0,0)


  • CSS3中的 transform: scale(Sx, Sy) 等价于 transform: matrix(Sx,0,0,Sy,0,0)


  • CSS 3中的 transform: skew(θx,θy) 等价于 transform:matrix(tan(θx),0,0,tan(θy),0,0)


CSS3中的3d矩阵变换


给个简单的demo,利用CSS3动画库 bounce.js 通过设置元素属性 transform:matrix3d (1-16位参数值) 让元素偏移 200px。 从matrix三阶矩阵到matrix3d四阶矩阵,本质上很多东西都与2D大同小异,只是复杂度不一样而已。


<!--dom-->
<div class="animation-target"></div>
<!--css代码-->
.animation-target {
  background-color: #333;
  height: 100px;
  width: 100px;
}
<!--js代码-->
let bounce = new Bounce();
bounce.translate({
  from: { x: 0 },
  to: { x: 200 }
})
bounce.applyTo(document.querySelector('.animation-target'))
/*
   bounce.js 其余scale、rotate、skew等api最终都是通过transform:matrix3d(1-16位参数值)来实现元素的动画效果
*/


效果图如下:matrix3d对应的矩阵运算细节可参考 bounce.js



svg中的矩阵变换


svg中的变换原理和css3中的类似,但是在svg中没有相关的属性来设置变换的中心点,只能通过translate来模拟。如下设置transform-origin是不生效的


<!--dom-->
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100" height="190">
   <rect id="SvgjsRect1008" width="100" height="100" transform-origin="0% 0%" transform="translate(100, 0)"></rect>
</svg>
/*
   transform-origin="0% 0%" 设置是不生效的
*/


下面结合SVG.js 这个开源库来看下svg中的矩阵变换应用


<!--dom 作为SVG.js的挂载节点-->
<div id="drawing"></div>
<!--js-->
let draw = SVG('drawing').size(300, 300)
let rect = draw.rect(100, 100)
rect.rotate(45)  // 旋转45度


如图:



那么rect.rotate(45) 是怎么变成 上图中的 matrix 的呢? 如下:


<!--SVG.js 中的关键代码截取-->
rect.rotate(45)
=>
rotate: function(d, cx, cy) {
 return this.transform({ rotation: d, cx: cx, cy: cy })
}
transform: function(o, relative) {
 var target = this, matrix; // this 通过SVG.js new 出的一个react实例对象 
 matrix = new SVG.Matrix(target) // 获取当前元素的transform: matrix矩阵值,具体实现可以查阅SVG.js源码
 ... 此处省略部分代码
 ensureCentre(o, target)  // 通过svg原生api, element.node.getBBox()来计算元素的中心点o
  // 应用矩阵
  matrix = relative ? 
    // relative
    matrix.rotate(o.rotation, o.cx, o.cy) :
    // absolute
    matrix.rotate(o.rotation - matrix.extract().rotation, o.cx, o.cy)
}
rotate: function(r, cx, cy) {
  // convert degrees to radians
  r = SVG.utils.radians(r)
  // 计算对应的旋转矩阵, 对应a,b,c,d,e,f值如下
  return this.around(cx, cy, new SVG.Matrix(Math.cos(r), Math.sin(r), -Math.sin(r), Math.cos(r), 0, 0))
}
// Transform around a center point 以中心点来进行旋转
around: function(cx, cy, matrix) {
 //这里很重要:svg以某个参考点变换时 => 通过先平移translate(cx,cy), 然后transform目标matrix值, 再进行反平移translate(-cx,-cy)
 return this
   .multiply(new SVG.Matrix(1, 0, 0, 1, cx || 0, cy || 0))
   .multiply(matrix)
   .multiply(new SVG.Matrix(1, 0, 0, 1, -cx || 0, -cy || 0))
}
multiply: function(matrix) {
  // 这里是把元素当前的transform: matrix属性值与目标矩阵相乘
  return new SVG.Matrix(this.native().multiply(parseMatrix(matrix).native()))
}
native: function() { 
  // SVG.js 中的矩阵相乘, 利用的是svg元素的原生api, createSVGMatrix()来实现
  // create new matrix
  var matrix = SVG.parser.native.createSVGMatrix()
  // update with current values
  for (var i = abcdef.length - 1; i >= 0; i--)
    matrix[abcdef[i]] = this[abcdef[i]]
  return matrix
}
//最后把最终计算的matrix变换值设置到react元素上就完成了
this.attr('transform', matrix)


相关文章
|
前端开发
无处不在的前端矩阵变换(下)
在前端开发中不论CSS3也好,SVG也好,还是Canvas,无论多复杂的图形,都是由一个个点组成的。一个元素渲染后就可以得到一张位图,然后对这个位图上每一点进行变换,就可以得到新的一张位图,从而产生了视觉上的平移translate、旋转rotate、缩放scale、拉伸skew 等效果。这一切都是变换矩阵的功劳。
|
4月前
|
Web App开发 缓存 前端开发
前端性能优化的整理笔记(一)
前端性能优化的整理笔记(一)
150 0
|
14天前
|
SpringCloudAlibaba JavaScript 前端开发
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架
分布式组件、nacos注册配置中心、openfegin远程调用、网关gateway、ES6脚本语言规范、vue、elementUI
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架
|
1月前
|
存储 前端开发 JavaScript
前端语言串讲 | 青训营笔记
前端语言串讲 | 青训营笔记
25 0
|
3月前
|
JSON 前端开发 JavaScript
前端Ajax、Axios和Fetch的用法和区别笔记
前端Ajax、Axios和Fetch的用法和区别笔记
71 2
|
3月前
|
前端开发 JavaScript 数据库
如何实现前后端分离-----前端笔记
如何实现前后端分离-----前端笔记
|
3月前
|
前端开发 安全 NoSQL
技术笔记:Security前端页面配置
技术笔记:Security前端页面配置
|
4月前
|
存储 前端开发 JavaScript
前端笔记_OAuth规则机制下实现个人站点接入qq三方登录
前端笔记_OAuth规则机制下实现个人站点接入qq三方登录
76 1
|
4月前
|
移动开发 前端开发 JavaScript
10款精美的web前端源码的特效,2024年最新面试题+笔记+项目实战
10款精美的web前端源码的特效,2024年最新面试题+笔记+项目实战
|
4月前
|
前端开发 容器
CSS3属性详解(一)文本 盒模型中的 box-ssize 属性 处理兼容性问题:私有前缀 边框 背景属性 渐变 前端开发入门笔记(七)
CSS3属性详解(一)文本 盒模型中的 box-ssize 属性 处理兼容性问题:私有前缀 边框 背景属性 渐变 前端开发入门笔记(七)
69 2