HTML5 视频直播

参考资料:

createJS实战深入解析

CreateJS简介

CreateJS 是一套可以构建丰富交互体验的 HTML5 游戏的开源工具包,旨在降低 HTML5 项目的开发难度和成本,让开发者以熟悉的方式打造更具现代感的网络交互体验。

CreateJS中文Github:https://github.com/CreateJS/
CreateJS英文版Api:http://www.createjs.com/
CreateJS中文版Api:http://www.createjs.cc/

CreateJS 中包含:

  • EaselJS:用于 Sprites、动画、向量和位图的绘制,创建 HTML5 Canvas 上的交互体验(包含多点触控),同时提供 Flash 中的“显示列表”功能。
  • TweenJS:一个简单的用于制作类似 Flash 中“补间动画”的引擎,可生成数字或非数字的连续变化效果。
  • SoundJS:一个音频播放引擎,能够根据浏览器性能选择音频播放方式。将音频文件作为模块,可随时加载和卸载。
  • PerloadJS:帮助你简化网站资源预加载工作,无论加载内容是图形、视频、声音、JS、数据……
    以上的Createjs介绍来自百度,不过通过介绍可以知道,虽然CreateJS看起来复杂,不过四个部分各有作用,其中最主要的就是EaselJS,其余三项不过是为他服务。

开发步骤:
1、下载类库,可以使用源代码,也可以使用压缩过的min.js,就好像平时写网页一样。
2、建立html和canvas标签,onload后再执行createjs相关逻辑。
3、编写createjs逻辑。这个非常简单,因为createjs只提供了最简单的基础功能,我们理解了基础功能后就可以叠积木了。

关于createjs,最关键是要理解类结构

createjs类结构

上图列出了createjs的主要类结构,所有舞台上的内容都是元件,元件的基类是DisplayObject。Container可以包含子元件,舞台Stage本身也是Container。另外Sprite用于表现SpriteSheet帧动画人物、Bitmap用于展示纯静态的人物。

createjs类结构

而Filter和Shadow则是滤镜分支,可以针对任意元件实现颜色变换、模糊、阴影等效果。使用滤镜的方式跟Flash一致,需要新建Filter实例,添加到目标元件的FilterList中,Createjs框架在下一帧就会把该元件加上滤镜效果。

EaselJS部分

EaselJS所有的功能都是被一个全局类createjs所包含,将其打印大致包含如下(有删减):

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
30
31
32
33
34
35
36
37
38
AlphaMapFilter
AlphaMaskFilter
Bitmap //位图,用于引入图片 位图类不需要缓存
BitmapText // 位图中绘制文字
BlurFilter //模糊滤镜
ButtonHelper
ColorFilter // 颜色滤镜
ColorMatrix
ColorMatrixFilter
Container
DisplayObject
DisplayProps
DOMElement
EaselJS //版本信息
Event
EventDispatcher
Filter //滤镜
Graphics //绘制各种图形
Matrix2D
MouseEvent //鼠标事件,用于与用户交互
MovieClip //动画剪裁
MovieClipPlugin
Point //绘制点
Rectangle //绘制矩形
Shadow //绘制阴影
Shape //新建图形图层
Sprite //帧或帧序列(即动画)
SpriteContainer
SpriteSheet
SpriteSheetBuilder
SpriteSheetUtils
SpriteStage
Stage //新建舞台
Text //绘制文本图层
Ticker
Touch //移动端交互 触摸事件 注册createjs.Touch.enable(stage) pressup、pressmove
UID //用于生成序列唯一标识号的全局实用程序
Utility Methods

使用EaselJS基本结构:

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
30
31
32
33
34
35
36
37
38
39
40
41
var stage=new createjs.Stage("canvas");
var canvas = new createjs.Stage("canvas").canvas;
var container = new createjs.Container();
var ctx = new createjs.Stage("canvas").canvas.getContext("2d");

var circle=new createjs.Shape();
circle.graphics.beginFill("red").drawCircle(0,0,50);

//regX,regY向左,向上偏移两,旋转时设置可以让其沿坐标点旋转。
circle.regX = -25;
circle.regY = -25;
circle.x=50;
circle.y=50;

//增加形状实例显示在舞台列表上
stage.addChild(circle);

//更新舞台渲染
stage.update();


stage.addEventListener("stagemousedown",function(){
//控制舞台点击
})

stage.addEventListener("click",function(){
//只能点击舞台上的显示元素才能触发
})

//多点触摸功能的设备 pressup,pressmove替换touchstart,touchmove
createjs.Touch.enable(stage);

//帧频率绘制模式
createjs.Ticker.timingMode = createjs.Ticker.RAF;

//createjs.Ticker.setFPS(60);

//获取当前帧频率
createjs.Ticker.getMeasuredFPS()

stage.addEventListener("tick",tick);

1.stagemousedown,stagemouseup,stagemousemove与mousedown,mouseup,mousemove的区别

(1) stagemousedown,stagemouseup,stagemousemove是针对stage的专属事件
(2) mousedown,mouseup,mousemove事件对stage、DisplayObject都可以触发,但针对stage只对舞台上DisplayObject才触发

2.pressmove、pressup与touchmove,touchend

(1) 要使用移动端交互,多点触控事件,需先注册createjs.Touch.enable(stage),开启触摸事件
(2) pressmove代替touchmove, pressup代替touchend

3.DisplayObject中cache提高stage渲染效率
cache方法其实是把显示对象画到一个新的canvas中,从而每一次stage.update()重绘的时候不用重新渲染了,大大提高效率。
通常把一些不经常变化的复杂的显示对象进行cache(比如说有许多子对象的容器或者复杂的Shape),被缓存的显示对象可以移动、旋转、改变透明度。但是被缓存的显示对象的内容变化的话,就要重新调用cache()、updateCahce()、uncache()方法。

关于cache,官网cache例子

语法:

1
2
3
4
cache ( x  y  width  height  [scale=1] )  //scale默认为1

前四个参数指定了显示对象要缓存的区域,注意的事x和y的坐标都是根据当前这个显示对象本身的坐标系来计算。
最后一个参数scale表示在缓存时缩放的比例,比如 myShape.cache(0,0,100,100,2) 这样使用时,缓存出来的结果大小事200*200。

缓存一个圆型的Shape,例子:

1
2
3
var shape = new createjs.Shape();
shape.graphics.beginFill("#ff0000").drawCircle(0, 0, 25);
shape.cache(-25, -25, 50, 50);

使用cache注意关键点:

1.在displayObject上使用filter,要在调用cache方法之前使用filter
2.Bitmap对象中使用cache,普通bitmap不要调用cache方法,如果bitmap要使用滤镜filter的话,一定要调用cache
3.在Sprite对象中,Sprite已经是光栅格式,对于Sprite实例来说cache没有必要。不要为提高性能来调用Spritecache

4.DisplayObject中scalerotation中心点,通过regX,regY偏移,定位到相对DisplayObject坐标点

例如,让一个100 x100px位图旋转中心,您将设置regX regY 50

5.Ticker处理帧频率

Ticker类为游戏开发提供了一个主要的定时类,主要的目的就是把stage渲染的工作集中起来,也就是说定时调用stage.update()这个方法。Ticker设置的频率也就是游戏的帧数了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
createjs.Ticker.setFPS(60);
createjs.Ticker.addEventListener("tick", handleTick);
stage.addEventListener("stagemousedown", function(event){
createjs.Ticker.setPaused(!createjs.Ticker.getPaused());
});
function handleTick(event){
if(!event.paused){
……
}
stage.update();
}

在侦听函数中event的数据
1.event.paused 表示ticker是否处于暂停状态
2.event.delta 在上一次tick事件之后到这次事件的时间间隔,以毫秒为单位。
3.event.time 在Ticker被初始化以后的时间总和,以毫秒为单位。
4.event.runTime 在Ticker被初始化以后没有暂停的时间总和,以毫秒为单位。

Ticker常用属性和方法:
1.paused 在ticker暂停时,所有的侦听器仍然会接受到tick事件,但是事件中的paused会是true(createjs.Ticker.paused = true);
2.timingMode指定tick的timing模式。一共有三种模式,TIMEOUT、RAF和RAF_SYNCHEN。
(1)TIMEOUT,这种模式下使用的就是setTimeOut这个方法实现的。是timingMode的默认模式。
(2)RAF 在这个模式下使用requestAnimationFrame,完全忽略Ticker的帧频。如果requestAnimationFrame API不支持的话就用TIMEOUT模式。
(3)RAF_SYNCHEN 在这个模式下使用requestAnimationFrame,但是试图与ticker的帧频同步。如果requestAnimationFrame API不支持的话就用TIMEOUT模式。
3.getMeasuredFPS() 获得当前的实际帧频。
4.getMeasuredTickTime 获得平均一次tick所有的时间,大概就是在这一次tick所用的时间。

PrloadJS部分

PreloadJS是一个用来管理和协调相关资源加载的类库,它可以方便的帮助你预先加载相关资源。当我们打印PreloadJS对象,发现主要提供以下类:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
AbstractLoader
AbstractMediaLoader
AbstractRequest
BinaryLoader //二进制文件的加载
CSSLoader //CSS文件的加载
DataUtils
DomUtils
ImageLoader
JavaScriptLoader
JSONLoader //加载JSON
JSONPLoader //要加载JSON跨域,使用JSONP和 JSONPLoader 代替
LoadItem
LoadQueue //加载管理器,可以预先加载一个文件或者一个文件队列
ManifestLoader
MediaTagRequest
PreloadJS
ProgressEvent
RequestUtils
SamplePlugin
SoundLoader
SpriteSheetLoader
SVGLoader //加载svg
TagRequest
TextLoader
VideoLoader
XHRRequest
XMLLoader
```
LoadQueue类,应该来说平时使用比较多,这里就主要聊聊LoadQueue。

LoadQueue 类
LoadQueue类是预加​​载内容的主要API。 LoadQueue是负载管理器,它可以预载是单个文件或文件的队列。

LoadQueue包含了几个可以订阅的事件:

- complete: 当队列完成加载所有文件时。
- error: 当队列与任何文件遇到错误时。
- progress: 对于整个队列进展已经改变。
- fileload: 单个文件已完成加载。
- fileprogress: 单个文件进度变化。注意,只有文件装载XHR(或可能通过插件)将 file 事件进展除了0或100%。

LoadQueue支持相关文件类型如下:

- BINARY: XHR调用的二进制文件
- CSS: CSS文件
- IMAGE: 一般图片文件格式
- JAVASCRIPT: JavaScript文件
- JSON: JSON数据
- JSONP: 跨域JSON文件
- MANIFEST: JSON格式的文件列表
- SOUND: 音频文件
- SVG: SVG文件
- TEXT: 文本文件 - 仅支持XHR
- XML: XML数据

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var queue = new createjs.LoadQueue(true); //LoadQueue ( [preferXHR=true]  [basePath=""]  [crossOrigin=""] )

queue.loadManifest([{
id: "guide",
src: "images/guide.png"
}}]);

queue.on("fileload", handleFileLoad, this);
queue.on("complete", handleComplete, this);
queue.on("progress", handleProgress, this);

function handleComplete(){
queue.getResult(‘id’);
}
function handleProgress(event) {
console.log(event.progress * 100)
}

LoadQueue支持相关文件类型如下:

  • 预加载音频文件

    1
    2
    //初始化插件
    queue.installPlugin(createjs.Sound);
  • 设置加载路径
    注意,第一个参数为true,代表通过xhr形式加载,但是通常,我们可能需要http加载,所以建议设置为false,以免造成重复加载。

    1
    var queue = new createjs.LoadQueue(false,"./base/src/"); //LoadQueue ( [preferXHR=true]  [basePath=""]  [crossOrigin=""] )
  • 获取加载进度

    1
    event.progress
  • 获取预加载资源

    1
    preload.getResult(‘id’);

TweenJS部分

TweenJS Javascript库提供了一个简单但强大的渐变界面。它支持渐变的数字对象属性&CSS样式属性,并允许您链接补间动画和行动结合起来,创造出复杂的序列。其中主要包含如下类:

1
2
3
4
5
6
7
CSSPlugin   //用css的方式写动画,但是它采用的形式是html,效率低下
Ease //提供支持贝塞尔动画
MotionGuidePlugin //轨迹动画插件
SamplePlugin
Timeline
Tween
TweenJS

Tween构造函数:

1
Tween ( target  [props]  [pluginData] )

参数

  • target对象: 将其属性渐变的目标对象
  • [props] 对象: 适用于这个渐变实例的配置属性(ex. {loop:true, paused:true}. 所有属性默认为false. 被支持的小道具是:
    (1)loop: 设置循环属性渐变,true为循环,false为不循环.
    (2)useTicks: 使用嘀嗒走针是因为持续时间而不是毫秒.
    (3)ignoreGlobalPause: 设置在渐变动画上 ignoreGlobalPause 属性.
    (4)override:如果设置为true,Tween.removeTweens(target) 将被称为移除相同目标的所有别的渐变动画.
    (5)paused: 指示是否开始停止渐变动画.
    (6)position: 表明这个渐变的初始位置.
    (7)onChange: 指定一个“change”事件侦听器.

  • [pluginData] 对象(可选的):一个对象包含的数据供安装使用插件。有关详细信息,请参阅个别插件的文档.

Tween实例:

1
2
3
4
5
6
7
8
9
10
11
target.alpha = 1;
createjs.Tween.get(target, {override:true}) //多个渐变动画可以指向相同的实例,然而如果他们影响相同的属性可能会有意外行为. 需要停止所有的渐变动画, 使用 removeTweens 或者通过 override:true
.to({alpha:0.5,x:10,y:20}, 1000, createjs.Ease.linear)
.wait(500)
.call(handleComplete)
.to({alpha:0, visible:false}, 1000, createjs.Ease.bounceInOut)
.addEventListener("change",handleChange)

function handleComplete() {
//Tween complete
}
  • get 获取目标元素
  • to 执行动画
  • wait 队列等待
  • call 执行回调函数
  • createjs.Ease.bounceInOut 缓动效果
  • change 订阅 change 事件以便当目标的属性改变时获得通知

使用Ease可以控制运动的轨迹,实现曲线的运动,还可以控制运动过程,比如先加速再减速等,在Tweenjs官方示例中有两个可以用来观察Ease提供的各个参数对运动过程产生的影响,
http://andysaia.com/blog/tweenjs/
http://www.createjs.com/demos/tweenjs/tween_sparktable

参考资料:

Mac怎么制作iphone铃声?

有时候听到好听的音乐就想把它做成手机铃声,那么怎么在Mac上制作iPhone铃声呢?其实,Mac电脑下iTunes本身具有有这个功能,而且操作并不是太难只需要注意几个关键点一步一步引导即可。步骤如下:

一.打开itunes软件

打开itunes软件

二. 选择左上脚“文件”——“将文件导入资料库”

打开itunes软件

或者直接点击本地音乐文件播放(注意选择iTunes),我们就可以在iTunes最近添加找到文件:
打开itunes软件

三. 选择你要的文件点击打开

打开itunes软件

四:选择“选项”,然后写上你想要开始和结束的时间,注意iphone的铃声只支持40秒。写好后将起始时间和停止时间都选勾,然后点击右下角的“好”。

打开itunes软件

五:选择左上脚“文件”——“转换”——“创建ACC版本”,iTunes会生成一首歌曲,在原来歌曲的下面。

打开itunes软件

六:右键点选歌曲例《单车》选择在Finder中显示“然后把后缀名”m4a“改为”m4r“。因为m4r才是iphone铃声的格式,改好后将其移动到桌面,然后在iTunes中把这首铃声删除,option+command删除文件从资料库,设备。

打开itunes软件

七. 选择左上脚“文件”——“将文件导入资料库”,选择刚才移出到桌面的m4r文件导入

八. 点击设备手机图标,点击左侧菜单“铃声”——同步铃声“所选铃声”,应用将此歌曲同步到iphone的铃音库中,即可设置成功

打开itunes软件

打开itunes软件

参考资料:

如何愉快的使用ESLint进行代码校验--转载

一. ESLint是什么?

ESLint 是一个开源的 JavaScript 代码校验工具,最初是由 Nicholas C. Zakas 在2013年创建的。经常被用来发现问题的模式或代码,不符合特定的风格准则。

ESLint 创建的首要原因是为了让开发人员创建自己的校验规则,ESLint 的目的是让所有的规则完全可插拔。虽然ESLint将附带一些内置的规则,你可以在任何时间点动态加载规则。

二. ESLint有什么用?

  • 可以辅助编码规范执行,有效控制代码质量
  • 默认规则包含所有 JSLint、JSHint 中存在的规则,易迁移;
  • 规则可配置性高:可设置「警告」、「错误」两个 error 等级,或者直接禁用;
  • 包含代码风格检测的规则;
  • 支持插件扩展、自定义规则。

三. ESLint规则一览

Vim常见有两种模式一种是Insert模式,该模式下可以像其它文本编辑器一样正常输入字符;另一种是Normal模式,该模式下Vim监听用户的按键可以对文本进行快速修改。

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
"no-alert": 0,//禁止使用alert confirm prompt
"no-array-constructor": 2,//禁止使用数组构造器
"no-bitwise": 0,//禁止使用按位运算符
"no-caller": 1,//禁止使用arguments.caller或arguments.callee
"no-catch-shadow": 2,//禁止catch子句参数与外部作用域变量同名
"no-class-assign": 2,//禁止给类赋值
"no-cond-assign": 2,//禁止在条件表达式中使用赋值语句
"no-console": 2,//禁止使用console
"no-const-assign": 2,//禁止修改const声明的变量
"no-constant-condition": 2,//禁止在条件中使用常量表达式 if(true) if(1)
"no-continue": 0,//禁止使用continue
"no-control-regex": 2,//禁止在正则表达式中使用控制字符
"no-debugger": 2,//禁止使用debugger
"no-delete-var": 2,//不能对var声明的变量使用delete操作符
"no-div-regex": 1,//不能使用看起来像除法的正则表达式/=foo/
"no-dupe-keys": 2,//在创建对象字面量时不允许键重复 {a:1,a:1}
"no-dupe-args": 2,//函数参数不能重复
"no-duplicate-case": 2,//switch中的case标签不能重复
"no-else-return": 2,//如果if语句里面有return,后面不能跟else语句
"no-empty": 2,//块语句中的内容不能为空
"no-empty-character-class": 2,//正则表达式中的[]内容不能为空
"no-empty-label": 2,//禁止使用空label
"no-eq-null": 2,//禁止对null使用==或!=运算符
"no-eval": 1,//禁止使用eval
"no-ex-assign": 2,//禁止给catch语句中的异常参数赋值
"no-extend-native": 2,//禁止扩展native对象
"no-extra-bind": 2,//禁止不必要的函数绑定
"no-extra-boolean-cast": 2,//禁止不必要的bool转换
"no-extra-parens": 2,//禁止非必要的括号
"no-extra-semi": 2,//禁止多余的冒号
"no-fallthrough": 1,//禁止switch穿透
"no-floating-decimal": 2,//禁止省略浮点数中的0 .5 3.
"no-func-assign": 2,//禁止重复的函数声明
"no-implicit-coercion": 1,//禁止隐式转换
"no-implied-eval": 2,//禁止使用隐式eval
"no-inline-comments": 0,//禁止行内备注
"no-inner-declarations": [2, "functions"],//禁止在块语句中使用声明(变量或函数)
"no-invalid-regexp": 2,//禁止无效的正则表达式
"no-invalid-this": 2,//禁止无效的this,只能用在构造器,类,对象字面量
"no-irregular-whitespace": 2,//不能有不规则的空格
"no-iterator": 2,//禁止使用__iterator__ 属性
"no-label-var": 2,//label名不能与var声明的变量名相同
"no-labels": 2,//禁止标签声明
"no-lone-blocks": 2,//禁止不必要的嵌套块
"no-lonely-if": 2,//禁止else语句内只有if语句
"no-loop-func": 1,//禁止在循环中使用函数(如果没有引用外部变量不形成闭包就可以)
"no-mixed-requires": [0, false],//声明时不能混用声明类型
"no-mixed-spaces-and-tabs": [2, false],//禁止混用tab和空格
"linebreak-style": [0, "windows"],//换行风格
"no-multi-spaces": 1,//不能用多余的空格
"no-multi-str": 2,//字符串不能用\换行
"no-multiple-empty-lines": [1, {"max": 2}],//空行最多不能超过2行
"no-native-reassign": 2,//不能重写native对象
"no-negated-in-lhs": 2,//in 操作符的左边不能有!
"no-nested-ternary": 0,//禁止使用嵌套的三目运算
"no-new": 1,//禁止在使用new构造一个实例后不赋值
"no-new-func": 1,//禁止使用new Function
"no-new-object": 2,//禁止使用new Object()
"no-new-require": 2,//禁止使用new require
"no-new-wrappers": 2,//禁止使用new创建包装实例,new String new Boolean new Number
"no-obj-calls": 2,//不能调用内置的全局对象,比如Math() JSON()
"no-octal": 2,//禁止使用八进制数字
"no-octal-escape": 2,//禁止使用八进制转义序列
"no-param-reassign": 2,//禁止给参数重新赋值
"no-path-concat": 0,//node中不能使用__dirname或__filename做路径拼接
"no-plusplus": 0,//禁止使用++,--
"no-process-env": 0,//禁止使用process.env
"no-process-exit": 0,//禁止使用process.exit()
"no-proto": 2,//禁止使用__proto__属性
"no-redeclare": 2,//禁止重复声明变量
"no-regex-spaces": 2,//禁止在正则表达式字面量中使用多个空格 /foo bar/
"no-restricted-modules": 0,//如果禁用了指定模块,使用就会报错
"no-return-assign": 1,//return 语句中不能有赋值表达式
"no-script-url": 0,//禁止使用javascript:void(0)
"no-self-compare": 2,//不能比较自身
"no-sequences": 0,//禁止使用逗号运算符
"no-shadow": 2,//外部作用域中的变量不能与它所包含的作用域中的变量或参数同名
"no-shadow-restricted-names": 2,//严格模式中规定的限制标识符不能作为声明时的变量名使用
"no-spaced-func": 2,//函数调用时 函数名与()之间不能有空格
"no-sparse-arrays": 2,//禁止稀疏数组, [1,,2]
"no-sync": 0,//nodejs 禁止同步方法
"no-ternary": 0,//禁止使用三目运算符
"no-trailing-spaces": 1,//一行结束后面不要有空格
"no-this-before-super": 0,//在调用super()之前不能使用this或super
"no-throw-literal": 2,//禁止抛出字面量错误 throw "error";
"no-undef": 1,//不能有未定义的变量
"no-undef-init": 2,//变量初始化时不能直接给它赋值为undefined
"no-undefined": 2,//不能使用undefined
"no-unexpected-multiline": 2,//避免多行表达式
"no-underscore-dangle": 1,//标识符不能以_开头或结尾
"no-unneeded-ternary": 2,//禁止不必要的嵌套 var isYes = answer === 1 ? true : false;
"no-unreachable": 2,//不能有无法执行的代码
"no-unused-expressions": 2,//禁止无用的表达式
"no-unused-vars": [2, {"vars": "all", "args": "after-used"}],//不能有声明后未被使用的变量或参数
"no-use-before-define": 2,//未定义前不能使用
"no-useless-call": 2,//禁止不必要的call和apply
"no-void": 2,//禁用void操作符
"no-var": 0,//禁用var,用let和const代替
"no-warning-comments": [1, { "terms": ["todo", "fixme", "xxx"], "location": "start" }],//不能有警告备注
"no-with": 2,//禁用with

"array-bracket-spacing": [2, "never"],//是否允许非空数组里面有多余的空格
"arrow-parens": 0,//箭头函数用小括号括起来
"arrow-spacing": 0,//=>的前/后括号
"accessor-pairs": 0,//在对象中使用getter/setter
"block-scoped-var": 0,//块语句中使用var
"brace-style": [1, "1tbs"],//大括号风格
"callback-return": 1,//避免多次调用回调什么的
"camelcase": 2,//强制驼峰法命名
"comma-dangle": [2, "never"],//对象字面量项尾不能有逗号
"comma-spacing": 0,//逗号前后的空格
"comma-style": [2, "last"],//逗号风格,换行时在行首还是行尾
"complexity": [0, 11],//循环复杂度
"computed-property-spacing": [0, "never"],//是否允许计算后的键名什么的
"consistent-return": 0,//return 后面是否允许省略
"consistent-this": [2, "that"],//this别名
"constructor-super": 0,//非派生类不能调用super,派生类必须调用super
"curly": [2, "all"],//必须使用 if(){} 中的{}
"default-case": 2,//switch语句最后必须有default
"dot-location": 0,//对象访问符的位置,换行的时候在行首还是行尾
"dot-notation": [0, { "allowKeywords": true }],//避免不必要的方括号
"eol-last": 0,//文件以单一的换行符结束
"eqeqeq": 2,//必须使用全等
"func-names": 0,//函数表达式必须有名字
"func-style": [0, "declaration"],//函数风格,规定只能使用函数声明/函数表达式
"generator-star-spacing": 0,//生成器函数*的前后空格
"guard-for-in": 0,//for in循环要用if语句过滤
"handle-callback-err": 0,//nodejs 处理错误
"id-length": 0,//变量名长度
"indent": [2, 4],//缩进风格
"init-declarations": 0,//声明时必须赋初值
"key-spacing": [0, { "beforeColon": false, "afterColon": true }],//对象字面量中冒号的前后空格
"lines-around-comment": 0,//行前/行后备注
"max-depth": [0, 4],//嵌套块深度
"max-len": [0, 80, 4],//字符串最大长度
"max-nested-callbacks": [0, 2],//回调嵌套深度
"max-params": [0, 3],//函数最多只能有3个参数
"max-statements": [0, 10],//函数内最多有几个声明
"new-cap": 2,//函数名首行大写必须使用new方式调用,首行小写必须用不带new方式调用
"new-parens": 2,//new时必须加小括号
"newline-after-var": 2,//变量声明后是否需要空一行
"object-curly-spacing": [0, "never"],//大括号内是否允许不必要的空格
"object-shorthand": 0,//强制对象字面量缩写语法
"one-var": 1,//连续声明
"operator-assignment": [0, "always"],//赋值运算符 += -=什么的
"operator-linebreak": [2, "after"],//换行时运算符在行尾还是行首
"padded-blocks": 0,//块语句内行首行尾是否要空行
"prefer-const": 0,//首选const
"prefer-spread": 0,//首选展开运算
"prefer-reflect": 0,//首选Reflect的方法
"quotes": [1, "single"],//引号类型 `` "" ''
"quote-props":[2, "always"],//对象字面量中的属性名是否强制双引号
"radix": 2,//parseInt必须指定第二个参数
"id-match": 0,//命名检测
"require-yield": 0,//生成器函数必须有yield
"semi": [2, "always"],//语句强制分号结尾
"semi-spacing": [0, {"before": false, "after": true}],//分号前后空格
"sort-vars": 0,//变量声明时排序
"space-after-keywords": [0, "always"],//关键字后面是否要空一格
"space-before-blocks": [0, "always"],//不以新行开始的块{前面要不要有空格
"space-before-function-paren": [0, "always"],//函数定义时括号前面要不要有空格
"space-in-parens": [0, "never"],//小括号里面要不要有空格
"space-infix-ops": 0,//中缀操作符周围要不要有空格
"space-return-throw-case": 2,//return throw case后面要不要加空格
"space-unary-ops": [0, { "words": true, "nonwords": false }],//一元运算符的前/后要不要加空格
"spaced-comment": 0,//注释风格要不要有空格什么的
"strict": 2,//使用严格模式
"use-isnan": 2,//禁止比较时使用NaN,只能用isNaN()
"valid-jsdoc": 0,//jsdoc规则
"valid-typeof": 2,//必须使用合法的typeof的值
"vars-on-top": 2,//var必须放在作用域顶部
"wrap-iife": [2, "inside"],//立即执行函数表达式的小括号风格
"wrap-regex": 0,//正则表达式字面量用小括号包起来
"yoda": [2, "never"]//禁止尤达条件

参考资料:

vim快捷操作整理

Vim常见有两种模式一种是Insert模式,该模式下可以像其它文本编辑器一样正常输入字符;另一种是Normal模式,该模式下Vim监听用户的按键可以对文本进行快速修改。

想要从Insert模式切换到Normal模式只需按下ESC键即可。

想要从Normal模式切换到Insert模式,有很多方法。
最直接的是按下I键,效果是:在当前光标处插入文本。
如果按下A键,效果是:在下一光标处追加文本。

进入和退出vim编辑器:

进入 vi filename(要编辑的文件名字)———>进入了命令模式
命令模式——>输入 :wq——>退出

保存退出

:wq 保存修改并退出
ZZ 快捷键,保存修改并退出(前面没有冒号)
:q! 不保存退出
:wq! 强行保存退出,(文件所属者科忽略文件的制度属性)
:w 保存不退出
:wqa 保存所有文件
:w new_filename 另存为指定文件

vim配置文件,所在目录~/.vimrc

1.修改配置文件时,可以不用加:
2.可将编辑模式下的命令写在里面,每个命令单独一行,这样每次启动时,会自动执行里面的命令。

光标的快速移动

h,j,k,l:左,下,上,右
w:光标移动至下一单词首位
b:光标移动至当前单词首位,如果光标已经在当前单词首位,就移动到前一单词首位
e:光标移动至当前单词末位
gg:光标移动至文本首行
Shift+g:光标移动至文本尾行
27+Shift+g:光标移动至文本第27行

插入行

o:在当前光标的下方插入新一行
Shift+o: 在当前光标的上方插入新一行

删除与还原

x:删除光标后的一个字符
Shift+x:删除光标前的一个字符
dd:删除光标所在整行,同时被删除内容存于剪贴板上
de:删除光标后的单词内容,同时被删除内容存于剪贴板上
dw:删除光标后的单词内容以及之后的空格,同时被删除内容存于剪贴板上
u:还原上一个操作(不限于删除)

剪切、复制与粘贴

选定文本块:使用v进入可视模式;移动光标键选定内容
y:复制选定块
yy:复制光标所在整行
d:剪切选定块
dd:剪切光标所在整行
p:粘贴文本

查找与替换

f+o:在当前行的光标之后查找字母o
f+o:在当前行的光标之后查找字母o
F+b:在当前行的光标之前查找字母b
:/word:全文查找word。 按下:实际上是进入了Vim的命令模式。查找操作支持正则表达式。
r+p:将光标之后的字符替换为字母p
:s/word/replace:光标所在行的第一个word替换为replace。
:%s/from/to/:全文查找from并替换为to。
:1,50s/from/to/:在第1行和第50行之间(含)进行搜索和替换。:45s/from/to/表示仅仅在第45行进行搜索和替换。而1,$行号范围和%是等价的。
:%s/from/to/g:全文查找from并替换为to,包含选项g的替换范围更广。??
:%s/from/to/gc:全文查找from并替换为to,替换时询问。可以选择y/n/a/q/l/^E/^Y:y表示同意当前替换;n表示不同意当前替换;a表示替换当前和后面的并且不再确认;q表示立即结束替换操作;l表示把当前的替换后结束替换操作;^E向上滚屏^Y向下滚屏,用来帮助查看前后内容以决定进行操作。

执行Shell命令

:!ls就等同于在Shell终端执行ls命令。

参考资料:

Mac使用brew安装Nginx、MySQL、PHP的LAMP开发环境

准备工作

新版的 Mac OS 内置了Apache 和 PHP,我的系统版本是OS X 10.9.3,可以通过以下命令查看Apache和PHP的版本号:

1
2
3
4
5
6
7
8
9
10
httpd -v

Server version: Apache/2.2.26 (Unix)
Server built: Dec 10 2013 22:09:38

php --version

PHP 5.4.24 (cli) (built: Jan 19 2014 21:32:15)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies

因为我们要自己动手来安装 Nginx,因此首先来关闭系统自带的apache:

1
sudo apachectl stop  #关闭apache,如果事先没开启过,可以忽略报错信息

如果你的apache已经加入了launchctl,使用下面的命令来关闭:

1
sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist

为什么选择关闭apache?因为mac os x系统自带的apache是没有优雅的remove/uninstall 的方式的… 对于“洁癖”比较严重的童鞋,可以选择直接删除相关的文件!(千万不要手抖删错目录…)

1
2
3
sudo rm /usr/sbin/apachectl
sudo rm /usr/sbin/httpd
sudo rm -r /etc/apache2/

删除自带的php

1
sudo rm -r /usr/bin/php

如果没有安装brew,可以按照官网的步骤安装

1
http://brew.sh/

nginx的安装与配置

安装nginx

1、连接到远程主机:

1
brew install nginx

修改配置文件

1
2
sudo vim /usr/local/etc/nginx/nginx.conf
#修改默认的8080端口为80,小于1024需要root权限

给予管理员权限

1
2
sudo chown root:wheel /usr/local/opt/nginx/bin/nginx
sudo chmod u+s /usr/local/opt/nginx/bin/nginx

加入launchctl启动控制

1
2
3
mkdir -p ~/Library/LaunchAgents
cp /usr/local/opt/nginx/homebrew.mxcl.nginx.plist ~/Library/LaunchAgents/
launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.nginx.plist

运行nginx

1
2
3
sudo nginx #打开 nginx
nginx -s reload|reopen|stop|quit #重新加载配置|重启|停止|退出 nginx
nginx -t #测试配置是否有语法错误

注意:出现Nginx操作错误,可以参照Mac Nginx 安装(源文件安装)

用法详解

1
nginx [-?hvVtq] [-s signal] [-c filename] [-p prefix] [-g directives]

选项列表

1
2
3
4
5
6
7
8
9
-?,-h           : 打开帮助信息
-v : 显示版本信息并退出
-V : 显示版本和配置选项信息,然后退出
-t : 检测配置文件是否有语法错误,然后退出
-q : 在检测配置文件期间屏蔽非错误信息
-s signal : 给一个 nginx 主进程发送信号:stop(停止), quit(退出), reopen(重启), reload(重新加载配置文件)
-p prefix : 设置前缀路径(默认是:/usr/local/Cellar/nginx/1.2.6/)
-c filename : 设置配置文件(默认是:/usr/local/etc/nginx/nginx.conf)
-g directives : 设置配置文件外的全局指令

mysql的安装与配置

安装mysql

1
2
brew install mysql
cd /usr/local/opt/mysql/

修改配置文件

1
2
sudo vim my.cnf
#如果出现无法启动mysql,rm my.cnf

加入launchctl启动控制

1
2
3
4
5
mkdir -p ~/Library/LaunchAgents/
cp /usr/local/opt/mysql/homebrew.mxcl.mysql.plist ~/Library/LaunchAgents/
launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist
#取消启动
#launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist

初始化 mysql

1
./bin/mysql_install_db

执行安全设置脚本,设置root账号密码

1
./bin/mysql_secure_installation

命令行连接mysql

1
mysql -u root -p

php的安装与配置
brew 默认没有 php 安装包:

1
2
brew tap homebrew/dupes
brew tap josegonzalez/homebrew-php

现在可以安装php了:

1
brew install php54 --with-imap --with-tidy --with-debug --with-mysql --with-fpm

将php路径加入PATH

1
2
3
4
sudo vim ~/.bash_profile    
export PATH="$(brew --prefix php54)/bin:$PATH"

source ~/.bash_profile

加入launchctl启动控制

1
2
3
mkdir -p ~/Library/LaunchAgents
cp /usr/local/opt/php54/homebrew.mxcl.php54.plist ~/Library/LaunchAgents/
launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.php54.plist

配置路径

1
2
/usr/local/etc/php/5.4/php.ini
/usr/local/etc/php/5.4/php-fpm.conf

配置 Nginx 支持 PHP-FPM

1
2
3
4
5
6
7
8
9
10
11
12
13
sudo vim /usr/local/etc/nginx/nginx.conf    

# 添加默认首页 php
index index.php index.html index.htm;

# 取消以下内容的注释,并做修改
location ~ \.php$ {
fastcgi_intercept_errors on;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/local/Cellar/nginx/1.6.0_1/html$fastcgi_script_name;
include /usr/local/etc/nginx/fastcgi_params;
}

测试环境

1
2
3
4
5
sudo vim /usr/local/Cellar/nginx/1.6.0_1/html/index.php

#添加测试代码
<?php
phpinfo();

结语

到目前为止,我们的Nginx、MySQL、PHP-FPM三大软件已经安装好了,针对不同的系统版本和软件版本,可能会遇到一些问题,欢迎留言探讨。

原文链接:Mac OS使用brew安装Nginx、MySQL、PHP-FPM的LAMP开发环境

参考资料:

nginx反向代理处理静态页面(转载)

Nginx (“engine x”) 是一个高性能的 HTTP 和 反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本0.1.0发布于2004年10月4日。其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。

尽管Node.JS的性能不错,但处理静态事务确实不是他的专长,如:gzip编码,静态文件,HTTP缓存,SSL处理,负载平衡和反向代理及多站点代理等,都可以通过nginx来完成,从而减小node.js的负载,并通过nginx强大的缓存来节省您网站的流量从而提高网站的加载速度。

虽然node.js也有一些如http-proxy的代理模块可以实现一台服务器上面架设多个网站(每个域名映射到不同nodejs进程的端口),但这种基础性的工作,其实更应该交给ngnix来完成。

下面我们可以看一个多站点代理的例子, 假设你有一个node.js进程正在侦听8080端口,你希望从domaina.com的进入的连接由node.js提供服务,从domainb.com进入的连接映射到另一个静态文件服务的网站,你可以使用下面的ngix.confg(for 1.44),配置比较简单,一般写程序的人应该都能看懂,进行之后你输入http://192.168.0.101, http://localhost会看到不同的结果.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#user  nobody;
worker_processes 2;

error_log logs/error.log;

events {
worker_connections 1024;
}

http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;

gzip on;
gzip_min_length 1k;
gzip_buffers 4 8k;
gzip_http_version 1.1;
gzip_types text/plain application/x-javascript text/css application/xml;

upstream node_app {
server 127.0.0.1:8080;
}

server {
listen 80;
server_name localhost;

location / {
proxy_pass http://node_app;
}
}

# static server
server {
listen 80;
server_name 192.168.0.101;

location / {
root D:\GitHub\areu\web;
index home.html;
}
}
}

这里有一篇更加复杂的示例,由于版本相对陈旧,仅供参考 Using Nginx To Avoid NodeJS Load

简单说明一下,各个部分的作用

指明你网站运行的端口,因为支持http/https所以有两个端口:

1
2
3
4
5
6
7
8
9
http {
...
upstream silly_face_society_upstream {
server 127.0.0.1:61337;
server 127.0.0.1:61338;
keepalive 64;
}
...
}

静态文件拦截器,将以images/js/img/css…开头的地址映射到网站目录,由ngnix直接提供服务:

1
2
3
4
5
6
7
8
9
10
11
12
http {
...
server {
...
location ~ ^/(images/|img/|javascript/|js/|css/|stylesheets/|flash/|media/|static/|robots.txt|humans.txt|favicon.ico) {
root /usr/local/silly_face_society/node/public;
access_log off;
expires max;
}
...
}
}

设置缓存

1
2
3
4
5
6
http {
...
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=one:8m max_size=3000m inactive=600m;
proxy_temp_path /var/tmp;
...
}

设置Gzip压缩

1
2
3
4
5
6
7
8
9
10
11
http {
...
gzip on;
gzip_comp_level 6;
gzip_vary on;
gzip_min_length 1000;
gzip_proxied any;
gzip_types text/plain text/html text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip_buffers 16 8k;
...
}

最后将非静态文件交给nodejs进程去响应:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
http {
...
server {
...
location / {
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
...
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_pass http://silly_face_society_upstream;
}
...
}
}

分享几个nginx调试命令: Debian Linux

安装nginx,使用apt-get 即可

1
apt-get install nginx

测试nginx配置文件

1
nginx -t -c /etc/nginx/nginx.conf

重启nginx服务器

1
/etc/init.d/nginx restart

设置某脚本开机启动

1
2
3
4
5
sudo chmod 755 /etc/init.d/foobar
sudo update-rc.d foobar defaults #开机时启动
sudo update-rc.d -f foobar remove  #开机时不启动

find / -name 'node' #在根目录 '/' 查找 node的位置(某些场合会用到)

有时侯nginx在windows下面怎么杀也杀不死,可以使用此脚本 (Windows 2003 测试有效)

1
taskkill /F /IM nginx.exe > nul

参考资料:

ssh常用命令

1、连接到远程主机:

命令格式 :

1
2
ssh name@remoteserver 或者
ssh remoteserver -l name

说明:以上两种方式都可以远程登录到远程主机,server代表远程主机,name为登录远程主机的用户名。

2、连接到远程主机指定的端口:

命令格式:

1
2
ssh name@remoteserver -p 2222 或者
ssh remoteserver -l name -p 2222

说明:p 参数指定端口号,通常在路由里做端口映射时,我们不会把22端口直接映射出去,而是转换成其他端口号,这时就需要使用-p端口号命令格式。

3、通过远程主机1跳到远程主机2:

命令格式:

1
ssh -t remoteserver1 ssh remoteserver2

说明:当远程主机remoteserver2无法直接到达时,可以使用-t参数,然后由remoteserver1跳转到remoteserver2。在此过程中要先输入remoteserver1的密码,然后再输入remoteserver2的密码,然后就可以操作remoteserver2了。

4、公钥登录免密码登录

使用密码登录,每次都必须输入密码,非常麻烦。好在SSH还提供了公钥登录,可以省去输入密码的步骤。

所谓”公钥登录”,原理很简单,就是用户将自己的公钥储存在远程主机上。登录的时候,远程主机会向用户发送一段随机字符串,用户用自己的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,如果成功,就证明用户是可信的,直接允许登录shell,不再要求密码。

这种方法要求用户必须提供自己的公钥。如果没有现成的,可以直接用ssh-keygen生成一个:

1
$ ssh-keygen

运行上面的命令以后,系统会出现一系列提示,可以一路回车。其中有一个问题是,要不要对私钥设置口令(passphrase),如果担心私钥的安全,这里可以设置一个。

运行结束以后,在$HOME/.ssh/目录下,会新生成两个文件:id_rsa.pub和id_rsa。前者是你的公钥,后者是你的私钥。

1
2
3
//查看公钥,如下
➜ ~ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCrP9L9GGttZgk3HQ/gfi9O6snm8J0atMGWet9NHGlzj+Di2eziYL5qWYrPiwIfLVYQ7IHLHM2k5WJl4cQoVj2mWpvq0feRfMBvRemfKb/F2jVKcFTJthzfyt+yQQ3p/HxoEwhpbJ2i1wDk77ANBIPFUtSdBbNoFsX7ftxYBKvsHRojWj4ZYuZZ39lXkZjt61k6Wr89iZlI9bPuhJFMVs83l37Tx/Losstj4NaO48IEdUGiEBzGX8lVWzw8vc6amHN5WN+sdfsdfsdsdf/vFkKLHd/6t+LvhoLRadHzSwqXRqDCY7ikixLh001b9sV8MO2jYp9R6B6zKBD6X3dah2+ulzjaNQuvAiZjxSMO7xALQxPI59qxWhbMYLgzXYe8hswZWZ+ClIzdLFsYX2BeQVfFM3sroi9A2kRmSGvTNgmBLxehBECv6eLcvQDBRwj69NtHNS4T5obnfN7MHKNRQI7jpNFqTQ6h23C+7VG16ec42MHggRcIjKFw57sq/6dmjKiYxwM16JKADrVvFxDzaQbuRgvvh0+d9mxwU/ejQic7CE3E7an35yTH9b4g3yJh+5QOMBEyurMpAQjMdZOrOLw== sdfsdfsdfsd@qq.com

这时再输入下面的命令,将公钥传送到远程主机host上面:

1
$ ssh-copy-id user@host  [-p 端口]

好了,从此你再登录,就不需要输入密码了。
如果还是不行,就打开远程主机的/etc/ssh/sshd_config这个文件,检查下面几行前面”#”注释是否取掉。

1
2
3
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys

然后,重启远程主机的ssh服务。

1
2
3
4
// ubuntu系统
service ssh restart
// debian系统
/etc/init.d/ssh restart

authorized_keys文件

远程主机将用户的公钥,保存在登录后的用户主目录的$HOME/.ssh/authorized_keys文件中。公钥就是一段字符串,只要把它追加在authorized_keys文件的末尾就行了。

这里不使用上面的ssh-copy-id命令,改用下面的命令,解释公钥的保存过程:

1
$ ssh user@host 'mkdir -p .ssh && cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub

这条命令由多个语句组成,依次分解开来看:(1)”$ ssh user@host”,表示登录远程主机;(2)单引号中的mkdir .ssh && cat >> .ssh/authorized_keys,表示登录后在远程shell上执行的命令:(3)”$ mkdir -p .ssh”的作用是,如果用户主目录中的.ssh目录不存在,就创建一个;(4)’cat >> .ssh/authorized_keys’ < ~/.ssh/id_rsa.pub的作用是,将本地的公钥文件~/.ssh/id_rsa.pub,重定向追加到远程文件authorized_keys的末尾。

写入authorized_keys文件后,公钥登录的设置就完成了。

5、通过SSH运行远程shell命令:

命令格式:

1
2
ssh -l name remoteserver ‘command’ 
例 $ ssh -l root 192.168.1.100 svmon -G

说明:连接到远程主机,并执行远程主机的command命令。例如:查看远程主机的内存使用情况。

6、修改SSH监听端口:

默认情况下,SSH监听连接端口22,攻击者使用端口扫描软件就可以看到主机是否运行有SSH服务,将SSH端口修改为大于1024的端口是一个明智的选择,因为大多数端口扫描软件(包括nmap)默认情况都不扫描高位端口。打开/etc/ssh/sshd_config文件并查找下面这样的行:

1
Port  22

去掉该行前面的# 号,然后修改端口号并重新启动SSH服务:

1
$ /etc/init.d/ssh restart

7、仅允许SSH协议版本2:
有两个SSH协议版本,仅使用SSH协议版本2会更安全,SSH协议版本1有安全问题,包括中间人攻击(man-in-the-middle)和注入(insertion)攻击。编辑/etc/ssh/sshd_config文件并查找下面这样的行:

1
# Protocol 2,1

修改为

1
Protocol 2

8、禁止root用户登录:
通常情况下,不采用直接用root用户登录到远程主机,由于root用户拥有超级权限,这样会带来安全隐患,所以,一般我们用普通用户登录,当需要管理远程主机时,再切换到root用户下。打开/etc/ssh/sshd_config文件并查找下面这样的行:

1
#PermitRootLogin yes

将#号去掉,然后将yes修改成no,重启ssh服务,这样就可以禁止root用户登录。

9、设置登录时提示信息
首先编辑一个文件,如bannertest.txt,文件内容自行定义。然后打开/etc/ssh/sshd_config文件并查找下面这样的行:

1
#Banner /some/path

将#号去掉,然后将bannertest.txt文件的全路径替换/some/path,然后保存,重启ssh服务。当客户端登录时,就会看到bannertest.txt文件中的提示信息。

10、进行端口映射:

假如公司内网有台web服务器,但是只对内不对外,这样,外网就无法访问,可以用ssh进行端口映射来实现外网访问内网的web服务器。假如web服务器名为webserver,webserver可以用ssh访问到远端主机remoteserver,登录到webserver,然后用下面命令进行映射

命令格式:

1
ssh -R 3000:localhost:80 remoteserver

执行完成后,在remoteserver机器上,执行netstat -an | grep 3000,查看有没有开通3000端口。并执行以下命令观察是否可以打开webserver上的网页

1
$ w3m http://127.0.0.1:3000

如果能打开界面,说明映射成功.但是,这只限于本机访问web服务器,即只能remoteserver机器访问webserver。因为3000端口绑定的是remoteserver机器的127.0.0.1端口。可以编辑remoteserver机器上的/etc/ssh/sshd_config文件并添加如下内容:
添加 GatewayPorts yes 内容,把监听端口3000绑定到 0.0.0.0 地址上,这样外部的所有机器都能访问到这个监听端口,然后保存退出。并重启ssh服务。完成后其它机器就可以在浏览器中输入 http://remoteserver:3000来访问webserver了。

SSH 简易登录

查看 cat ~/.ssh/config 文件(如果不存在则 touch ~/.ssh/config 创建一下),添加以下内容:

1
2
3
4
5
6
7
8
Host HOST_ALIAS                       # 用于 SSH 连接的别名,最好与 HostName 保持一致
HostName SERVER_DOMAIN # 服务器的域名或 IP 地址
Port SERVER_PORT # 服务器的端口号,默认为 22,可选
User SERVER_USER # 服务器的用户名

#密钥对应正确下面两行可以不要
PreferredAuthentications publickey
IdentityFile ~/.ssh/PRIVATE_KEY # 本机上存放的私钥路径

参考资料:

SVG、SVG Symbol组件化实践

前言

随着移动互联网的到来,各种高清屏幕移动设备的层出不穷,导致H5应用在移动设备retina屏幕下经常会遇到图标不清晰的问题。

为了解决屏幕分辨率对图标影响的问题,通常采用CSS Sprite,Icon Font,CSS Icon以及SVG以适应@x1屏、@2屏、@3屏,相对比较而言SVG矢量性、缩放无损等诸多优点,更应受前端设计师的青睐,可在许多公司的移动项目应用中却很鲜见,究其主因在于SVG开发学习成本比较高以及在绘制的性能上比PNG要差。此篇文章将从SVG快速导出到SVG、SVG Symbol组件化在项目中实战进行讲解,教你如何提高SVG开发效率减少成本。

SVG简介

SVG是一种开放标准的矢量图形语言,使用svg格式我们可以直接用代码来描绘图像,可以用任何文字处理工具打开svg图像,通过改变部分代码来使图像具有交互功能,并可以随时插入到HTML中通过浏览器来浏览。

SVG优缺点:

优点 缺点
1.缩放无损还原,显示清晰 1.SVG在绘制的性能上比PNG要差
2.语义性良好 2.局限性,对应单色或普通渐变没什么问题,但对不规则的渐变以及特效叠加效果显示不全
3.可用CSS控制图标样式以及动画 3.兼容性稍差,android4.1才开始支持
4.减少http请求 4.学习应用成本较高

Web应用中SVG的使用方式

1.使用img、object、embed 标签直接引用svg
此方法的缺点主要在于每个图标都需单独保存成一个 SVG 文件,使用时单独请求,增加了HTTP请求数量。

1
<img src="http://www.w3school.com.cn/svg/rect1.svg"  width="300" />

2.Inline SVG,直接把SVG写入 HTML 中

Inline SVG 作为HTML文档的一部分,不需要单独请求。临时需要修改某个图标的形状也比较方便。但是Inline SVG使用上比较繁琐,需要在页面中插入一大块SVG代码不适合手写,图标复用起来也比较麻烦。

1
2
3
4
5
6
<body>
<svg width="100%" height="100%">
<rect x="20" y="20" width="250" height="250"
style="fill:#fecdddd;"/>
</svg>
</body>

3.SVG Sprite

这里的Sprite技术,类似于CSS中的Sprite技术。图标图形整合在一起,实际呈现的时候准确显示特定图标。其实基础的SVG Sprite也只是将原来的位图改成了SVG而已,控制SVG大小、颜色需要重新合并SVG文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.icon-bg{
display: inline-block;
width: 30px;
height: 30px;
background: url(./res/svg-sprite-background.svg);
background-size:100% 100%;
}
.icon-facebook-logo{
background-position: 0 0;
}
.icon-earth{
background-position: 0 -30px;
}


<span class="icon-bg icon-facebook-logo"></span>
<span class="icon-bg icon-earth"></span>

4.使用 SVG 中的 symbol,use 元素来制作SVG Sprite
SVG Symbols的使用,本质上是对Sprite的进一步优化,通过<symbol>元素来对单个svg元素进行分组,使用<use>元素引用并进行渲染。这种方法的解决了上述三种方式带来的弊端,少量的http请求,图标能被缓存方便复用,每个SVG图标可以更改大小颜色,整合、使用以及管理起来非常简单。

①SVG Symbols作为body的第一个元素插入在HTML中使用:

1
2
3
4
5
6
7
8
9
10
11
<body>
<svg style="width:0; height:0; visibility:hidden;position:absolute;z-index:-1">
<symbol viewBox="0 0 24 24" id="heart">
<path fill="#E86C60" d="M17,0c-1.9,0-3.7,0.8-5,2.1C10.7,0.8,8.9,0,7,0C3.1,0,0,3.1,0,7c0,6.4,10.9,15.4,11.4,15.8 c0.2,0.2,0.4,0.2,0.6,0.2s0.4-0.1,0.6-0.2C13.1,22.4,24,13.4,24,7C24,3.1,20.9,0,17,0z"></path>
</symbol>
</svg>

<svg>
<use xlink:href="#heart"/>
</svg>
</body>

②使用完整路径引用Icon(此方法涉及到跨域问题)

存在跨域问题,同域可以使用。

1
2
3
4
5
6
7
8
9
<body>
//路径形式进行获取icon
<svg>
<use xlink:href="/asset/svg-symbols.svg#heart"/>
</svg>
<svg>
<use xlink:href="/asset/svg-symbols.svg#heart"/>
</svg>
</body>

③js控制svg写入body进行引用

推荐使用,有效分离结构和展现、解决缓存以及跨域问题。

svg.js:

1
2
3
4
5
6
var symbols = '<svg style="width:0; height:0; visibility:hidden;position:absolute;z-index:-1">
<symbol viewBox="0 0 24 24" id="heart">
<path fill="#E86C60" d="M17,0c-1.9,0-3.7,0.8-5,2.1C10.7,0.8,8.9,0,7,0C3.1,0,0,3.1,0,7c0,6.4,10.9,15.4,11.4,15.8 c0.2,0.2,0.4,0.2,0.6,0.2s0.4-0.1,0.6-0.2C13.1,22.4,24,13.4,24,7C24,3.1,20.9,0,17,0z"></path>
</symbol>
</svg>';
document.body.insertAdjacentHTML("afterBegin",symbols)

svg.html:

1
2
3
4
5
6
7
8
<body>
//脚本需在svg use引用之前引入
<script src = "/asset/svg.js"></script>

<svg>
<use xlink:href="#heart"/>
</svg>
</body>

SVG快速导出

SVG导出工具:

Photoshop CC 2015 导出svg使用

Ps可以对矢量图层进行导出,即通过矢量工具绘制所在图层或图层文件夹进行导出,若对不是矢量图形进行导出,可能会引起错误或者导出的文件是位图。

SVG导出,建议图形一定要撑满整个画布,若存在间隙,网页使用时图标居中对齐就会比较麻烦。

1.批量导出SVG
批量导出SVG,只需在矢量图层或失落图层文件夹名后添加相应格式后缀(如.svg),依次点击菜单“文件->生成->图像资源”,确认该菜单项已被勾选。但是此方法会根据icon实际大小进行导出,若icon图标存在小数导出就不太适用,我们需要手动去调节。

批量导出SVG

2.设置导出为单个导出
设置导出为单个导出,选中矢量图层单击右键,依次点击“导出为->设置参数->导出”,此方法可以设置svg的图像实际大小,以及画布大小。

导出为:
批量导出SVG

设置导出svg图像实际大小,以及画布大小:
批量导出SVG

SVG Symbol自动化合并生成

Ps导出来的是单个svg文件,需要将这些单个svg文件进行合并生产symbol的SVG,这样才能通过symbol+use进行引用。可以使用手工合并,推荐使用工具,安利给大家一个专门用于处理SVG Symbols用的glup插件gulp-svg-symbols

下面我们就来以一个实例一步一步来使用下这个插件。

首先新建一个文件夹,目录结构如下图所示:

1
2
3
4
5
6
7
8
9
assets
├── svg //存放ps导出的大量svg文件
├── xxx.svg
├── xxx.svg
├── xxx.svg
├── out
├── gulpfile.js
├── package.json
├── index.html

安装gulp-svg-symbols插件,若没有预先安装gulp请先行安装:

1
npm i gulp-svg-symbols  --save

gulpfile.js写入如下执行任务:

1
2
3
4
5
6
7
8
9
10
'use strick';
const gulp = require("gulp");
const symbols = require("gulp-svg-symbols");

//转换svg
gulp.task('svg', () => {
return gulp.src('./svg/**')
.pipe(symbols())
.pipe(gulp.dest('out/'))
});

执行任务导出svg-symbols:

1
gulp svg  //out文件夹,生成svg-symbols.svg,svg-symbols.css(此文件对应svg样式,基本无用)

SVG组件化实践

鉴于移动端全站规范的统一性,页面之间会存在许多的图标复用,为了引入svg图标复用性问题,引入了SVG组件化,SVG组件化主要包含三部分:SVG展示平台、SVG自动化工具、SVG Git仓库。
流程

设计师出图标规范 —-> Ps导出svg —-> 工具自动化合并svg symbol —-> 上传Git仓库管理 —-> SVG平台展示快速获取svg symbol

工具生成部分已上传Github,svgicon,快速生成svg symbol,对生产svg大小带小数进行预警

SVG展示平台,提供预览快速查找svg,点击下载使用。

参考资料: