如何用程序触发window的onscroll事件
5 Comments · Posted by admin in 前端开发877 个打酱油的来压过马路
很多延迟加载的组件监听的都是window.onscroll事件.所以如果你自己模拟滚动条的话,你需要在滚动到时候能用js触发这个事件.
如何做呢,直接上代码,不要问为什么,就是这样:
if (document.createEvent)
{
var evObj = document.createEvent("HTMLEvents")
evObj.initEvent( "scroll", true, false )
window.dispatchEvent(evObj)
}else{
document.body.click();
}
ie里面有人说用scrollTo或者scrollBy可以触发....不错,不过如果你的鼠标左键被按下或者滚轮在滚动,这种方法就失效了....为什么我也不知道.
后来发现只需要点击一下body...就能触发onscroll....注意是window的onscroll...其他元素的可能存在不同.
No tags
贝塞尔曲线的更正和一些方法
3 Comments · Posted by admin in 图形和数学489 个打酱油的来压过马路
之前写过一篇关于贝塞尔曲线的文章,写的很复杂,用矩阵算出的贝塞尔,今天在使用的时候发现是有错误的.
所以重新写了一个方法,比矩阵简单的多:
资料:http://paulbourke.net/geometry/bezier/index2.html
前提:定义一个向量类,主要用来标识点坐标,所以叫 Point:
(function(){
var p=SCD.Point;
SCD.Point=function(x,y){
this.x=x||0;
this.y=y||0;
}
SCD.Point.prototype={
/*~!Vector*/
toArray:function(){
return [this.x,this.y]
},
add:function(v){
return new SCD.Point(this.x+v.x,this.y+v.y);
},
sub:function(v){
return new SCD.Point(this.x-v.x,this.y-v.y);
},
getMod:function(){
return Math.sqrt(this.x*this.x+this.y*this.y);
},
mulNum:function(num){
return new SCD.Point(this.x*num,this.y*num);
},
getNegative:function(){
return new SCD.Point(-this.x,-this.y);
},
/**
*返回一个常数代表b在a上的投影乘以a的长度
*/
dotMul:function(v){
return this.x*v.x+this.y*v.y;
},
crossMul:function(v){
return this.x*v.y-this.y*v.x;
},
/**
*获取夹角,注意返回的是角度
*/
getAngle:function(v){
return Math.acos(this.dotMul(v)/(this.getMod()*v.getMod()))* 180/Math.PI;
},
/**
*获取夹角,返回的是弧度
*/
getRadian:function(v){
var m1=this.getMod(),m2=v.getMod();
if(m1==0||m2==0){
return 0;
}
return Math.acos(this.dotMul(v)/(m1*m2));
},
distance:function(v){
return Math.sqrt((this.x-v.x)*(this.x-v.x)+(this.y-v.y)*(this.y-v.y))
},
distance2:function(v){
return (this.x-v.x)*(this.x-v.x)+(this.y-v.y)*(this.y-v.y)
},
/**
*求某向量的法向量,返回一个单位向量,其模为1,返回的向量总是指向this向量的右边
* @return
*/
getNormal:function(){
return new SCD.Point(this.y/(Math.sqrt(this.x*this.x+this.y*this.y)),-this.x/(Math.sqrt(this.x*this.x+this.y*this.y)));
},
reflex:function(v){
var normal=v.getNormal();//先求法向量
var angle=this.getAngle(normal);//求与法线的夹角
return this.sub(normal.mulNum(2*this.dotMul(normal)));
},
mirror:function(v){
return this.reflex(v).getNegative();
},
isZero:function(){
if(this.x==0&&this.y==0) return true;else return false;
},
/**
*判断某个点是否在某个矩形区域里,如果在里面的话,并且存在第四个参数的话(true),
*就继续判断相对矩形中心点所在象限,最后返回象限,不存在第四个参数返回-1
*如果不在矩形区域里,就直接返回false
*
*@param {vector} t 矩形左上角坐标
*@param {vector} b 矩形右下角坐标
*@param {boolean} q 是否返回象限
*@return {number} 象限或者-1
*/
isIn:function(t,b,q){
var r1=this.sub(t),r2=this.sub(b)
if(r1.x>=0&&r1.y>=0&&r2.x<=0&&r2.y<=0){
if(q){
var c=t.add(b).mulNum(0.5)
return this.getQ(c)
}else{
return -1;
}
}else{
return false;
}
},
/**
*获取第一个点相对第二个点所在的象限
*
*@param {vector} pc 第二个点的坐标
*/
getQ:function(pc){
var r=this.sub(pc);
if(r.x>=0&&r.y>=0){
return 4
}else if(r.x<0 &&r.y>=0){
return 3
}else if(r.x<0&&r.y<0){
return 2
}else if(r.x>=0&&r.y<0){
return 1
}
},
toString:function(){
return this.x+":"+this.y;
}
/*END~!Vector*/
}
})();
三维贝塞尔方法:
var bezier=function(begin,c1,c2,end,t){
var p=new SCD.Point(0,0)
p.x=begin.x*(1-t)*(1-t)*(1-t)+c1.x*3*t*(1-t)*(1-t)+c2.x*3*t*t*(1-t)+end.x*t*t*t
p.y=begin.y*(1-t)*(1-t)*(1-t)+c1.y*3*t*(1-t)*(1-t)+c2.y*3*t*t*(1-t)+end.y*t*t*t
return p;
}
最后一个参数是t,大小从0到1 ,0的时候是起点,1是终点.
附上一些方法:
包括: //判断两条线段是否相交 //检测点是否在多边形内//三维贝塞尔//二维贝塞尔//打碎三维贝塞尔 //打碎二维贝塞尔
(function(){
SCD.util={
//向量叉乘
crossMul:function(v1,v2){
return v1.x*v2.y-v1.y*v2.x;
},
//判断两条线段是否相交
checkCross:function(p1,p2,p3,p4){
var v1={
x:p1.x-p3.x,
y:p1.y-p3.y
},
v2={
x:p2.x-p3.x,
y:p2.y-p3.y
},
v3={
x:p4.x-p3.x,
y:p4.y-p3.y
},
v=this.crossMul(v1,v3)*this.crossMul(v2,v3)
v1={
x:p3.x-p1.x,
y:p3.y-p1.y
}
v2={
x:p4.x-p1.x,
y:p4.y-p1.y
}
v3={
x:p2.x-p1.x,
y:p2.y-p1.y
}
return (v<=0&&this.crossMul(v1,v3)*this.crossMul(v2,v3)<=0)?true:false
},
//检测点是否在多边形内
checkPP:function(point,polygon){
var p1,p2,p3,p4
p1=point
p2={
x:-100,
y:point.y
}
var count=0
//对每条边都和射线作对比
for(var i=0;i<polygon.length-1;i++){
p3=polygon[i]
p4=polygon[i+1]
if(this.checkCross(p1,p2,p3,p4)==true){
count++
}
}
p3=polygon[polygon.length-1]
p4=polygon[0]
if(this.checkCross(p1,p2,p3,p4)==true){
count++
}
// console.log(count)
return (count%2==0)?false:true
},
// // B(u) = P0 * ( 1 - u ) 2 + P1 * 2 * u ( 1 - u ) + P2 u2
//P0 * ( 1 - u )3 + P1 * 3 * u * ( 1 - u )2 + P2 * 3 * u2 * ( 1 - u ) + P3 * u3
//三维贝塞尔
bezier:function(begin,c1,c2,end,t){
var p=new SCD.Point(0,0)
p.x=begin.x*(1-t)*(1-t)*(1-t)+c1.x*3*t*(1-t)*(1-t)+c2.x*3*t*t*(1-t)+end.x*t*t*t
p.y=begin.y*(1-t)*(1-t)*(1-t)+c1.y*3*t*(1-t)*(1-t)+c2.y*3*t*t*(1-t)+end.y*t*t*t
return p;
},
//二维贝塞尔
quadratic:function(begin,c1,end,t){
var p=new SCD.Point(0,0)
p.x=begin.x*(1-t)*(1-t)+c1.x*2*t*(1-t)+end.x*t*t
p.y=begin.y*(1-t)*(1-t)+c1.y*2*t*(1-t)+end.y*t*t
return p;
},
//打碎三维贝塞尔
brokenBezier:function(begin,c1,c2,end,partCount){
var partCount=partCount||10;
var points=[]
var t=0;
for(var t=0;t<=1;t+=1/partCount){
points.push(this.bezier(begin,c1,c2,end,t));
}
return points;
},
//打碎二维贝塞尔
brokenQuadratic:function(begin,c1,end,partCount){
var partCount=partCount||10;
var points=[]
var t=0;
for(var t=0;t<=1;t+=1/partCount){
points.push(this.quadratic(begin,c1,end,t));
}
return points;
}
}
})();
No tags
如何判断点是否点在贝塞尔曲线上以及如何将贝赛尔曲线打碎成折线
No comments · Posted by admin in 图形和数学399 个打酱油的来压过马路
判断点是否在贝塞尔曲线上的方法就是:
把贝塞尔曲线打碎成一个小段一小段的折线,然后去判断每一段折线有没有和点重合.
问题变成如何打碎贝塞尔曲线.
如果你看过我之前一篇文章的话,现在就知道这是多么有用了:
文章见:http://www.html-js.com/?p=1031# (用js计算三次贝塞尔曲线);
利用文中的方式,可以按需计算贝塞尔曲线.只需要调整时间t的增益就行.
看demo:
http://www.html-js.com/mj/pj/v2/test/testbezierBroken.html
调整滑块的值即可改变打碎程度(非ie下浏览)
No tags
判断点在圆弧上(顺时针画)
No comments · Posted by admin in 图形和数学411 个打酱油的来压过马路
点为p.
圆弧圆心c0.半径r.起始弧度 a1,中止弧度 a2
先计算Math.abs(p.distance(c0)-r)
计算p到c0的弧度 a0
此时如果a1不在第一和第二象限(很容易根据弧度得到),那么就把它逆时针旋转到0,a2和a0跟着旋转同样的角度. 我感觉这已经是一个比较简单的方法..
No tags
如果a0和a2有超出2PI的,就减去2PI,例如a0=3PI,那就让它等于PI,总之将所有的弧度控制在0-2PI.
判断a0是不是>0&&
保持a2和a0在0-2PI内
判断a0是不是>0&&
如何判断点在线段上(保留可变浮动范围)
No comments · Posted by admin in 图形和数学318 个打酱油的来压过马路
线段又两个点 c0,c1表示,点用p表示. 0.1自己可以调节
No tags
直接计算p.distance(c0)+p.distance(c1)
OAuth2.0的refresh token
2 Comments · Posted by admin in 前端开发, 微博应用制作1,186 个打酱油的来压过马路
最近看人人网的OAuth认证,发现他是OAuth2.0,之前一直看的是新浪的OAuth,是OAuth1.0.
二者还是有很多不同的,主要的不同点在access token的获取方式.
OAuth1.0的access token获取过来之后,就可以存到数据库里,然后长期使用,因为它有效期很长,通常有效期是无限的.
但是OAuth2.0为了增强安全性,access token的有效期被大大缩短,通常只有几个小时,也可以申请增加到几十天,但是总是会有过期的时候.
为此,OAuth2.0增加了一个refresh token的概念,这个token并不能用于请求api.它是用来在access token过期后刷新access token的一个标记.
这里所描述的场景,通常是指那种长周期的应用.也就是需要一直保持用户在线的应用.
在线并不是说用户一直在用这个应用,也可能是用户已经离开,我们在后台仍然可以自动维持用户的状态.例如一个自动发状态的应用.用户并不需要操作这个应用,我们会定时在后台利用用户的accesskey帮助用户发送状态.这也算是用户维持登录状态的一种.
登录状态的维持,在OAuth中靠的是access token,只要我们的应用定时从数据库里取出用户的access token,然后利用access token就可以使用这个用户的身份去请求api了.
在OAuth1.0中用户的登录状态是一直存在的.
在OAuth2.0中用户的登录状态需要通过不断刷新来维持.
例如上面提到的应用.假设更详细的场景,这个应用在用户授权之后,每天给用户的人人网发送一条状态报告当天的日期.
用户授权之后,获取到一个access token和一个refresh token,还有一个是session key,这个是国内大多数开放平台自己添加的一个标记,可以让用户使用http来调用api,如果没有它,用户只能通过https来调用api.session key的生命周期和access token是相同的.
我们把这三个值存到一个队列的数据库中.
然后,在每天的10点,我们遍历这个数据库表,取出它的access token和session key,然后用他们去请求api,如果发现他们已经过期,我们就需要利用refresh token去重新刷新,获取新的access token和session key.然后利用他们去请求api,如果请求的时候提示refresh token也已经过期,那么这时候用户的登录状态就会过期,这说明这个用户至少2各月没有在此应用活跃了,这个活跃不光指用户自己在使用应用,也包括应用自动调用用户api的行为.
每次刷新token的时候都会返回一个新的refresh token,所以说如果你的应用每个月帮用户发一条状态的话,走上面的流程,一直下去,这个用户的登录状态一直都不会过期,至于为什么,自己去琢磨哦,琢磨透了也就理解了.
No tags
这几天做一个bannermaker.遇到不少问题.总结一下吧:
先试用一下….可能会有问题…有问题及时反馈哦,亲
后台版bannermaker: http://www.html-js.com/bannerMaker-tmall/index.php
HTML5版bannermaker: http://www.html-js.com/bannerMaker-tmall/index_1.php
两个版本的bannermaker,主要是一开始用php处理图片的,后来发现php在图片上写字只能用一种字体,宋体的英文很丑,这个方案直接废掉了.
第二个版本是用html5的canvas来处理图像的,最后传给服务器,用php压缩成png-8,然后输出到浏览器让用户下载.
几个点:
1. 经试验,demo的php环境支持GD库,也支持读写文件系统,但是很可惜不支持使用ttf字体来作图.
2. 用php画宋体的粗体没有普遍方法,可以先画一次,然后右移一个像素再画一次,最后出来的就是粗体.
3. 用php生成png-8的方法:
ImageTrueColorToPalette($image, false, 255);
4. 使用GD库的时候会有乱码,网上的解决方案大部分不起作用,有这样一个方法,用此方法转换后的utf-8字符就可以作为ImageTTFText的参数使用了:
function to_entities($string) {
$len = strlen($string);
$buf = "";
for ($i = 0; $i < $len; $i++) {
if (ord($string[$i]) <= 127) {
$buf .= $string[$i];
} else if (ord($string[$i]) < 192) {
//unexpected 2nd, 3rd or 4th byte
$buf .= "�";
} else if (ord($string[$i]) < 224) {
//first byte of 2-byte seq
$buf .= sprintf("&#%d;",
((ord($string[$i + 0]) & 31) << 6) +
(ord($string[$i + 1]) & 63)
);
$i += 1;
} else if (ord($string[$i]) < 240) {
//first byte of 3-byte seq
$buf .= sprintf("&#%d;",
((ord($string[$i + 0]) & 15) << 12) +
((ord($string[$i + 1]) & 63) << 6) +
(ord($string[$i + 2]) & 63)
);
$i += 2;
} else {
//first byte of 4-byte seq
$buf .= sprintf("&#%d;",
((ord($string[$i + 0]) & 7) << 18) +
((ord($string[$i + 1]) & 63) << 12) +
((ord($string[$i + 2]) & 63) << 6) +
(ord($string[$i + 3]) & 63)
);
$i += 3;
}
}
return $buf;
}
ImageTTFText($tim, 10.2, 0, 10, 123, $white, "simsun.ttf", to_entities($_POST['title']));
5. 用pathinfo可以方便获取文件名信息: http://www.w3school.com.cn/php/func_filesystem_pathinfo.asp
6. 自动调用浏览器的下载下载文件:
$filepath = "temp/" . time() . md5($src) . ".png";
imagepng($tim, $filepath);
header("Content-type:image/png");
header("Content-Disposition: attachment; filename=$filepath");
header('Content-Length: ' . filesize($filepath));
$fp = fopen($filepath, 'rb');
fpassthru($fp);
fclose($fp);
7. 怎么用html5处理图片然后传给后台继续处理?
用html5的canvas处理图片,然后用canvas的toDataURL() [ 文档 ] 方法将canvas的内容变成一张图片,形式是dataurl的字符串,然后post到后台,后台吧dataurl当成普通url处理即可获取到图片资源:
$im = imagecreatefrompng($src);//$src就是一个dataurl
等等等等….
No tags
将dom结构缓存到本地存储里有没有必要和意义?
2 Comments · Posted by admin in 前端开发605 个打酱油的来压过马路
将dom结构缓存到本地存储里有没有必要和意义?
是一个静态页面,内容变化不是很频繁,页面分成N个独立模块,每个模块由不同的人维护.
将这些内容缓存到本地存储,然后利用时间戳机制,只有时间戳过期的时候才会去服务器更新.
所有的模块的更新只使用一个http请求,也就是说只会比平常多出一个http请求并不是每个模块独立去更新.
之所以开始怀疑这样做的意义.
因为:
1.前提是你的网站不需要考虑搜索引擎,例如淘宝网.
2.会多出1-几个请求...你可以将请求控制在1个之内,影响不是很大.
3.因为只使用一个请求,得到内容后,需要正则匹配将内容分解到每个模块中,可能会耗费一些浏览器性能,经过测试不会出现明显的性能问题.
4.维护和配置麻烦...学习成本高.....
5.浏览器本身就有缓存,包括对整个页面的缓存.只是这样做,刷新的时候也不会去服务器获取内容.
大家怎么认为呢,希望共同探讨下
No tags
接上一篇:稍微改进下算法生成大色盘
3 Comments · Posted by admin in html5和canvas研究, 前端开发, 图形和数学729 个打酱油的来压过马路
之前文章中生成的小色盘,有白色斑点,因为算法原因,没有顾及每个像素.这个算法是由模型推导像素点的,所以有瑕疵.改进一下即可,我们由像素点推导模型:
for(var y=0;y<400;y++){
for(var x=0;x<400;x++){
var r=Math.sqrt((x-200)*(x-200)+(y-200)*(y-200))
if(r<200){
var angle=(Math.atan2((200-y),(200-x)))*180/Math.PI
angle<0&&(angle+=360);
pixel=HSVToRGB(angle,r/200,0.8)
setData(imageData2,x,y,[
pixel.r,
pixel.g,
pixel.b,
255
]);
}
}
}
点击颜色,页面背景色将会变化
No tags

