kylin

醉里论道,醒时折花。

kylin

关于js异步

同步Ajax

在任何情况下都不应该使用这种方式,因为它会锁定浏览器UI(按钮、菜单、滚动条等),并阻塞所有的用户交互。

error-first风格的超时报错处理

1
2
3
4
5
6
7
8
9
10
11
12
13
function timeoutify(fn,delay){
var intv = setTimeout( function(){
intv = null
fn(new Error("Timeout"))
},delay)
return function(){
if(intv){
clearTimeout(intv)
fn.apply(this,arguments)
}
}
}

阅读全文

js对象属性的getter与setter

总述

我们知道对象是由名字、值和一组特性(attribute)构成的。在ECMAScript5.1中,属性值可以用一个或两个方法替代,这两个方法就是gettersetter。由gettersetter定义的属性称作“存取器属性”(accessor property),它不同于“数据属性”(data property),数据属性只有一个简单的值。

  • 当程序查询存取器属性的值时,调用getter方法(无参)
  • 当程序设置一个存取器属性的值时,调用setter方法,赋值表达式右侧的值作为参数传入setter

存取器属性不具有可写性。如果属性同时拥有gettersetter,那么它是一个读/写属性。如果只有getter(或者setter),那么他就是一个只读(写)属性。读取只写属性总是返回 undefined

定义setter和getter的几种方式

在新对象初始化时定义(ES5.1)

1
2
3
4
5
6
7
8
9
10
11
12
13
var obj = {
value:1,
get access_prop(){
return this.value
},
set access_prop(value){
this.value = value
}
}
console.log(obj.access_prop)//1
obj.access_prop = 2
console.log(obj.access_prop,obj.value)//2 2

阅读全文

snabbdom源码阅读笔记(二)

hook

name 调用时间 参数
pre patch 开始的时候
init vnode 被添加时 vnode
create a DOM element has been created based on a vnode emptyVnode vnode
insert an element has been inserted into the DOM vnode
prepatch patch 开始之前 oldVnode, vnode
update an element is being updated oldVnode, vnode
postpatch an element has been patched oldVnode, vnode
destroy an element is directly or indirectly being removed vnode
remove an element is directly being removed from the DOM vnode, removeCallback
post patch结束之后

snabbdom源码阅读笔记(一)

vnode结构

vnode结构定义在vnode.js中

1
2
3
4
5
module.exports = function(sel, data, children, text, elm) {
var key = data === undefined ? undefined : data.key;
return {sel: sel, data: data, children: children,
text: text, elm: elm, key: key};
};

vnode属性

  • sel: (string | undefined) css选择器 如 div#contianer.class1
  • data: (VNodeData | undefined) virtual dom包含的数据
  • children: (Array | undefined) virtual dom 的子节点 可以使vnode或者字符串
  • elm: (Node | undefined) 对dom element的引用
  • text: (string | undefined)元素的文本内容
  • key: Key 用于提示 children patch 过程

h函数

h函数定义在h.js中

  • 对存在data和不存在data的情况进行了分开处理
  • 并将子元素中的 primitive 类型包装成vnode (is.arrayis.primitive 定义在 is.jsprimitive 指 参数是否是StringNumber类型)
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
module.exports = function h(sel, b, c) {
var data = {}, children, text, i;
// 若c存在(存在第三个参数)
if (c !== undefined) {
data = b;
// 若c是数组
if (is.array(c)) { children = c; }
// c是String或者Number,则直接赋值
else if (is.primitive(c)) { text = c; }
} else if (b !== undefined) { //若存在data
//如果b是数组(b参数为子元素数组)
if (is.array(b)) { children = b; }
// 如果b是String或Number
else if (is.primitive(b)) { text = b; }
// b是data
else { data = b; }
}
// 循环children数组
if (is.array(children)) {
for (i = 0; i < children.length; ++i) {
// 若当前子元素是字符串或数字,则将其包装成vnode
if (is.primitive(children[i])) children[i] = VNode(undefined, undefined, undefined, children[i]);
// VNode(sel,data,children,text,elm,key)
}
}
// tagName若为svg,则特殊处理
if (sel[0] === 's' && sel[1] === 'v' && sel[2] === 'g') {
addNS(data, children, sel);
}
// 返回VNode
return VNode(sel, data, children, text, undefined);
};

阅读全文

常用操作命令

删除

删除文件夹以及文件夹中的所有文件命令:

1
rm -rf 目录名字

其中:

1
2
-r:向下递归删除
-f:直接强行删除,且没有任何提示

删除文件命令

1
rm -f 文件名

将会强行删除文件,且无提示

使用rm -rf要格外注意,linux中没有回收站,慎重删除

新建文件与文件夹

1
2
cd /someDir 定位到目标目录
mkdir test 新建一个叫test的文件夹
1
touch test/a.txt 在test文件夹下建一个名为a.txt的文件

阅读全文

使用mac在远程linux上安装node

链接 ECS 实例

1
$ ssh username@remotehost //如 ssh root@115.20.39.163

接下来会提示输入登录密码,在冒号之后输入然后回车

1
root@115.20.39.163's password:

成功登录后会提示

1
2
3
4
5
6
7
8
Welcome to Ubuntu 14.04.4 LTS (GNU/Linux 3.13.0-86-generic x86_64)
* Documentation: https://help.ubuntu.com/
New release '16.04.1 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
Welcome to aliyun Elastic Compute Service!

阅读全文

canvas-flower

canvas彩色小花

Demo

实现原理

我们的小花是由36片叶片围绕圆形构成

原理大致分为三部分

  • 如何生成花瓣
  • 如何绕圆心生成花瓣
  • 如何实现色环

如何生成花瓣

这里主要使用的是canvasarcTo()这个方法

arcTo()方法用于画布上创建介于两个切线之间的弧

Demo

1
2
3
4
5
6
7
8
var thisCanvas = document.getElementsByTagName('canvas')[0];
var x = thisCanvas.getContext('2d');
x.beginPath();
x.moveTo(100, 100);
x.arcTo(200, 100, 200, 200, 100);
x.strokeStyle = "rgba(0,0,0,0.5)";
x.stroke();

这里分别以A(100,100),C(200,100),B(200,200)为端点,100为半径(AD),D为圆形画与AC,BC相切的圆弧

两条圆弧即可拼成一片花瓣

如何绕圆心生成花瓣

如图

我们需要绕圆心生成n个花瓣,每个花瓣的两端分别位于半径为r和半径为R的圆上。这里的变量为两点连线相对于水平线的夹角,即∠COB

我这边需要36个花瓣,所以每个花瓣的角度增量为PI/18

我们设定东方水平线上为第一片花瓣

假设我们要花第i片花瓣(假设以图上的EC为端点),我们需要的数值有 点O,E,H,D,C的坐标,以及圆弧半径ED

1
2
3
4
E.x = r*Math.cos(Math.PI/18*i)
E.y = r*Math.sin(Math.PI/18*i)
C.x = R*Math.cos(Math.PI/18*i)
C.y = R*Math.sin(Math.PI/18*i)

接下来要求点H,D的坐标
以点H为例子
假设将点H移到G这个位置

1
2
3
4
5
var xr = 0.707(R-r) //OG的长度
G.x = xr*Math.cos(Math.PI/18*i+Math.PI/4) //45度+当前角度
G.y = xr*Math.sin(Math.PI/18*i+Math.PI/4)
H.x = G.x + (R-r)/2
H.y = G.y + (R-r)/2

由此可推点D坐标

以上就是我们所需的全部数据了,需要注意的是,当年计算所得是相对于圆心的坐标,还要装换成相对于canvas左上角的坐标

最终代码如下:

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
function draw(i){
x.beginPath();
var pointr = {
x:r*Math.cos(baseIncrement*i)+centerPoint.x,
y:r*Math.sin(baseIncrement*i)+centerPoint.y
};
var pointR = {
x:R*Math.cos(baseIncrement*i)+centerPoint.x,
y:R*Math.sin(baseIncrement*i)+centerPoint.y
}
x.moveTo(pointr.x, pointr.y);
var y1 = xr*Math.sin(baseIncrement*i-Math.PI/4)+r*Math.sin(baseIncrement*i)+centerPoint.y;
var x1 = xr*Math.cos(baseIncrement*i-Math.PI/4)+r*Math.cos(baseIncrement*i)+centerPoint.x;
var y2 = xr*Math.sin(baseIncrement*i+Math.PI/4)+r*Math.sin(baseIncrement*i)+centerPoint.y;
var x2 = xr*Math.cos(baseIncrement*i+Math.PI/4)+r*Math.cos(baseIncrement*i)+centerPoint.x;
x.arcTo(x1, y1, pointR.x, pointR.y, xr);
x.arcTo(x2, y2,pointr.x,pointr.y, xr);
x.closePath();
rr-=u/-36;
var red = Math.cos(rr)*127+128;
var green = Math.cos(rr+u/3)*127+128;
var blue = Math.cos(rr+u/3*2)*127+128;
x.fillStyle = "#dadada"//色彩计算
x.fill();
}

再用一个循环来生成36个花瓣

1
2
3
for(var i=0;i<36;i++){
draw(i);
}

如何实现色环

色环的生成原理可以参考这里

最后

然后就能生成小花拉~

这里还实现了一个滚动版本Demo
一个变异版本Demo
完毕(~ ̄▽ ̄)~

数组合并并去重

数组合并并去重

Demo

Write a function that takes one or more arrays and returns a new array of unique values in the order of the original provided arrays.

In other words, all values present from all arrays should be included in their original order, but with no duplicates in the final array.

The unique numbers should be sorted by their original order, but the final array should not be sorted in numerical order.

讲两个数组合并并去掉重复的部分

如:

[1, 2], [3, 4] => [1,2,3,4]

[1, 3, 2], [5, 2, 1, 4], [2, 1] => [1, 3, 2, 5, 4]

[4, "a", 2], [] => [4, "a", 2]

普通版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function uniteUnique() {
//your code here
var obj = {};
var res = [];
for(var i in arguments){
arguments[i].forEach(function(e){
if(!obj[e]){
res.push(e);
obj[e] = true;//讲当前值作为键,值为true
}
});
}
return res;
}

arguments是一个隐藏参数,能够获取到所有传递进来的参数,是一个对象

阅读全文

如何用js画一条彩带

前言

前阵子看到尤小右同学的主页上有这样一个彩带点这里

观察了小右的知乎回答之后,找到了实现原理(~ ̄▽ ̄)~ 原理点这里

于是实现了一个简单版本Demo

简单版demo没有专门去计算三角形第三个点的坐标范围,有小小的瑕疵,常常不能横满整个屏幕

原理

主要分成以下几块

  • 如何生成彩虹色
  • 如何绘制连续的三角形

如何生成彩虹色

彩虹色Demo
首先,如何生成一条灰带?

正弦波能帮助我们连续地产生-1~1之间的数,可以满足我们的需求


1
2
3
4
5
var frequency = .3;
for (var i = 0; i < 32; ++i)
{
Document.write( Math.sin(frequency * i) );
}

frequency约等于6.2时,正好一个周期(正弦波的周期为2PI 约等于6.2)

Degrees Radians
0 0
90 π/2
180 π
270 3π/2
360

阅读全文

如何在内层div滚动到底部时禁止外部div滚动

做过微信端(特别是IOS)web开发的小伙伴一定遇到过这样一个问题:
微信内嵌浏览器的顶部是可以下拉的(ios下底部还能上拉),会显示网页有XXXX提供,QQ浏览器X5内核提供技术支持
平时看到这个可能觉得还好,但若是下面我们自己的网页中有一个需要滚动的div(overflow-y:scroll)时,这个就极其恶心了,拉倒底部时再往下拉,会导致微信浏览器顶部下拉(ios拉倒顶部时上拉则会导致整个页面上拉,下方露出一大片黑色)
这是因为内部div滚动到头之后会带动webview滚动
我们可以通过禁止默认事件来解决,当滚动到底部时,判断touchmove是否是向下滚动,若是,则event.preventDefault(),反之亦然
具体代码如下

阅读全文