css 动画

animate动画

  • animation-name动画的名字
  • animation-duration 动画持续的时间
  • animation-timing-function 为动画的曲线
    • linear 动画从头到尾的速度是相同的。
    • ease 默认。动画以低速开始,然后加快,在结束前变慢。
    • ease-in 动画以低速开始
    • ease-out 动画以低速结束
    • ease-in-out 动画以低速开始和结束
    • cubic-bezier(n,n,n,n) 在 cubic-bezier 函数中自己的值。可能的值是从 0 到 1 的数值。
  • animation-delay 规定在动画开始之前的延迟
  • animation-iteration-count 动画播放的次数
  • animation-direction 属性定义是否应该轮流反向播放动画
    • normal 动画正常播放
    • alternate 动画轮流反向播放
  • animation-fill-mode 属性规定动画在播放之前或之后,其动画效果是否可见
    • none 不改变
    • forwards 动画完成后,保持最后一帧
    • backwards 动画完成后,保持第一帧
    • both 前后叠加效果
  • animation-play-state 动画是暂停还是继续进行
    • 可以在js中进行操作 object.style.animationPlayState="paused"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.box {
width: 100px;
height: 100px;
background-color: red;
animation-name: move; // 动画名字
animation-duration: 2000ms; // 动画持续时间
animation-timing-function: ease-in-out; // 动画的表现方式
animation-iteration-count: 20; // 持续次数
animation-direction: alternate; // 轮播方式
}

@keyframes move {
0% {
transform: translateX(0rem);
}
100% {
transform: translateX(3rem);
opacity: 0;
}
}

transform动画

transition属性

  • transition-property 规定设置过渡效果的 CSS 属性的名称。
  • transition-duration 规定完成过渡效果需要多少秒或毫秒。
  • transition-timing-function 规定速度效果的速度曲线。
  • transition-delay 定义过渡效果何时开始。

transform属性

  • none 定义不进行转换。
  • matrix(n,n,n,n,n,n) 定义 2D 转换,使用六个值的矩阵。
  • matrix3d(n,n,n,n,n,n,n,n,n,n,n,n,n,n,n,n) 定义 3D 转换,使用 16 个值的 4x4 矩阵
  • translate(x,y) 定义 2D 转换。
  • translate3d(x,y,z) 定义 3D 转换。
  • translateX(x) 定义转换,只是用 X 轴的值。
  • translateY(y) 定义转换,只是用 Y 轴的值。
  • translateZ(z) 定义 3D 转换,只是用 Z 轴的值。
  • scale(x,y) 定义 2D 缩放转换。
  • scale3d(x,y,z) 定义 3D 缩放转换。
  • scaleX(x) 通过设置 X 轴的值来定义缩放转换。
  • scaleY(y) 通过设置 Y 轴的值来定义缩放转换。
  • scaleZ(z) 通过设置 Z 轴的值来定义 3D 缩放转换。
  • rotate(angle) 定义 2D 旋转,在参数中规定角度。
  • rotate3d(x,y,z,angle) 定义 3D 旋转。
  • rotateX(angle) 定义沿着 X 轴的 3D 旋转。
  • rotateY(angle) 定义沿着 Y 轴的 3D 旋转。
  • rotateZ(angle) 定义沿着 Z 轴的 3D 旋转。
  • skew(x-angle,y-angle) 定义沿着 X 和 Y 轴的 2D 倾斜转换。
  • skewX(angle) 定义沿着 X 轴的 2D 倾斜转换。
  • skewY(angle) 定义沿着 Y 轴的 2D 倾斜转换。
  • perspective(n) 为 3D 转换元素定义透视视图。

例子

1
2
3
4
5
6
7
8
9
#box {
width: 100px;
height: 100px;
background-color: red;
transition-duration: 1s; // 动画持续时间
}
#box:hover {
transform:scaleX(1.2);
}

如果设置了transform的变化 都是会脱离文档流

减少bundle.js体积

本文为译文,原文点我

我开发了很多年的SPA(单页应用),然而我总是很惊讶很多开发者都不去思考bundle.js的体积大小。

“压缩代码之后,大小还是可以接受的啊” ~一些人是这么说的,但是现在我不这么认为

即使我压缩bundle.js,在一个大型的应用中也会花费很多时间去加载这些资源,在低网速和手机上显示的时候特别慢。我们怎么样才能显著的解决这个问题呢?

非常简单!使用相对的文件路径。让我们来看下这个例子,看看有什么不同。

例子1

首先,我们用ES6的解构语法加载模块来编写一个简单的应用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# src/example.js

import { concat, sortBy, map, sample } from 'lodash';

// Example: sortBy
const users = [
{ 'user': 'fred', 'age': 48 },
{ 'user': 'barney', 'age': 36 },
{ 'user': 'fred', 'age': 42 },
{ 'user': 'barney', 'age': 34 }
];
const exampleSortBy = sortBy(users, function(o) { return o.user; });
console.log(exampleSortBy);

// Example: map
const exampleMap = map(users, 'user');
console.log(exampleMap);

// Example: concat
const array = [1];
const exampleConcat = concat(array, 2, [3], [[4]]);
console.log(exampleConcat);

// Example: sample
const exampleSample = sample([1, 2, 3, 4]);
console.log(exampleSample);

我们使用browserify来编译、打包这个应用

browserify src/example.js -o dist/bundle.js -t [ babelify --presets [ es2015 ] ] -v -d -g uglifyify

目前为止,情况很好。我们编写下一个例子,然后比较一下编译打包后的文件大小。

例子2

我们编写一个功能一样的应用。但是我们使用文件的路径来加载所有的模块,而不使用ES6的解构来加载模块。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# src/example-2.js

import concat from 'lodash/concat';
import sortBy from 'lodash/sortBy';
import map from 'lodash/map';
import sample from 'lodash/sample';

// Example: sortBy
const users = [
{ 'user': 'fred', 'age': 48 },
{ 'user': 'barney', 'age': 36 },
{ 'user': 'fred', 'age': 42 },
{ 'user': 'barney', 'age': 34 }
];
const exampleSortBy = sortBy(users, function(o) { return o.user; });
console.log(exampleSortBy);

// Example: map
const exampleMap = map(users, 'user');
console.log(exampleMap);

// Example: concat
const array = [1];
const exampleConcat = concat(array, 2, [3], [[4]]);
console.log(exampleConcat);

// Example: sample
const exampleSample = sample([1, 2, 3, 4]);
console.log(exampleSample);

现在,我们来编译我们的代码

browserify src/example-2.js -o dist/bundle-2.js -t [ babelify --presets [ es2015 ] ] -v -d -g uglifyify

问题 :你觉得哪个例子生成出来的文件更小?

比较

我们的应用做的事情完全一样。代码也几乎相同,编译之后我们发现例子2的代码要小很多。

1
$ ls -lha dist/
bundle-2.js (84K)
bundle.js (204K)

原因我们在上面已经提到了:我们没有引入所有lodash,而是引入了我们需要用的文件。

这个对于所有的node modules都适用。简单的把引入模块的结构语法替换成实际路径引入的语法,很快能到减少的文件大小。

源码

如果你想看这个例子的源码,你可以从github上check out 这个仓库

https://github.com/tlackemann/minimize-bundle-js-size

我收到了很多回复提到了Webpack2、Rollup等等。是的,这些新技术是很棒,有一个名为tree shaking的功能(可以在打包中不引入我们不需要的代码)。但是在你接手一个老的项目的时候,你很有可能是不能使用这些新技术,需要的是一些其他的办法来解决这个问题。本文提到的方法可以更快速的解决你当前遇到的问题。

判断ios设备旋转方向


title: 判断ios设备旋转方向
date: 2016-03-8 22:12:57

tags: ios

  • 首先你要在对应的controller中,开启旋转的功能

    1
    // 默认开启全部方向的旋转
    - (BOOL)shouldAutorotate {
        return YES;
    }
  • 下一个方法是可以旋转接受哪几个方向的旋转

    1
    - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
          return UIInterfaceOrientationMaskPortrait |UIInterfaceOrientationMaskLandscapeLeft;
      }
    1
    // 可以选择多个方向选择
    typedef NS_OPTIONS(NSUInteger, UIInterfaceOrientationMask) {
        UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
        UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
        UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
        UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
        UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
        UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),
        UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
    } __TVOS_PROHIBITED;
  • 旋转的时候,你可以开启系统通知的功能,这样你就可以在旋转的时候执行特定的函数了

    1
    [[NSNotificationCenter defaultCenter] addObserver:self
                        selector:@selector(statusBarOrientationChange:)                                                               name:UIApplicationDidChangeStatusBarOrientationNotification
                                                 object:nil];
    
     // 打印出相关的方向
     - (void)statusBarOrientationChange:(NSNotification *)notification {
    
        UIInterfaceOrientation oriention = [UIApplication sharedApplication].statusBarOrientation;
        NSLog(@"%ld",(long)oriention);
    }

mac初始化配置apache启动目录

此文章的目的是把apache的默认启动目录改为当前的用户目录

默认情况下mac下apachectl配置的默认路径是

1
/Library/WebServer/Documents

我们可能需要在本地的服务器上访问我们的文件,通过这个地址我们很不方便的访问我们需要的文件,我们可以修改我们apachectl的根目录来快速的访问到我们需要访问的文件。

第一步


我们需要找到apachectl的配置文件

1
cd /etc/apache2
1
vim httpd.conf

第二步


在文件中搜索
<Directory "/Library/WebServer/Documents">
Options FollowSymLinks Multiviews修改为Options Indexes FollowSymLinks Multiviews

因为系统级根目录默认没有开启目录列表,这个修改则开启了目录列表

在终端上输入

cd && pwd
查看你当前用户级的目录地址/Users/username


<Directory "/Library/WebServer/Documents">替换为<Directory "/Users/username">
#DocumentRoot "/Library/WebServer/Documents"替换为#DocumentRoot "/Users/username"

第三步


这个时候我们去打开我们的localhost访问是,会提示没有权限,这个时候我们需要在配置文件下面添加username.conf添加我们的用户信息,将文件保存在/etc/apache2/users/下。这里需要使用sudo权限。

其他

更多信息可以参考这篇文章

发布一个npm模块

发布模块

  • 创建新目录
    • npm init
    • 自动生成package.json
    • nameversion是必须要的
    • nameqyt-test
  • 创建index.js

    1
    export.printMsg = function() {
      console.log('this module name is qyt-test');
    }
  • package.json里有一个main字段,默认引入的就是这个字段的文件

    • "main": "index.js"
      1
      var aMoudle = require('qyt-test');
      /**
      * aMoudle 就是 index.js里输出的内容
      **/
  • 注册npm账号(两个方法)

    1. 注册地址
    2. npm adduser
  • npm登录
    • npm login
  • npm模块发布
    • npm publish
  • npmtags
    • 安装npm包的时候,可以使用npm install qyt-test来安装,或者使用npm install qyt-test@1.0.0npm install qyt-test@beta来安装
    • @后面的标识符就是我们npm publish发布所打的tag
    • 默认情况,发布版本的时候会打上你的package.json的version做为tag。
      • 例如你的package.json里的"version": "1.0.3",你安装的时候就可以使用npm install qyt-test@1.0.3
    • 同时默认情况下,会在最后一次的npm publish中给你打上latest的tag
      • 例如你的最后一次发布package.json里的"version": "1.0.3",你安装的时候就可以使用npm install qyt-test@1.0.3以及npm install qyt-test@latest
    • 你也可以增加其他的tag
      • npm dist-tag add <pkg>@<version> [<tag>] 例如 npm dist-tag qyt-test@1.0.3 beta
      • 你也可以直接在发布的时候npm publish --tag beta
      • 如果你想给已经发布过的模块打tag,也是使用npm dist-tag qyt-test@1.0.0 beta
    • 删除tag
      • npm dist-tag rm <pkg> <tag>
      • 例如npm dist-tag rm qyt-test beta
    • 查看模块tag
      • npm dist-tag ls [<pkg>]
      • 例如 npm dist-tag ls qyt-test

使用你发布的模块

  • 创建路径

    1
    mkdir test
    cd test
    npm init
    npm install qyt-test
    touch index.js
  • 创建文件

    1
    touch index.js
    
    /**
    * in index.js
    **/
    var a = require('qyt-test');
  • 执行
    node index.js会输出this module name is qyt-test

npm教程

基本使用

  • 安装与升级
    • 在安装 node的时候会自动安装npm
    • sudo npm install npm -g进行升级,使用cnpm的话,sudo cpm install npm -g进行升级
  • 安装模块
    • 全局
      • 命令行等工具,使用全局安装
      • npm install <package_name> -g
    • 本地项目
      • 你项目中的各种依赖
      • npm install <package_name>
  • 使用package.json
    • 在项目中管理npm模块,最好的方式是创建一个package.json的文件进行管理
    • 好处
      • 你依赖的各个模块在文件中都有记载
      • 可以让你指定模块的特定版本
      • 更好的协作性
    • npm install <package_name> --save安装模块,并写入package.jsondependencies字段
    • npm install <package_name> --save-dev安装模块,并写入package.jsondevDependencies字段
  • package.json中的版本号
    • 指定版本: "gulp": "1.2.2",只允许装1.2.2的版本
    • 允许bug-fixed版本自动升级~: "gulp": "~1.2.2",最后一位小版本可以高于2,但不允许装1.3.x的版本,1.2.3的版本是可以的
    • 中间版本号可以升级+: "gulp": "+1.2.2",可以安装1.x.x的版本,但是2.x.x是不允许的
    • latest: "gulp": "latest",安装最新版本
  • 升级模块
    • 本地模块
      • npm outdated 查看哪些需要升级
      • npm update进行升级
    • 全局模块
      • npm outdated -g --depth=0
      • npm update -g 升级全部模块
  • 卸载模块
    • 本地
      • npm uninstall lodash删除模块
      • npm uninstall --save lodash,删除模块,并在package.json中移除
    • 全局
      • npm uninstall -g jshint

问题

  • 提示EACCESerror(两种解决方案)
    1. 改变npm默认目录的权限
      • 找到npm的路径
        • npm config get prefix
      • sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}
    2. 更改npm的默认目录
      • 创建一个新目录mkdir ~/.npm-global
      • npm配置到该目录 npm config set prefix '~/.npm-global'
      • 创建一个~/.profile文件,并写入 export PATH=~/.npm-global/bin:$PATH
      • 回到命令行,进行编译 source ~/.profile

npm start 和 npm run start

背景

在项目的目录中,我们会在 package.json 里配置 scripts

1
{
  "name": "hexo-site",
  "version": "0.0.0",
  "private": true,
  "hexo": {
    "version": "3.1.1"
  },
  "dependencies": {
    "hexo": "^3.1.1",
    "hexo-generator-archive": "^0.1.3",
    "hexo-generator-category": "^0.1.3",
    "hexo-generator-index": "^0.2.0",
    "hexo-generator-tag": "^0.1.2",
    "hexo-renderer-ejs": "^0.1.0",
    "hexo-renderer-stylus": "^0.3.0",
    "hexo-renderer-marked": "^0.2.6",
    "hexo-server": "^0.1.2"
  },
  "scripts": {
    "start": "hexo server",
    "publish": "hexo generate"
  }
}

在这里你可以直接使用 shell command npm start去起hexo server,在端口中查看你的修改。
但是你会发现,我操npm publish是没用的。

为什么会这样

遇到这种问题,肯定要去看看文档啊。npm-run-script
文档里是这么说的 If no "command" is provided, it will list the available scripts. run[-script] is used by the test, start, restart, and stop commands, but can be called directly, as well,也就是说 test, start, restart, and stop这几个命令是不用加run,其他几个都是要加run

所以,想要publish的话,就需要npm run publish就可以了。

参考文档

git 版本回退 -- git log 和 git reflog 的区别

背景

今天代码写着写着,就发现在IE8有问题,但是在改代码之前是没问题的。这个时候我就决定先commit我的代码,然后reset到我刚才pull的远程最新版本上去。

回退完之后,也看出是什么问题了,我就想回到我刚才commit的那个时候去,执行了git log命令,这个时候我傻眼了,麻痹的我的commit记录没了。当时无所个草泥马在眼前,当时就呆在那坐了回,骂了半天,什么鬼。

解决方案

然后我就去google了一下(总不能让我重新写我写了一上午的东西吧),我觉得我commit过了,肯定不会有问题的,代码一定还在。果不出其然,我发现了还有一个命令git reflog,执行了之后,找到了我刚才commitid,直接git reset --hard xxx,找回了我之前的代码。

原理

  • git log
    • git log展示的是当前的HEAD以及它之前的各种信息。等于它只能找到之前的各种commitmerge等信息。
    • 所以在我reset之后,找不到我commit的记录,因为这次的commit是在此时HEAD之后进行的。
  • git reflog
    • git reflog记录了你的目录下任意时刻的commits。所以就算我reset了,依旧会有我的记录。

总结

所以说,只要你commit过,始终reflog绝壁是能找到你的commit记录的

“Keep calm and use git reflog

参考文档

如何判断页面是否在iframe中

卧槽。。。我做前端这么久,一直没接触过iframe,最近在搞登录,总算是有机会接触下这玩意了。

然后开发和我说在登录中要判断我们自己的页面是否是在iframe中,当时我就 懵逼 了。当时的第一想法是,这搞不定吧。后面google了一下,发现还是可以搞定的。

就是判断window对象上的top属性是否等于自己。

1
if (window.top === window) {
  console.log('我不在iframe中');
} else {
  console.log('我在iframe中');
}
  • top对象是什么鬼呢
    • top 属性返回最顶层的先辈窗口。
      该属性返回对一个顶级窗口的只读引用。
    • 如果窗口本身就是一个顶级窗口,top 属性存放对窗口自身的引用。如果窗口是一个框架,那么 top 属性引用包含框架的顶层窗口。

说的通俗一点就是,让你在iframe中的时候,top就是引用你的页面的window对象;当你不在的时候,就是自己的window对象了

1
<!-- father.html -->
<html>
  <head>
  </head>
  <body>
    <iframe src="./chind.html"></iframe>
    <script>
      console.log(window === window.top); // 没有父窗口,就是top就是window
    </script>
  </body>
</html>

<!-- child.html -->
<html>
  <head>
  </head>
  <body>
    <script>
      console.log(window === window.top); // 父窗口是father.html,所以window.top是father.html的window
    </script>
  </body>
</html>