用于在浏览器中下载文件,特性是支持断点续传(符合CORS规则时)、阻塞重连和失败重试,使用fetch流作为下载方式。
NPM: https://www.npmjs.com/package/@luojia/browser-filedownloader
GitHub: https://github.com/JiaJiaJiang/browser-FileDownloader
用于在浏览器中下载文件,特性是支持断点续传(符合CORS规则时)、阻塞重连和失败重试,使用fetch流作为下载方式。
NPM: https://www.npmjs.com/package/@luojia/browser-filedownloader
GitHub: https://github.com/JiaJiaJiang/browser-FileDownloader
用于在页面上通过js附加样式表文本
此博文由一个话题引出,原话题是通过滑条控制页面上显示3D模型的某个部分,于是我就来尝试了一下。
由于Three.js我也已经2年没碰了,而且在项目里只用过一次,所以并不是很清楚它是否能通过本身的功能达到这个效果,甚至一开始我已经在想手搓点坐标来达到目标了。
但手搓点坐标实在太麻烦了一点,我就回到blender想看看通常用于控制形变的形态键是否可以导出来使用,然后发现确实可以,这样就方便了,只要控制形态键的数值就可以对模型的形态进行定量控制,以下是操作过程: 继续阅读[WebGL]使用javascript控制模型形变
碰到一个需要给图表上数据打颜色的场景,我希望对于同一个名字的数据每次出来的颜色都是一样的,于是想了半分钟,搞出了这么个方案
function strToRGB(name){ let sum=0; for(let s of name)sum+=s.codePointAt(0); return [sum%128,sum%126,sum%124]; }
原理是把每一个字符的unicode值累加起来,然后对这个和分别取3个余数。
除数选1到256都可以,选多少取决于希望结果出现在哪个范围,我这里为了让结果颜色偏暗,所以选了128左右的除数。
为了完成java的作业,先拿js写了一个。暂时只完成了一些简单的运算
由于coding gists即将关闭,所以把此代码片搬到博客
js的Number支持直接使用toString转换到最多36进制(0-9a-z),而此函数支持转换到由传入进制表定义的任何进制。
默认进制表为0-9a-zA-Z的62进制
/* COPYRIGHT luojia@luojia.me MIT LICENSE */ function conv(n,o,t,olist,tlist){//数,原进制,目标进制[,原数所用字符表,目标字符表] var dlist='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', tnum=[],m,negative=((n+='').trim()[0]=='-'),decnum=0; olist||(olist=dlist); tlist||(tlist=dlist); if(negative)n=n.slice(1); for(var i=n.length;i--;) decnum+=olist.indexOf(n[i])*Math.pow(o,n.length-i-1); for(;decnum!=0;tnum.unshift(tlist[m])){ m=decnum%t; decnum=Math.floor(decnum/t); } decnum&&tnum.unshift(tlist[decnum]); if(tnum.length===0)tnum.unshift(tlist[0]); return (negative?'-':'')+tnum.join(''); } conv(1234,10,2) //"10011010010" conv(15,10,16) //"f" conv('ABC',16,10) //"9846" conv(3245670,10,10,null,'零一二三四五六七八九') //"三二四五六七零" conv('①②③',10,2,'〇①②③④⑤⑥⑦⑧⑨') //"1111011"
翻了翻message事件的属性,没找到可以直接获取事件源iframe的属性,想想也没毛病,毕竟事件也可以是其它窗口post过来的。于是想了个曲线方法。
先让发送源获取焦点,然后获取焦点元素。
window.addEventListener('message',function(msg){ //做一些事来判断是不是某个iframe发送的消息 msg.source.focus(); var sourceFrame=document.activeElement; });
如果不想影响焦点的话,可以遍历一遍所有的iframe
function findIframe(win){ var fs=document.querySelectorAll('iframe'); for(var is=fs.length;is--;){ if(fs[is].contentWindow==win) return fs[is]; } } window.addEventListener('message',function(msg){ var iframe=findIframe(msg.source);//获取消息源 });
把特定格式的js对象转换成HTML元素
https://github.com/JiaJiaJiang/Object2HTML
{_:'div', child:[ {_:'button',prop:{innerHTML:'poi'},event:{'click':function(){alert('niconiconi');}}}, {_:'br'}, {_:'video',prop:{src:'http://www.w3school.com.cn/example/html5/mov_bbb.mp4'},attr:{controls:true}} ] }
写了段代码可以用来识别用户的操作方式是否为触摸。
首先需要给元素加一个便于批量添加事件的on方法(我自认为这么写没什么毛病
(function(){ function Extent_On_Event(){ if(arguments[0] instanceof Array){ var arg=arguments,es=arguments[0]; es.forEach(function(e){ arg[0]=e; this.addEventListener.apply(this,arg); }); }else{ this.addEventListener.apply(this,arguments); } return this; }; (window.EventTarget||window.Node).prototype.on=Extent_On_Event; if(!window.on)Window.prototype.on=Extent_On_Event; })();
然后定义判断触摸模式的代码
//touchMode (function(){ var isTouchMode=window.touchMode=('ontouchstart' in window); var mouseEventRec=0; function touchModeEvent(node){ node.on(['touchstart','touchend','touchmove'],function(){ mouseEventRec&&(mouseEventRec=0); if(isTouchMode)return; isTouchMode=window.touchMode=true; var e=new Event('touchModeChange'); e.touchMode=isTouchMode; window.dispatchEvent(e); }); node.on('mousemove',function(){ if(!isTouchMode)return; mouseEventRec++; if(mouseEventRec>4){ isTouchMode=window.touchMode=false; var e=new Event('touchModeChange'); e.touchMode=isTouchMode; window.dispatchEvent(e); }; }); } touchModeEvent(window); })();
这段代码的作用
在支持触摸的设备上,touchMode默认为true,移动鼠标后会转变为false。我认为这个地方是有点毛病的,但是不知道如何正确判断初始状态。
对于阻止以上代码中事件冒泡到window的元素,需要额外执行相关的监听代码以保证正确性。
用来把页面上播放的HTML5视频变速,以节省看番时间或者达到慢放暂停看福利的效果。
javascript:var v=document.querySelector('video'),s=prompt('倍度',v.playbackRate);v.playbackRate=Number(s);
保存成书签在视频页点击即可。
我按照http://ucren.com/blog/archives/549 的思路把字符串转换成零宽字符穿,但是不限代码,可以用来转换任意字符串
项目地址:https://github.com/JiaJiaJiang/stringHider
在线工具:https://jiajiajiang.github.io/stringHider/
============2018/10/14更新===========
修复了无法转换ascii码表以外字符的bug
便于发车的小工具
地址:https://github.com/JiaJiaJiang/toDataURI
选择文本或者文件模式,填好内容或者选择文件
可自定义Content type,一般空着就好
然后点转换。
即可发车。
转换结果让别人粘贴在浏览器地址栏即可。
Demo:http://pages.luojia.me/image-diff/
用于对两张图片进行像素对比,相同的像素结果为白色,不同的像素结果为黑色。
做这个东西是因为某群在讨论QQ的火炬传递页面到底有没有藏什么东西,为了证明它们真的是一模一样的图片,我就做了这东西。。。
用javascript写了个base32的编解码函数
const charTable=[ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '=' ],allowedPeddingCount=[6,4,3,1,0]; function str_split(str,length){ if(typeof str !== 'string')return []; let a=[],i=0; length||(length=1); do{ a.push(str.substr(i,length)); i+=length; }while(i<str.length); return a; } const Base32={ encode:function(str,padding){ if(!str)return ''; let binaryString=''; for (let i = 0;i<str.length;i++) { let bin=str.charCodeAt(i).toString(2); binaryString+=('0'.repeat(8-bin.length)+bin); } let fiveBitBinaryArray=str_split(binaryString,5),base32=''; for(let i=0;i<fiveBitBinaryArray.length;i++){ let bin=fiveBitBinaryArray[i]; base32+=charTable[parseInt(bin+'0'.repeat(5-bin.length),2)]; } let x=binaryString.length%40; if (padding && x != 0) { if (x == 8)base32+=charTable[32].repeat(6); else if(x===16)base32+=charTable[32].repeat(4); else if(x===24)base32+=charTable[32].repeat(3); else if(x===32)base32+=charTable[32]; } return base32; }, decode:function(str){ if(!str)return ''; let paddingMatch=str.match(/\=+$/), paddingCharCount=paddingMatch?paddingMatch[0].length:0; if(allowedPeddingCount.indexOf(paddingCharCount)<0)return false; for (let i=0;i<4;i++){ if (paddingCharCount===allowedPeddingCount[i] && str.substr(-(allowedPeddingCount[i]))!=charTable[32].repeat(allowedPeddingCount[i])) return false; } str=str.replace(/\=+$/,''); let binaryString = ""; for (let i=0;i<str.length;i+=8) { let x=''; if (charTable.indexOf(str[i])<0)return false; for (let j=0;j<8;j++) { let bin=charTable.indexOf(str[i+j]).toString(2); x+='0'.repeat(5-bin.length)+bin; } let eightBits=str_split(x,8); for (let z = 0; z < eightBits.length; z++) { let y,cd=parseInt(eightBits[z],2,10); binaryString+=((y=String.fromCharCode(cd))||cd==48)?y:""; } } return binaryString; } }
用一个看起来似乎有点不恰当的办法,用Error对象
(new Error).stack
获取到的是字符串形式的调用栈。
不知道还有没有其它办法来获得调用栈。
由于解决这个问题花了我一些时间,所以记录一下说不定可以帮到其他人。
process.stdout是一个getter,所以我们不能用普通的替换来换掉process.stdout来拦截写入它的数据。同时,process.stdout是一个Writable Stream,所以也不能简单地直接从它里面获取写入的数据。
一开始我花了不少时间来研究怎么可以从这个Writable Stream里读出数据,但是这似乎太麻烦了,然后我甚至想到了利用child process来拦截数据。最后发现其实很简单,我们只要重新定义这个Getter就可以了。
var stream=require('stream'); var rawStdout=process.stdout,//先拿到原来的stdout newStdout=new stream.PassThrough();//创建一个passthrough流,这是一种特殊的Transform流,会直接把写入的数据吐出来 process.__defineGetter__('stdout',function(){//重新定义process.stdout的Getter return newStdout;//返回我们的passthrough流 });
这样我们就成功拦截到标准输出了,要注意,这段代码必须放在有任何输出之前,一旦在之前有了内容输出,它就没用了。
然后我们就可以自己决定怎么处理stdout了比如:
newStdout.pipe(rawStdout);//内容输出到控制台 newStdout.pipe(文件的writable stream);//内容写入文件 newStdout.pipe(其它可写流);//随你怎么处理
同理,process.stderr也可以这样拦截