移动端二三事【三】:transform的注意事项
*每当在DOM浏览器中增加动态效果时,使用强大的transform和transition,总是很酸爽。抛开css,使用js操作transform还真的有点复杂,涉及到线性代数中的矩阵,但是js操作又不可避免的会用到。俗话说,山水有相逢,早日学会,早日总结,方便以后用到。今天就与大家分享一下,transform的注意事项以及transform矩阵操作的一些技巧。
*首先说一些小的注意事项,硬菜在后面!
1.js操作transition时需使用驼峰命名增加前缀:
div.style.WebkitTransform = div.style.transform = "rotate(90deg)";
2.多个transition操作的执行顺序:先写的后后执行
以下以两个div为例,点击后执行不同的过渡效果:
div[0].addEventListener('touchend', function(e) {
this.style.WebkitTransform = this.style.transform = "scale(.5) translateX(100px)";
});
div[1].addEventListener('touchend', function(e) {
this.style.WebkitTransform = this.style.transform = "translateX(100px) scale(.5)";
});
初始 效果:

点击后的效果:

页面代码如下,可自己拎下来运行:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,user-scalable=no" />
<title>执行顺序</title>
<style type="text/css">
#box {
width: 100px;
border: 1px solid #000;
padding: 100px;
}
.div {
width: 100px;
height: 100px;
margin: 10px 0;
background: red;
transition: 3s;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
}
</style>
<script type="text/javascript">
document.addEventListener('touchstart', function(e) {
e.preventDefault();
});
window.onload = function(){
var div = document.querySelectorAll('.div');
div[0].addEventListener('touchend', function(e) {
this.style.WebkitTransform = this.style.transform = "scale(.5) translateX(100px)";
});
div[1].addEventListener('touchend', function(e) {
this.style.WebkitTransform = this.style.transform = "translateX(100px) scale(.5)";
});
};
</script>
</head>
<body>
<div id="box">
<div class="div"></div>
<div class="div"></div>
</div>
</body>
</html>
3.移动端在操作结点位置时,尽量使用translate,而操作left或margin等都会引起页面回流(reflow),我们要做的就是尽可能地避免回流,尽可能的减少重绘。
举个栗子使用translate模拟垂直滚动条:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>垂直滚动</title>
<meta name="viewport" content = "width=device-width,user-scalable=no">
<style type="text/css">
body {
margin: 0;
}
html,
body {
overflow: hidden;
height: 100%;
position: relative;
}
header{
height: 40px;
background: #000;
color: #fff;
text-align: center;
font-size: 20px;
line-height: 40px;
}
#wrap {
position: absolute;
left: 0;
right: 0;
top: 40px;
bottom: 0px;
overflow: hidden;
}
#list {
margin: 0;
padding: 0;
list-style: none;
}
#list li {
height: 30px;
border-bottom: 1px solid #000;
line-height: 30px;
text-indent: 20px;
}
</style>
<script type="text/javascript">
document.addEventListener("touchstart",function(e){
e.preventDefault();
});
function setListInner(){
var list = document.querySelector('#list');
var inner = "";
for(var i = 0; i < 100; i++){
inner += "<li>这是第"+i+"个li</li>"
}
list.innerHTML = inner;
}
window.onload = function(){
setListInner();
var wrap = document.querySelector('#wrap');
var list = document.querySelector('#list');
var startPoint = 0;
var startEl = 0;
var elTranslateY = 0;
list.addEventListener('touchstart', function(e) {
startPoint = e.changedTouches[0].pageY;
startEl = elTranslateY;
});
list.addEventListener('touchmove', function(e) {
var nowPoint = e.changedTouches[0].pageY;
var dis = nowPoint - startPoint;
elTranslateY = startEl + dis;
list.style.WebkitTransform = list.style.transform = "translateY("+elTranslateY+"px)";
});
};
</script>
</head>
<body>
<header>垂直滚动</header>
<div id="wrap">
<ul id="list"></ul>
</div>
</body>
</html>
4.矩阵操作
大家都知道当使用js获取transform时获取的是一个矩阵:
div[0].style.WebkitTransform = div[0].style.transform = "scale(.5) translateX(100px)";
//最终样式才能获取到transform的矩阵参数字符串
console.log(getComputedStyle(div[0])["transform"]); // matrix(0.5, 0, 0, 0.5, 50, 0)
console.log( typeof (getComputedStyle(div[0])["transform"])); // string
console.log(div[0].style.transform); // scale(0.5) translateX(100px)
console.log(typeof (div[0].style.transform)); // string
*矩阵参数对应的变量:
matrix( a, b, c, d, e, f ),基础值为:
matrix( 1, 0, 0, 1, 0, 0 )
基础效果如下:

1.改变位移:
//位移:
//x为轴位移量,y为y轴位移量,可使用负数
//x轴位移 = e + x;
//y轴位移 = f + y;
//如下为左移100像素,下移50像素
div[0].style.transform = "matrix(1, 0, 0, 1, -100, 50)";
改变位移效果:

2.缩放:
(1) x轴缩放:操作变量a,c,e
//x轴:
//a = a*x;
//c = c*x;
//e = e*x;
//x为缩放倍数
div[0].style.transform = "matrix(.5, 0, 0, 1, 0, 0)";
x轴缩放0.5效果:

(2)y轴缩放:操作变量b,d,f
//y轴:
//b = b*x;
//d = d*x;
//f = f*x;
div[0].style.transform = "matrix(1, 0, 0, .5, 0, 0)";
y轴缩放后效果:

由此就可以解释,在使用css命令时的执行顺序问题:
//先执行matrix(.5, 0, 0, 1, 0, 0)
//后执行matrix(.5, 0, 0, 1, 100, 0)
div[0].style.transform = "scaleX(.5) translateX(100px)";
//先执行matrix(1, 0, 0, 1, 100, 0)
//后执行matrix(.5, 0, 0, 1, 50, 0)
div[0].style.transform = "translateX(100px) scaleX(.5)";
3.斜切:
(1)x轴斜切:
//x轴斜切30度:单位(deg)
//操作参数c,修改参数时需要转化为弧度
//弧度 = Math.tan(角度/180*Math.PI);
div[0].style.transform = "matrix(1, 0, "+Math.tan(30/180*Math.PI)+", 1, 0, 0)";
效果如下:

(2)y轴斜切:
//y轴斜切30度:单位(deg)
//操作参数b,修改参数时需要转化为弧度
div[0].style.transform = "matrix(1,"+Math.tan(30/180*Math.PI)+",0, 1, 0, 0)";
效果如下:

4.旋转rotate:
//旋转:
//修改a,b,c,d四个参数
var a = Math.cos(45/180*Math.PI);
var b = Math.sin(45/180*Math.PI);
var c = -Math.sin(45/180*Math.PI);
var d = Math.cos(45/180*Math.PI);
div[0].style.transform = "matrix("+ a +","+ b +","+ c +","+ d +",0,0)";
效果如下:

5.transform操作函数封装
若现在有这么一个需求,每次点击div后,使其旋转30deg,那么我们是无法直接操作transform完成的,通过js修改操作css的transform无法记录当前的状态(旋转角度等)。因此需要转换思想进行函数封装,封装的原理是添加自定义属性,再利用自定义属性为相应结点添加transform。
function cssTransform(element, attr, val){
if(!element.transform){
element.transform = {};
}
if(typeof val === "undefined"){
if(typeof element.transform[attr] === "undefined"){
switch(attr){
case "scale":
case "scaleX":
case "scaleY":
case "scaleZ":
element.transform[attr] = 100;
break;
default:
element.transform[attr] = 0;
}
}
return element.transform[attr];
} else {
element.transform[attr] = val;
var transformVal = "";
for(var s in element.transform){
switch(s){
case "scale":
case "scaleX":
case "scaleY":
case "scaleZ":
transformVal += " " + s + "("+(element.transform[s]/100)+")";
break;
case "rotate":
case "rotateX":
case "rotateY":
case "rotateZ":
case "skewX":
case "skewY":
transformVal += " " + s + "("+element.transform[s]+"deg)";
break;
default:
transformVal += " " + s + "("+element.transform[s]+"px)";
}
}
element.style.WebkitTransform = element.style.transform = transformVal;
}
}
注意!如果要获取transform相关的属性,那transform相关的设置 也必须是通过该方法设置的!
利用封装的函数,就可以完成刚才的需求。完整的代码如下,可自行运行查看效果:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,user-scalable=no" />
<title>点击旋转30deg</title>
<style type="text/css">
#box {
width: 100px;
height: 100px;
border: 1px solid #000;
padding: 100px;
}
#div {
height: 100px;
background: red;
transition: .5s;
}
</style>
<script type="text/javascript">
function cssTransform(element, attr, val){
if(!element.transform){
element.transform = {};
}
if(typeof val == "undefined"){
if(!element.transform[attr]){
switch(attr){
case "scale":
case "scaleX":
case "scaleY":
case "scaleZ":
element.transform[attr] = 100;
break;
default:
element.transform[attr] = 0;
}
}
return element.transform[attr];
} else {
element.transform[attr] = val;
var transformVal = "";
for(var s in element.transform){
switch(s){
case "scale":
case "scaleX":
case "scaleY":
case "scaleZ":
transformVal += " " + s + "("+(val/100)+")";
break;
case "rotate":
case "rotateX":
case "rotateY":
case "rotateZ":
case "skewX":
case "skewY":
transformVal += " " + s + "("+val+"deg)";
break;
default:
transformVal += " " + s + "("+val+"px)";
}
}
element.style.WebkitTransform = element.style.transform = transformVal;
}
}
window.onload = function(){
var div = document.querySelector('#div');
div.addEventListener('touchend', function(e) {
var deg = cssTransform(this, "rotate");
deg += 30;
cssTransform(this, "rotate", deg);
});
};
</script>
</head>
<body>
<div id="box">
<div id="div"></div>
</div>
</body>
</html>
移动端二三事【三】:transform的注意事项的更多相关文章
- 移动端二三事【三】:transform的矩阵(matrix)操作、transform操作函数及注意事项
*每当在DOM浏览器中增加动态效果时,使用强大的transform和transition,总是很酸爽.抛开css,使用js操作transform还真的有点复杂,涉及到线性代数中的矩阵,但是js操作又不 ...
- WinForm二三事(三)Control.Invoke&Control.BeginInvoke
http://www.cnblogs.com/yuyijq/archive/2010/01/11/1643802.html 这个系列从2009年写到2010年,差点又成太监文.随着WPF/Silver ...
- Java并发编程二三事
Java并发编程二三事 转自我的Github 近日重新翻了一下<Java Concurrency in Practice>故以此文记之. 我觉得Java的并发可以从下面三个点去理解: * ...
- linux杂记(十二?) 关于账号和密码的二三事
关于密码的二三事 关于账号和密码的二三事 久了不更linux的相关知识,实在是懒得想内容点(纯粹是懒).那么今天就来谈谈关于linux密码和账号的重要概念. 假如你的主机遭到入侵,那么对方的第一个侵入 ...
- {Django基础八之cookie和session}一 会话跟踪 二 cookie 三 django中操作cookie 四 session 五 django中操作session
Django基础八之cookie和session 本节目录 一 会话跟踪 二 cookie 三 django中操作cookie 四 session 五 django中操作session 六 xxx 七 ...
- Emacs 启动优化二三事
Emacs 启动优化二三事 */--> div.org-src-container { font-size: 85%; font-family: monospace; } p {font-siz ...
- docker-compose一键部署redis一主二从三哨兵模式(含密码,数据持久化)
本篇基于centos7服务器进行部署开发 一.拉取redis镜像,使用如下命令 docker pull redis 1.查看镜像是否拉取成功,使用如下命令 docker images 显示如下则证明拉 ...
- 【C#夯实】我与接口二三事:IEnumerable、IQueryable 与 LINQ
序 学生时期,有过小组作业,当时分工一人做那么两三个页面,然而在前端差不多的时候,我和另一个同学发生了争执.当时用的是简单的三层架构(DLL.BLL.UI),我个人觉得各写各的吧,到时候合并,而他觉得 ...
- [Java面经] 关于面试的二三事.
今天终于闲下来了, 那么也好总结下这几天面试的经历.四天的时间一共面了七家, 有一家是自己推迟了没有去.声明:如若转载请注明出处:http://www.cnblogs.com/wang-meng/p/ ...
随机推荐
- 你的专属定制——JQuery自定义插件
前 言 絮叨絮叨 jQuery是一个快速.简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架).jQuery设计的宗 ...
- thinkphp5.0无限极分类及格式化输出
首先我们来看数据表 从上图中可以发现,中国下有贵州,北京两个子节点,而北京有天安门一个子节点,纽约的子节点是"纽约的子类". 从pid为0看出,中国和纽约是顶级节点. 因为贵州的p ...
- 基于 Electron 的爬虫框架 Nightmare
作者:William 本文为原创文章,转载请注明作者及出处 Electron 可以让你使用纯 JavaScript 调用 Chrome 丰富的原生的接口来创造桌面应用.你可以把它看作一个专注于桌面应用 ...
- redhat下yum命令安装(替换为centos yum命令)
redhat默认自带的yum源需要注册,才能更新,报错:This system is not registered to Red Hat Subscription Management. You ca ...
- 翻译:MLAPP(2.1节)
笔者:尝试翻译MLAPP(Machine Learning: a Probabilistic Perspective)一书,供机器学习的学者参考,如有错误理解之处请指出,不胜感激!(如需转载,请联系本 ...
- Java比较器
导语 本节内容,比较器Comparable是核心内容. 主要内容 重新认识Arrays类 两种比较器的使用 具体内容 Arrays类 在之前一直使用的"java.util.Arrays.so ...
- JavaScript设计模式接口
JavaScript中实现接口的方法有三种: 第一种,使用注释的方法实现接口 特点:(1)最简单,但是功能最弱(2)利用 interface和 implement"文字"(3)把他 ...
- linux的基本java环境搭建
1.安装rz,sz以便于上传和下载文件 yum install -y lrzsz 2.安装java环境 -- jdk1.8 官网下载jdk1.8:http://www.oracle.com/techn ...
- C#取得站点跟目录
string strServer = "http://" + Request.ServerVariables["SERVER_NAME"].ToString() ...
- mysql导出数据库和恢复数据库代码
mysql导出数据库和备份数据库 用mysqldump 命令行 命令格式 mysqldump -u 用户名 -p 数据库名 > 数据库名.sql 范例: mysqldump -uroot -p ...