一个微型 Javascript 开源项目如何在 4 天到 1000 star ?

atool 发表了文章 • 0 个评论 • 527 次浏览 • 2016-09-13 11:25 • 来自相关话题

这里要提到的是我之前从项目抽离出来的微型 Javascript 项目 timeago.js,为什么是微型,因为他还不到 2kb,这个也是做这个项目的原因之一。
 
已有的类似项目不是一般都依赖 jQuery 和 moment.js,实际上仅仅用到其中的选择器、一个日期方法(fromNow),为了这么一点方法依赖,而引入则好么大的库,个人感觉不是很划算。
 
https://github.com/hustcc/timeago.js 项目大概开始于今年6月底左右,抽离出来,npm publish之后,在自己的多个项目中使用良好,就没有再多做更新了,后来因为另外一个项目中的 PR 引用到 timeago.js 项目,所以决定好好做一做,并推广一下,并陆续增加修改如下东西:
 
1. 增加实时更新方法 render,可以选择一些节点实时更新和计算;
2. 完善Testcase,使用travis CI;
3. 申请域名 timeago.org,后来因为这个域名和其他项目产生了一些不愉快,不过无所谓,我很大条;
4. 更新优化本地化文件的格式;
5. 新开一个 issue 专门记录 locale 的 pr;
 
然后将域名 timeago.org 发到 Hack New上,然后就是域名被老外转到reddit,并且关于创造更小的轮子,依赖jQuery这些问题引起了一些争论,再然后就过了一天,就上了 Github 的 Trending 总榜,目前已经在榜上 4 天了。就在这次天内,star 数量瞬间达到 1000 +,自己还是很激动的。
 
说说自己的感想吧?
 
1. 如果真的想好好做一个项目,还是申请一个合适的域名吧,这样可能会给人更加专业,更加重视的感觉;
2. 老外真的特别喜欢发 pr 和 issue,可能是国内程序员的时间被商人完全榨干了;
3. 保证项目有完善的测试,travis CI集成起来其实非常简单;
4. 项目特色,比如timeago.js特色就是tiny(1.75 kb完成其他项目依赖 jQ 的事情),并且在多个 issue 中要求 pr 一定要保证代码的简洁;
5. PR 规范,比如 timeago.js 中的主要 pr 来源于本地化语言的翻译,所以我会专门开一个issue来展现需要 pr 哪些语言,然后大家一目了然,可以增加大家 pr 的积极性;
 
做好这些之后,就可以到一些技术论坛发发文章,博客了,具体发哪些位置呢?
 
Hack New、开发者头条、V2ex、OSChina、segmentfault、极客头条等等。我对国外技术站点不是很了解,仅仅发了 Hack New。
  查看全部
这里要提到的是我之前从项目抽离出来的微型 Javascript 项目 timeago.js,为什么是微型,因为他还不到 2kb,这个也是做这个项目的原因之一。
 
已有的类似项目不是一般都依赖 jQuery 和 moment.js,实际上仅仅用到其中的选择器、一个日期方法(fromNow),为了这么一点方法依赖,而引入则好么大的库,个人感觉不是很划算。
 
https://github.com/hustcc/timeago.js 项目大概开始于今年6月底左右,抽离出来,npm publish之后,在自己的多个项目中使用良好,就没有再多做更新了,后来因为另外一个项目中的 PR 引用到 timeago.js 项目,所以决定好好做一做,并推广一下,并陆续增加修改如下东西:
 
1. 增加实时更新方法 render,可以选择一些节点实时更新和计算;
2. 完善Testcase,使用travis CI;
3. 申请域名 timeago.org,后来因为这个域名和其他项目产生了一些不愉快,不过无所谓,我很大条;
4. 更新优化本地化文件的格式;
5. 新开一个 issue 专门记录 locale 的 pr;
 
然后将域名 timeago.org 发到 Hack New上,然后就是域名被老外转到reddit,并且关于创造更小的轮子,依赖jQuery这些问题引起了一些争论,再然后就过了一天,就上了 Github 的 Trending 总榜,目前已经在榜上 4 天了。就在这次天内,star 数量瞬间达到 1000 +,自己还是很激动的。
 
说说自己的感想吧?
 
1. 如果真的想好好做一个项目,还是申请一个合适的域名吧,这样可能会给人更加专业,更加重视的感觉;
2. 老外真的特别喜欢发 pr 和 issue,可能是国内程序员的时间被商人完全榨干了;
3. 保证项目有完善的测试,travis CI集成起来其实非常简单;
4. 项目特色,比如timeago.js特色就是tiny(1.75 kb完成其他项目依赖 jQ 的事情),并且在多个 issue 中要求 pr 一定要保证代码的简洁;
5. PR 规范,比如 timeago.js 中的主要 pr 来源于本地化语言的翻译,所以我会专门开一个issue来展现需要 pr 哪些语言,然后大家一目了然,可以增加大家 pr 的积极性;
 
做好这些之后,就可以到一些技术论坛发发文章,博客了,具体发哪些位置呢?
 
Hack New、开发者头条、V2ex、OSChina、segmentfault、极客头条等等。我对国外技术站点不是很了解,仅仅发了 Hack New。
 

React 如何跨组件进行通信?组件和组件之间如何通信?

atool 发表了文章 • 0 个评论 • 736 次浏览 • 2016-07-15 17:04 • 来自相关话题

react最近在项目中用的很爽,不用操作js dom会方便很多;另外组件的封装,state绑定界面,爽的不要不要的。
 
但是项目中经常会遇到跨组件的通信。这个可以分成两类:
一类是父组件和子组件之见的通信;
一类是完全两个不相干的组件之前的通信,通常这两个组件是由路由(router)分割开了。
 
分别介绍一下,对于第一类:父子组件的通信,其实很容易通过子组件传递一个function类型的属性来解决,示例如下:
const Parent = React.createClass({
test_func: function(data) {
},
render: function(){
<Child funcProp={this.test_func} />
}
});

const Child = React.createClass({
propTypes: {
funcProp: React.PropTypes.func
},
componentDidUpdate: function() {
this.props.funcProp('send data to parent');
},
render: function(){
<div>child component.</div>
}
});通过子组件的 funcProp 属性方法就可以进行消息发送和通信。这种方式对于两个组件直接父子关系还比较好用,但是对于跨级的父子组件(实际上已经可以叫做爷子组件),或者评级的兄弟组件,他们之间的通信就比较麻烦了,需要传递好几层的数据。
 
这种情况我们都可以和第二类算作一起,作为跨组件的通信。我在项目中同样也遇到了,所以封装了一个简单的实现,大小才0.7kb左右,非常精简。代码为:https://github.com/hustcc/onfire.js
 
安装 npm install onfire.js
使用实例:
import onfire from 'onfire.js';

// 绑定事件
var eventObj = onfire.on('test_event', function(data) {
console.log('this is a event 1');
});
var eventObj2 = onfire.on('test_event', function(data) {
console.log('this is a event 2');
});

// 触发事件
onfire.fire('test_event', 'test_data');

// 取消绑定
onfire.un(eventObj); // 取消绑定这个事件.
onfire.un('test_event'); // 取消绑定所有的 `test_event`.

// 长度
onfire.size();当然这个库也可以直接使用script标签引入使用。
 
  查看全部
react最近在项目中用的很爽,不用操作js dom会方便很多;另外组件的封装,state绑定界面,爽的不要不要的。
 
但是项目中经常会遇到跨组件的通信。这个可以分成两类:
一类是父组件和子组件之见的通信;
一类是完全两个不相干的组件之前的通信,通常这两个组件是由路由(router)分割开了。
 
分别介绍一下,对于第一类:父子组件的通信,其实很容易通过子组件传递一个function类型的属性来解决,示例如下:
const Parent = React.createClass({
test_func: function(data) {
},
render: function(){
<Child funcProp={this.test_func} />
}
});

const Child = React.createClass({
propTypes: {
funcProp: React.PropTypes.func
},
componentDidUpdate: function() {
this.props.funcProp('send data to parent');
},
render: function(){
<div>child component.</div>
}
});
通过子组件的 funcProp 属性方法就可以进行消息发送和通信。这种方式对于两个组件直接父子关系还比较好用,但是对于跨级的父子组件(实际上已经可以叫做爷子组件),或者评级的兄弟组件,他们之间的通信就比较麻烦了,需要传递好几层的数据。
 
这种情况我们都可以和第二类算作一起,作为跨组件的通信。我在项目中同样也遇到了,所以封装了一个简单的实现,大小才0.7kb左右,非常精简。代码为:https://github.com/hustcc/onfire.js
 
安装 npm install onfire.js
使用实例:
import onfire from 'onfire.js';

// 绑定事件
var eventObj = onfire.on('test_event', function(data) {
console.log('this is a event 1');
});
var eventObj2 = onfire.on('test_event', function(data) {
console.log('this is a event 2');
});

// 触发事件
onfire.fire('test_event', 'test_data');

// 取消绑定
onfire.un(eventObj); // 取消绑定这个事件.
onfire.un('test_event'); // 取消绑定所有的 `test_event`.

// 长度
onfire.size();
当然这个库也可以直接使用script标签引入使用。
 
 

百度Echart 3.0的react封装

atool 发表了文章 • 0 个评论 • 1090 次浏览 • 2016-06-12 18:59 • 来自相关话题

github项目地址:https://github.com/hustcc/echarts-for-react
DEMO地址:http://git.hust.cc/echarts-for-react/#/?_k=l9a9ca
 
使用非常简单
一、安装npm install echarts-for-react
二、引入使用import React from 'react';
import ReactEcharts from 'echarts-for-react';

<ReactEcharts
option={this.getOtion()}
style={{height: '300px'}}
theme={"theme_name"}
onChartReady={this.onChartReadyCallback}
onEvents={EventsDict} />目前ReactEcharts有以下属性:
option、style、theme、className、onChartReady、showLoading、onEvents。大家可以去github上看readme文件。
 
另外API方法,只有一个getEchartsInstance()方法获取echarts的实例对象,然后就可以调用echarts的所有API方法了。





  查看全部
github项目地址:https://github.com/hustcc/echarts-for-react
DEMO地址:http://git.hust.cc/echarts-for-react/#/?_k=l9a9ca
 
使用非常简单
一、安装
npm install echarts-for-react

二、引入使用
import React from 'react';
import ReactEcharts from 'echarts-for-react';

<ReactEcharts
option={this.getOtion()}
style={{height: '300px'}}
theme={"theme_name"}
onChartReady={this.onChartReadyCallback}
onEvents={EventsDict} />
目前ReactEcharts有以下属性:
option、style、theme、className、onChartReady、showLoading、onEvents。大家可以去github上看readme文件。
 
另外API方法,只有一个getEchartsInstance()方法获取echarts的实例对象,然后就可以调用echarts的所有API方法了。

下载_(1).png

 

svn list 显示中文乱码问题的解决方法

atool 发表了文章 • 0 个评论 • 956 次浏览 • 2016-05-16 15:29 • 来自相关话题

一、背景

我们使用svn pre-commit hook做了一个svn锁定的功能,对于在上线前的svn提交进行控制,防止开发及策划胡乱提交,导致线上bug。这个平台有一个web界面功能,可以争对性给某些人开通一次提交权限,并记录他这一次的提交文件和log,乱码就出现了,web界面上显示的中文均乱码,包括log和提交文件名称

乱码的格式是:/design/X_?229?175?188?229?133?165?230?149?176?230?141?174/04_?233?129?147?229?133?183?230?149?176?230?141?174?232?161?168/?229?149?134?229?186?151?230?149?176?230?141?174?232?161?168.xls 这样的;

例如web上乱码为:






对应实际的中文汉字为:






二、原因

字符编码的问题,大家都知道,主要是ascii编码和unicode、utf-8之间的转换。关于字符编码,可以看阮一峰老师的文章,解析简单透彻:http://www.ruanyifeng.com/blog ... .html 

上述乱码基本是?229格式的,其中的?应该是svn自己加的分隔符,后面的三位数字为ascii编码,我们可以通过ascii转字符的函数将它转换成字符,将上述所有ascii字符拼接到一起即可形成unicode编码,然后再转utf-8,即可得到UrlEncode之后的中文汉字,然后再UrlDecode即可;

三、解决

知道上述原理之后,我采用js解决,这样不用修改后端代码,服务器也不用reload,调试也会方便一些;如果你才用其他语言,比如python、java、php等去解析乱码。可以找对应的函数替换即可。

3.1 urldecode和urlencode

比如:http://50vip.com/%E5%88%86%E5%B8%83%E5%BC%8F.html 这个链接里面的%E5%88%86%E5%B8%83%E5%BC%8F就是UrlEncode之后的中文,使用UrlDecode即可得到汉字“分布式”。关于这部分,网络博客很多,随便找;

Javascript方法如下:function UrlDecode(zipStr){
var uzipStr="";
for(var i=0;i<zipStr.length;i++){
var chr = zipStr.charAt(i);
if(chr == "+"){
uzipStr+=" ";
}else if(chr=="%"){
var asc = zipStr.substring(i+1,i+3);
if(parseInt("0x"+asc)>0x7f){
uzipStr+=decodeURI("%"+asc.toString()+zipStr.substring(i+3,i+9).toString());
i+=8;
}else{
uzipStr+=AsciiToString(parseInt("0x"+asc));
i+=2;
}
}else{
uzipStr+= chr;
}
}
return uzipStr;
}3.2 unicode转utf-8:EncodeUtf8

这部分代码网上找的,可能有bug,我用上没有什么问题,其他语言应该有更简单的方法:
function EncodeUtf8(s1) {
var s = escape(s1);
var sa = s.split("%");
var retV = "";
if (sa[0] != "") {
retV = sa[0];
}
for (var i = 1; i < sa.length; i++) {
if (sa[i].substring(0, 1) == "u") {
retV += Hex2Utf8(Str2Hex(sa[i].substring(1, 5)));
} else retV += "%" + sa[i];
}
return retV;
}
function Str2Hex(s) {
var c = "";
var n;
var ss = "0123456789ABCDEF";
var digS = "";
for (var i = 0; i < s.length; i++) {
c = s.charAt(i);
n = ss.indexOf(c);
digS += Dec2Dig(eval(n));
}
//return value;
return digS;
}
function Dec2Dig(n1) {
var s = "";
var n2 = 0;
for (var i = 0; i < 4; i++) {
n2 = Math.pow(2, 3 - i);
if (n1 >= n2) {
s += '1';
n1 = n1 - n2;
} else
s += '0';
}
return s;
}
function Dig2Dec(s) {
var retV = 0;
if (s.length == 4) {
for (var i = 0; i < 4; i++) {
retV += eval(s.charAt(i)) * Math.pow(2, 3 - i);
}
return retV;
}
return -1;
}
function Hex2Utf8(s) {
var retS = "";
var tempS = "";
var ss = "";
if (s.length == 16) {
tempS = "1110" + s.substring(0, 4);
tempS += "10" + s.substring(4, 10);
tempS += "10" + s.substring(10, 16);
var sss = "0123456789ABCDEF";
for (var i = 0; i < 3; i++) {
retS += "%";
ss = tempS.substring(i * 8, (eval(i) + 1) * 8);
retS += sss.charAt(Dig2Dec(ss.substring(0, 4)));
retS += sss.charAt(Dig2Dec(ss.substring(4, 8)));
}
return retS;
}
return "";
}3.3 解析SVN乱码

解析SVN格式乱码,获得每个字符的ascii,然后拼接unicode,然后转utf8,然后再UrlDecode,成功解析出汉字;
function svn_ascii_to_utf8(ori) {
s = ori.split('?');
//三个才是一个汉字,至少要有一个汉字
if (s.length < 3) {
return ori;
}
var ascii = '';
for(i in s) {
x = s[i];
if (x.length == 3) {
ascii += String.fromCharCode(x);
//console.log(ascii);
}
else if (x.length > 3) {
ascii += String.fromCharCode(x.substr(0, 3));
ascii += x.substr(3);
}
else {
//do nothing
}
}
return UrlDecode(EncodeUtf8(ascii));
}然后再web页面显示的时候,将相应的乱码,调用s = svn_ascii_to_utf8(s)即可,有乱码转乱码,无乱码保持不变;

Enjoy~ 查看全部
一、背景

我们使用svn pre-commit hook做了一个svn锁定的功能,对于在上线前的svn提交进行控制,防止开发及策划胡乱提交,导致线上bug。这个平台有一个web界面功能,可以争对性给某些人开通一次提交权限,并记录他这一次的提交文件和log,乱码就出现了,web界面上显示的中文均乱码,包括log和提交文件名称

乱码的格式是:/design/X_?229?175?188?229?133?165?230?149?176?230?141?174/04_?233?129?147?229?133?183?230?149?176?230?141?174?232?161?168/?229?149?134?229?186?151?230?149?176?230?141?174?232?161?168.xls 这样的;

例如web上乱码为:

14370127901362.png


对应实际的中文汉字为:

14370128636098.png


二、原因

字符编码的问题,大家都知道,主要是ascii编码和unicode、utf-8之间的转换。关于字符编码,可以看阮一峰老师的文章,解析简单透彻:http://www.ruanyifeng.com/blog ... .html 

上述乱码基本是?229格式的,其中的?应该是svn自己加的分隔符,后面的三位数字为ascii编码,我们可以通过ascii转字符的函数将它转换成字符,将上述所有ascii字符拼接到一起即可形成unicode编码,然后再转utf-8,即可得到UrlEncode之后的中文汉字,然后再UrlDecode即可;

三、解决

知道上述原理之后,我采用js解决,这样不用修改后端代码,服务器也不用reload,调试也会方便一些;如果你才用其他语言,比如python、java、php等去解析乱码。可以找对应的函数替换即可。

3.1 urldecode和urlencode

比如:http://50vip.com/%E5%88%86%E5%B8%83%E5%BC%8F.html 这个链接里面的%E5%88%86%E5%B8%83%E5%BC%8F就是UrlEncode之后的中文,使用UrlDecode即可得到汉字“分布式”。关于这部分,网络博客很多,随便找;

Javascript方法如下:
function UrlDecode(zipStr){  
var uzipStr="";
for(var i=0;i<zipStr.length;i++){
var chr = zipStr.charAt(i);
if(chr == "+"){
uzipStr+=" ";
}else if(chr=="%"){
var asc = zipStr.substring(i+1,i+3);
if(parseInt("0x"+asc)>0x7f){
uzipStr+=decodeURI("%"+asc.toString()+zipStr.substring(i+3,i+9).toString());
i+=8;
}else{
uzipStr+=AsciiToString(parseInt("0x"+asc));
i+=2;
}
}else{
uzipStr+= chr;
}
}
return uzipStr;
}
3.2 unicode转utf-8:EncodeUtf8

这部分代码网上找的,可能有bug,我用上没有什么问题,其他语言应该有更简单的方法:
function EncodeUtf8(s1) {
var s = escape(s1);
var sa = s.split("%");
var retV = "";
if (sa[0] != "") {
retV = sa[0];
}
for (var i = 1; i < sa.length; i++) {
if (sa[i].substring(0, 1) == "u") {
retV += Hex2Utf8(Str2Hex(sa[i].substring(1, 5)));
} else retV += "%" + sa[i];
}
return retV;
}
function Str2Hex(s) {
var c = "";
var n;
var ss = "0123456789ABCDEF";
var digS = "";
for (var i = 0; i < s.length; i++) {
c = s.charAt(i);
n = ss.indexOf(c);
digS += Dec2Dig(eval(n));
}
//return value;
return digS;
}
function Dec2Dig(n1) {
var s = "";
var n2 = 0;
for (var i = 0; i < 4; i++) {
n2 = Math.pow(2, 3 - i);
if (n1 >= n2) {
s += '1';
n1 = n1 - n2;
} else
s += '0';
}
return s;
}
function Dig2Dec(s) {
var retV = 0;
if (s.length == 4) {
for (var i = 0; i < 4; i++) {
retV += eval(s.charAt(i)) * Math.pow(2, 3 - i);
}
return retV;
}
return -1;
}
function Hex2Utf8(s) {
var retS = "";
var tempS = "";
var ss = "";
if (s.length == 16) {
tempS = "1110" + s.substring(0, 4);
tempS += "10" + s.substring(4, 10);
tempS += "10" + s.substring(10, 16);
var sss = "0123456789ABCDEF";
for (var i = 0; i < 3; i++) {
retS += "%";
ss = tempS.substring(i * 8, (eval(i) + 1) * 8);
retS += sss.charAt(Dig2Dec(ss.substring(0, 4)));
retS += sss.charAt(Dig2Dec(ss.substring(4, 8)));
}
return retS;
}
return "";
}
3.3 解析SVN乱码

解析SVN格式乱码,获得每个字符的ascii,然后拼接unicode,然后转utf8,然后再UrlDecode,成功解析出汉字;
function svn_ascii_to_utf8(ori) {
s = ori.split('?');
//三个才是一个汉字,至少要有一个汉字
if (s.length < 3) {
return ori;
}
var ascii = '';
for(i in s) {
x = s[i];
if (x.length == 3) {
ascii += String.fromCharCode(x);
//console.log(ascii);
}
else if (x.length > 3) {
ascii += String.fromCharCode(x.substr(0, 3));
ascii += x.substr(3);
}
else {
//do nothing
}
}
return UrlDecode(EncodeUtf8(ascii));
}
然后再web页面显示的时候,将相应的乱码,调用s = svn_ascii_to_utf8(s)即可,有乱码转乱码,无乱码保持不变;

Enjoy~

重写 file 控件样式

atool 发表了文章 • 0 个评论 • 347 次浏览 • 2016-04-25 09:32 • 来自相关话题

input[type="file"]{
-webkit-appearance: none;
text-align: left;
-webkit-rtl-ordering: left;
}
input[type="file"]::-webkit-file-upload-button{
-webkit-appearance: none;
float: right;
margin: 0 0 0 10px;
border: 1px solid #aaaaaa;
border-radius: 4px;
background-image: -webkit-gradient(linear, left bottom, left top, from(#d2d0d0), to(#f0f0f0));
background-image: -moz-linear-gradient(90deg, #d2d0d0 0%, #f0f0f0 100%);
} 查看全部
input[type="file"]{
-webkit-appearance: none;
text-align: left;
-webkit-rtl-ordering: left;
}
input[type="file"]::-webkit-file-upload-button{
-webkit-appearance: none;
float: right;
margin: 0 0 0 10px;
border: 1px solid #aaaaaa;
border-radius: 4px;
background-image: -webkit-gradient(linear, left bottom, left top, from(#d2d0d0), to(#f0f0f0));
background-image: -moz-linear-gradient(90deg, #d2d0d0 0%, #f0f0f0 100%);
}
1.png

css颤动效果

atool 发表了文章 • 0 个评论 • 308 次浏览 • 2016-04-25 09:30 • 来自相关话题

 .face:hover {
animation: shake 0.82s cubic-bezier(.36,.07,.19,.97) both;
transform: translate3d(0, 0, 0);
backface-visibility: hidden;
perspective: 1000px;
}

@keyframes shake {
10%, 90% {
transform: translate3d(-1px, 0, 0);
}

20%, 80% {
transform: translate3d(2px, 0, 0);
}

30%, 50%, 70% {
transform: translate3d(-4px, 0, 0);
}

40%, 60% {
transform: translate3d(4px, 0, 0);
}
} 查看全部
 
.face:hover {
animation: shake 0.82s cubic-bezier(.36,.07,.19,.97) both;
transform: translate3d(0, 0, 0);
backface-visibility: hidden;
perspective: 1000px;
}

@keyframes shake {
10%, 90% {
transform: translate3d(-1px, 0, 0);
}

20%, 80% {
transform: translate3d(2px, 0, 0);
}

30%, 50%, 70% {
transform: translate3d(-4px, 0, 0);
}

40%, 60% {
transform: translate3d(4px, 0, 0);
}
}

一个image placeholder客户端Javascript生成库

atool 发表了文章 • 0 个评论 • 513 次浏览 • 2016-04-22 16:48 • 来自相关话题

一、概述

placeholder,做过html都会知道,在input里面有一个属性是placeholder,这个属性是用到在input为空的时候,显示一个提示图片。
本项目地址为:https://github.com/hustcc/placeholder.js  




二、起因

个人在开发过程中,需要处理很多的APP logo,这些logo是从ipa和apk中dump出来的,有些可能加密无法完全解密。所以在logo打不开的时候,需要显示一个替代信息,方法有二:

1. 使用img的alt属性,当图片打不开的时候,显示alt文字;
2. 加载失败使用一个empty图片代替;

都有确定,方法1可能造成页面样式变化,因为img和text还是有差距的;方法2也有问题,所有失败的图片均使用相同的图片替代,辨识度低。

三、已有方案

这里就需要使用image的placeholder,最简答的方式,这种其实大家经常看到,比如网站的广告位预留,占位图片等等。但是要做到动态的图片,这就需要其他的一些手段了,方法有二:
1. 通过搭建一个web server,专门生成图片,然后通过传入一些参数来动态生成图片
这个比较多,也比较主流吧,例如:temp.im,placeholder.it等都是通过服务端生成,至于怎么生成,php使用gd,py使用pil等;
2. 通过浏览器客户端生成,github上有一个项目:https://github.com/imsky/holder 使用客户端生成,具体可以去github上参考。

四、本方案

本项目地址为:https://github.com/hustcc/placeholder.js   
演示网站:http://github.atool.org/placeholder.js.html   (代码使用上述imsky/holder的主页代码,修改placeholder生成方式)

为什么已经有holde项目,还要做一个placeholder.js的项目?二者做的都是客户端生成placeholder
1. holder的使用方式是参考server端生成placeholder的使用方式——使用url传递参数的方式,这种方式在浏览器端使用js并不是非常方便;
2. holder的Javascript库太大,压缩之后30kb,对于仅仅只是生成一个placeholder图片,而耗费30kb,并不划算;
3. server端生成图片比较耗费服务器资源,特别是一个页面生成图片比较多的时候,容易造成大量并发,而如果对图片来进行缓存,又会导致各种碎片文件。

本项目的特点:
1. 非常小:1kb都不到,后续更新尽量维持在1kb之类,也要有一个噱头;
2. 使用非常简单,几个简单易懂的配置项,两个api方法(一个获取base64,一个获取canvas);
3. 动态字体大小,在字体未设置的情况下,自动调整字体大小,方式文字overflow;
欢迎issue和PR。 查看全部
一、概述

placeholder,做过html都会知道,在input里面有一个属性是placeholder,这个属性是用到在input为空的时候,显示一个提示图片。
本项目地址为:https://github.com/hustcc/placeholder.js  
website.png

二、起因

个人在开发过程中,需要处理很多的APP logo,这些logo是从ipa和apk中dump出来的,有些可能加密无法完全解密。所以在logo打不开的时候,需要显示一个替代信息,方法有二:

1. 使用img的alt属性,当图片打不开的时候,显示alt文字;
2. 加载失败使用一个empty图片代替;

都有确定,方法1可能造成页面样式变化,因为img和text还是有差距的;方法2也有问题,所有失败的图片均使用相同的图片替代,辨识度低。

三、已有方案

这里就需要使用image的placeholder,最简答的方式,这种其实大家经常看到,比如网站的广告位预留,占位图片等等。但是要做到动态的图片,这就需要其他的一些手段了,方法有二:
1. 通过搭建一个web server,专门生成图片,然后通过传入一些参数来动态生成图片
这个比较多,也比较主流吧,例如:temp.im,placeholder.it等都是通过服务端生成,至于怎么生成,php使用gd,py使用pil等;
2. 通过浏览器客户端生成,github上有一个项目:https://github.com/imsky/holder 使用客户端生成,具体可以去github上参考。

四、本方案

本项目地址为:https://github.com/hustcc/placeholder.js   
演示网站:http://github.atool.org/placeholder.js.html   (代码使用上述imsky/holder的主页代码,修改placeholder生成方式)

为什么已经有holde项目,还要做一个placeholder.js的项目?二者做的都是客户端生成placeholder
1. holder的使用方式是参考server端生成placeholder的使用方式——使用url传递参数的方式,这种方式在浏览器端使用js并不是非常方便;
2. holder的Javascript库太大,压缩之后30kb,对于仅仅只是生成一个placeholder图片,而耗费30kb,并不划算;
3. server端生成图片比较耗费服务器资源,特别是一个页面生成图片比较多的时候,容易造成大量并发,而如果对图片来进行缓存,又会导致各种碎片文件。

本项目的特点:
1. 非常小:1kb都不到,后续更新尽量维持在1kb之类,也要有一个噱头;
2. 使用非常简单,几个简单易懂的配置项,两个api方法(一个获取base64,一个获取canvas);
3. 动态字体大小,在字体未设置的情况下,自动调整字体大小,方式文字overflow;
欢迎issue和PR。

PJAX的实现与应用实例

atool 发表了文章 • 0 个评论 • 1459 次浏览 • 2016-04-22 13:14 • 来自相关话题

一、前言

web发展经历了一个漫长的周期,最开始很多人认为Javascript这们语言是前端开发的累赘,是个鸡肋,那个时候人们还享受着从一个a链接蹦到另一个页面的web神奇魔术。后来随着JavaScript的不断更新换代,他的功能不仅仅是为网页添加一点特效了,语言本身的加强以及对DOM操作能力的提升让他在前端大放光彩。尤其是ajax的出现,让JavaScript以及整个web的发展翻开了崭新的一页。

利用ajax局部刷新页面,相信很多人玩得相当熟练了。如果整个页面的刷新都是使用ajax,我们可以称之为一个webapp,所有的逻辑都是在当页处理,这种形式的页面带来的体验是十分不错的,减少了那些比较“冗余”的页面跳转、新开页面等。不过,webapp的代码是十分不好维护的,页面逻辑太多太深,出点小问题,整个页面就会瘫痪,而且不方便定位bug,可维护性很低。

二、PJAX的实现与应用

1.场景再现-ajax弊端

ajax是一个非常好玩的小东西,不过用起来也会存在一些问题。

我们可以利用ajax进行无刷新改变文档内容,但是没办法去修改URL,有童鞋要问,这里为什么一定要修改URL呢?一个URL代表一个特定的网络资源,ajax修改了页面的内容,所以用不同的URL去标识他们,这个还是挺有必要的。

比如我们设计了一个单词查询的页面,比较合理的UR应该是http://example.com/word,不同的word对应不同的内容,但是如果整个页面都是ajax实现,我们就没法去修改/word了,当然我们可以使用hash如http://example.com#word,但这样就不能很好的处理浏览器的前进和后退问题。如:在页面中查询了单词A的翻译,接着又查询了单词B,这个时候浏览器的浏览历史会生成http://example.com#A和http://example.com#B两个记录,可是当我们从B转回A的时候,AJAX的效果还停留在B的状态(页面显示的还是单词B的翻译)。部分浏览器对此问题引入了onhashchange的接口,只要URL的hash值发生变化,我们的程序就可以监听并做出相应。不过对于那些木有这个接口的浏览器,就得定时去判断hash的变化了。

而这样的方式对搜索引擎是十分不友好的,twitter和google约定使用hash bang (#!xxx),也就是hash后面的第一个字符为感叹号,这样的网址他们是会爬取的,但是其他搜索引擎不支持。PJAX可以在改变页面内容的同时也改变他的URL,下面来说说PJAX和他的应用。

2.什么是PJAX

history API中有几个新特性,分别是history.pushState和history.replaceState,我们把pushState+AJAX进行封装,合起来简单点叫,就是PJAX~ 虽说实现技术上没什么新东西,但是概念上还是有所不同的。

PJAX的基本思路是,用户点击一个链接,通过ajax更新页面变化的部分,然后使用HTML5的pushState修改浏览器的URL地址,这样有效地避免了整个页面的重新加载。如果浏览器不支持history的两个新API或者JS被禁用了,那这个链接就只能跳转并重新刷新整个页面了。和传统的ajax设计稍微不同,ajax通常是从后台获取JSON数据,然后由前端解析渲染,而PJAX请求的是一个在服务器上生成好的HTML碎片,如下图所示:





客户端向服务器发送一个普通的请求(1),其实也就是点击了一个链接,服务器会相应这个请求(2),返回一个html文档。客户端向服务器发送一个有PJAX标志的请求(3),此时服务器只返回一个html碎片(4)。但是这两次请求都让客户端的URL变化了,希望上面的说明可以让你明白了PAJX和AJAX的区别了。

3.PJAX的实现

先看一个小DEMO吧,这个DEMO也写了我半个多小时,看之前先说明一下,打开你的现代浏览器(chrome,Firefox,opera,IE9+等),进入gallery页面,查看图片的时候注意观察浏览器的title和url变化,点击前进后退按钮也注意查看其变化。我已经在浏览历史管理中push了三条历史记录。

DEMO地址:http://qianduannotes.duapp.com ... .html

如果你还没有理解上面说的PJAX和AJAX的区别,看完这个demo,你应该有所领悟吧!在URL变化之后,页面并没有刷新,而是继续完成自己的动画(demo中为fadeOut)。

在HTML4,Histroy对象有下面属性方法:

length:历史堆栈中的记录数。

back():返回上一页。

forward():前进到下一页。

go([delta]):delta是个数字,如果不写或为0,则刷新本页;如果为正数,则前进到相应数目的页面;若为负数,则后退到相应数目的页面。

在HTML5中,新增了两个方法:

pushState(data, title [, url]):往历史堆栈的顶部添加一条记录。data为一个对象或null,它会在触发window的popstate事件(window.onpopstate)时,作为参数的state属性传递过去;title为页面的标题,但当前所有浏览器都忽略这个参数;url为页面的URL,不写则为当前页。

replaceState(data, title [, url]):更改当前页面的历史记录。参数同上。这种更改并不会去访问该URL。

当点击“上一张”、“下一张”这两个链接的时候,首先通过pushState修改URL以及修改document.title,那这个时候你就可以当做文档已经进入了另外一个链接了,然后该干什么干什么。demo中是让图片fadeOut,fadeOut完了之后让浏览器去加载资源,这个步骤就是正常的AJAX操作啦,没有什么特殊之处了~

因为只准备了三张图片,所有后台写的也比较简单:
<?phperror_reporting(false);$num = $_GET['num'];if(array_key_exists('HTTP_X_PJAX', $_SERVER) && $_SERVER['HTTP_X_PJAX'] === 'true'){ if($num == 1) {?>
<div class="imgwrap">
<img src="./images/1.jpg" />
</div>
<span><a href="num=2" class="next">下一张>></a></span>
<?php
} else if ($num == 2) {?>
<div class="imgwrap">
<img src="./images/2.jpg" />
</div>
<span><a href="num=1" class="previous"><<上一张</a>
<a href="num=3" class="next">下一张>></a></span>
<?php
} else {?>
<div class="imgwrap">
<img src="./images/3.jpg" />
</div>
<span><a href="num=2" class="previous"><<上一张</a></span>
<?php
}
}?>上面那张图中,我们看到了,并不是每个连接都使用PJAX来加载,如果有X_PJAX标识,我们才会添加相应的处理。js中稍加注意可以看到:
$.ajax({
"url": "./interface.php",
"data": {
"num": num
},
"dataType": "html",
"headers": {
"X_PJAX": true
}
});请求中:
Accept:text/html, */*; q=0.01
Accept-Encoding:gzip,deflate,sdch
Connection:keep-alive
Host:qianduannotes.duapp.com
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
X-Requested-With:XMLHttpRequest
X_PJAX:true我在请求的header中加了一个X_PJAX的头,而后台在处理的时候也做了判断:
function is_pjax(){
return array_key_exists('HTTP_X_PJAX', $_SERVER)
&& $_SERVER['HTTP_X_PJAX'] === 'true';
}并不是一定要求在header头部中加入X_PJAX的信息,你也可以在url中加入相关的参数,比如:http://example.com?pjax=1,或者其他方式,只要前后端达到一个共识就行。

三、开源的PJAX库

已经有人对这个东西做了封装,我就不重复造轮子了。

welefen封装的库,对jquery、qwrap和kissy都做了封装,github地址

Yahoo团队 PJAX地址

并不是页面中所有的链接都需要使用PJAX加载,所有在需要这个东西的a标签上加一个属性,如data-pjax=true,然后统一添加事件。

四、注意事项

如果浏览器不支持pushState接口函数,那就只能退化为ajax或者使用hash bang了~

本地环境下使用的话,浏览器会报错:`Uncaught SecurityError: A history state object with URL file:///E:/baidu_app/demo/PJAX/pic-2' cannot be created in a document with origin 'null'. ,所以如果你要测试的话,请把代码丢到服务器上!

为了得到更好的体验,PJAX经常配合localStorage来使用,把请求到的内容缓存到本地,再一次请求的时候先从本地查看。如果你的内容是动态变化的,缓存的时候加一个缓存时间,方便更新缓存。

还有一个容易忽略的东西是统计,使用PJAX只会局部刷新页面,如果忽略了对统计函数的更新,那就会让你失去很多数据。

五、参考资料
 
http://www.welefen.com/pjax-fo ... .html   welefen
http://ntotten.com/2012/04/09/ ... pjax/   Nathan Totten
http://yuilibrary.com/yui/docs/pjax/   YUI Pjax 查看全部
一、前言

web发展经历了一个漫长的周期,最开始很多人认为Javascript这们语言是前端开发的累赘,是个鸡肋,那个时候人们还享受着从一个a链接蹦到另一个页面的web神奇魔术。后来随着JavaScript的不断更新换代,他的功能不仅仅是为网页添加一点特效了,语言本身的加强以及对DOM操作能力的提升让他在前端大放光彩。尤其是ajax的出现,让JavaScript以及整个web的发展翻开了崭新的一页。

利用ajax局部刷新页面,相信很多人玩得相当熟练了。如果整个页面的刷新都是使用ajax,我们可以称之为一个webapp,所有的逻辑都是在当页处理,这种形式的页面带来的体验是十分不错的,减少了那些比较“冗余”的页面跳转、新开页面等。不过,webapp的代码是十分不好维护的,页面逻辑太多太深,出点小问题,整个页面就会瘫痪,而且不方便定位bug,可维护性很低。

二、PJAX的实现与应用

1.场景再现-ajax弊端

ajax是一个非常好玩的小东西,不过用起来也会存在一些问题。

我们可以利用ajax进行无刷新改变文档内容,但是没办法去修改URL,有童鞋要问,这里为什么一定要修改URL呢?一个URL代表一个特定的网络资源,ajax修改了页面的内容,所以用不同的URL去标识他们,这个还是挺有必要的。

比如我们设计了一个单词查询的页面,比较合理的UR应该是http://example.com/word,不同的word对应不同的内容,但是如果整个页面都是ajax实现,我们就没法去修改/word了,当然我们可以使用hash如http://example.com#word,但这样就不能很好的处理浏览器的前进和后退问题。如:在页面中查询了单词A的翻译,接着又查询了单词B,这个时候浏览器的浏览历史会生成http://example.com#Ahttp://example.com#B两个记录,可是当我们从B转回A的时候,AJAX的效果还停留在B的状态(页面显示的还是单词B的翻译)。部分浏览器对此问题引入了onhashchange的接口,只要URL的hash值发生变化,我们的程序就可以监听并做出相应。不过对于那些木有这个接口的浏览器,就得定时去判断hash的变化了。

而这样的方式对搜索引擎是十分不友好的,twitter和google约定使用hash bang (#!xxx),也就是hash后面的第一个字符为感叹号,这样的网址他们是会爬取的,但是其他搜索引擎不支持。PJAX可以在改变页面内容的同时也改变他的URL,下面来说说PJAX和他的应用。

2.什么是PJAX

history API中有几个新特性,分别是history.pushState和history.replaceState,我们把pushState+AJAX进行封装,合起来简单点叫,就是PJAX~ 虽说实现技术上没什么新东西,但是概念上还是有所不同的。

PJAX的基本思路是,用户点击一个链接,通过ajax更新页面变化的部分,然后使用HTML5的pushState修改浏览器的URL地址,这样有效地避免了整个页面的重新加载。如果浏览器不支持history的两个新API或者JS被禁用了,那这个链接就只能跳转并重新刷新整个页面了。和传统的ajax设计稍微不同,ajax通常是从后台获取JSON数据,然后由前端解析渲染,而PJAX请求的是一个在服务器上生成好的HTML碎片,如下图所示:
111.jpg


客户端向服务器发送一个普通的请求(1),其实也就是点击了一个链接,服务器会相应这个请求(2),返回一个html文档。客户端向服务器发送一个有PJAX标志的请求(3),此时服务器只返回一个html碎片(4)。但是这两次请求都让客户端的URL变化了,希望上面的说明可以让你明白了PAJX和AJAX的区别了。

3.PJAX的实现

先看一个小DEMO吧,这个DEMO也写了我半个多小时,看之前先说明一下,打开你的现代浏览器(chrome,Firefox,opera,IE9+等),进入gallery页面,查看图片的时候注意观察浏览器的title和url变化,点击前进后退按钮也注意查看其变化。我已经在浏览历史管理中push了三条历史记录。

DEMO地址:http://qianduannotes.duapp.com ... .html

如果你还没有理解上面说的PJAX和AJAX的区别,看完这个demo,你应该有所领悟吧!在URL变化之后,页面并没有刷新,而是继续完成自己的动画(demo中为fadeOut)。

在HTML4,Histroy对象有下面属性方法:

length:历史堆栈中的记录数。

back():返回上一页。

forward():前进到下一页。

go([delta]):delta是个数字,如果不写或为0,则刷新本页;如果为正数,则前进到相应数目的页面;若为负数,则后退到相应数目的页面。

在HTML5中,新增了两个方法:

pushState(data, title [, url]):往历史堆栈的顶部添加一条记录。data为一个对象或null,它会在触发window的popstate事件(window.onpopstate)时,作为参数的state属性传递过去;title为页面的标题,但当前所有浏览器都忽略这个参数;url为页面的URL,不写则为当前页。

replaceState(data, title [, url]):更改当前页面的历史记录。参数同上。这种更改并不会去访问该URL。

当点击“上一张”、“下一张”这两个链接的时候,首先通过pushState修改URL以及修改document.title,那这个时候你就可以当做文档已经进入了另外一个链接了,然后该干什么干什么。demo中是让图片fadeOut,fadeOut完了之后让浏览器去加载资源,这个步骤就是正常的AJAX操作啦,没有什么特殊之处了~

因为只准备了三张图片,所有后台写的也比较简单:
<?phperror_reporting(false);$num = $_GET['num'];if(array_key_exists('HTTP_X_PJAX', $_SERVER) && $_SERVER['HTTP_X_PJAX'] === 'true'){    if($num == 1) {?>
<div class="imgwrap">
<img src="./images/1.jpg" />
</div>
<span><a href="num=2" class="next">下一张>></a></span>
<?php
} else if ($num == 2) {?>
<div class="imgwrap">
<img src="./images/2.jpg" />
</div>
<span><a href="num=1" class="previous"><<上一张</a>
<a href="num=3" class="next">下一张>></a></span>
<?php
} else {?>
<div class="imgwrap">
<img src="./images/3.jpg" />
</div>
<span><a href="num=2" class="previous"><<上一张</a></span>
<?php
}
}?>
上面那张图中,我们看到了,并不是每个连接都使用PJAX来加载,如果有X_PJAX标识,我们才会添加相应的处理。js中稍加注意可以看到:
$.ajax({
"url": "./interface.php",
"data": {
"num": num
},
"dataType": "html",
"headers": {
"X_PJAX": true
}
});
请求中:
Accept:text/html, */*; q=0.01
Accept-Encoding:gzip,deflate,sdch
Connection:keep-alive
Host:qianduannotes.duapp.com
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
X-Requested-With:XMLHttpRequest
X_PJAX:true
我在请求的header中加了一个X_PJAX的头,而后台在处理的时候也做了判断:
function is_pjax(){
return array_key_exists('HTTP_X_PJAX', $_SERVER)
&& $_SERVER['HTTP_X_PJAX'] === 'true';
}
并不是一定要求在header头部中加入X_PJAX的信息,你也可以在url中加入相关的参数,比如:http://example.com?pjax=1,或者其他方式,只要前后端达到一个共识就行。

三、开源的PJAX库

已经有人对这个东西做了封装,我就不重复造轮子了。

welefen封装的库,对jquery、qwrap和kissy都做了封装,github地址

Yahoo团队 PJAX地址

并不是页面中所有的链接都需要使用PJAX加载,所有在需要这个东西的a标签上加一个属性,如data-pjax=true,然后统一添加事件。

四、注意事项

如果浏览器不支持pushState接口函数,那就只能退化为ajax或者使用hash bang了~

本地环境下使用的话,浏览器会报错:`Uncaught SecurityError: A history state object with URL file:///E:/baidu_app/demo/PJAX/pic-2' cannot be created in a document with origin 'null'. ,所以如果你要测试的话,请把代码丢到服务器上!

为了得到更好的体验,PJAX经常配合localStorage来使用,把请求到的内容缓存到本地,再一次请求的时候先从本地查看。如果你的内容是动态变化的,缓存的时候加一个缓存时间,方便更新缓存。

还有一个容易忽略的东西是统计,使用PJAX只会局部刷新页面,如果忽略了对统计函数的更新,那就会让你失去很多数据。

五、参考资料
 
http://www.welefen.com/pjax-fo ... .html   welefen
http://ntotten.com/2012/04/09/ ... pjax/   Nathan Totten
http://yuilibrary.com/yui/docs/pjax/   YUI Pjax

amcharts图表避免遮挡或重叠横坐标值斜着、竖着、间隔显示

atool 发表了文章 • 0 个评论 • 790 次浏览 • 2016-04-22 12:49 • 来自相关话题

amCharts是一个致力于图表组件开发的公司,公司地址在立陶宛首都维尔纽斯,2004年开始推出图表和地图组件。截至目前,amCharts提供了JavaScript/HTML5 Charts、Javascript/HTML5 Stock Chart、JavaScript Maps三种图表组件。amCharts图形效果炫丽,得到了广大使用者的青睐,amCharts的用户遍布全球各地,不乏Microsoft, Cisco, NASA, Motorola之类的行业巨头。

amCharts在1.x版本是基于flash实现,目前2.x版本改为Javascript/HTML5实现,显得更轻量。效果如下所示:




 
针对问题:amcharts图表避免遮挡或重叠横坐标值斜着、竖着、间隔显示,如下所示:categoryAxis.labelRotation = 90; //竖着显示
categoryAxis.labelRotation = 60; //斜着显示
categoryAxis.autoGridCount = false; //自动间隔横坐标显示另外,有时候需要在图表最上面加一个显示区间的滑动条SCROLLBARvar chartScrollbar = new AmCharts.ChartScrollbar();
chart.addChartScrollbar(chartScrollbar); 查看全部
amCharts是一个致力于图表组件开发的公司,公司地址在立陶宛首都维尔纽斯,2004年开始推出图表和地图组件。截至目前,amCharts提供了JavaScript/HTML5 Charts、Javascript/HTML5 Stock Chart、JavaScript Maps三种图表组件。amCharts图形效果炫丽,得到了广大使用者的青睐,amCharts的用户遍布全球各地,不乏Microsoft, Cisco, NASA, Motorola之类的行业巨头。

amCharts在1.x版本是基于flash实现,目前2.x版本改为Javascript/HTML5实现,显得更轻量。效果如下所示:
5351375266081.png

 
针对问题:amcharts图表避免遮挡或重叠横坐标值斜着、竖着、间隔显示,如下所示:
categoryAxis.labelRotation = 90; //竖着显示
categoryAxis.labelRotation = 60; //斜着显示
categoryAxis.autoGridCount = false; //自动间隔横坐标显示
另外,有时候需要在图表最上面加一个显示区间的滑动条SCROLLBAR
var chartScrollbar = new AmCharts.ChartScrollbar();
chart.addChartScrollbar(chartScrollbar);