>

14款基于javascript的数据可视化工具,营造高大上

- 编辑:云顶娱乐yd2221 -

14款基于javascript的数据可视化工具,营造高大上

浅谈javascript函数节流

2016/03/14 · JavaScript · 函数

初稿出处: 涂根华   

怎么着是函数节流?

     函数节流轻松的来讲便是不想让该函数在十分的短的光阴内连接被调用,譬喻大家最常见的是窗口缩放的时候,平常会实行一些其余的操作函数,举例发八个ajax央浼等等业务,那么此时窗口缩放的时候,有不小大概三番五次发八个供给,那而不是我们想要的,大概是说咱们广阔的鼠标移入移出tab切换效果,一时候三番五次且活动的高效的时候,会有闪光的成效,那时候大家就可以采纳函数节流来操作。我们都知道,DOM的操作会很成本或影响属性的,假若是说在窗口缩放的时候,为成分绑定大批量的dom操作的话,会掀起大批量的连接总计,比方在IE下,过多的DOM操作会影响浏览器品质,以致严重的动静下,会挑起浏览器崩溃的发生。那年我们就足以应用函数节流来优化代码了~

函数节流的基本原理:

     使用一个定时器,先延时该函数的实行,比如利用set汤姆eout()那些函数延迟一段时间后推行函数,若是在该时间段内还触发了任何事件,大家得以选择清除方法 clearTimeout()来解决该机械漏刻,再setTimeout()五个新的放大计时器延迟一会儿实施。

笔者们先来看三个简约的window.resize的demo例子,比方小编先定义二个大局变量count=0;当本身触发一次window.resize的时候,该全局变量count++; 我们来探视在调节台中打字与印刷出count的效率;JS代码如下:

var count = 0; window.onresize = function(){ count++; console.log(count); }

1
2
3
4
5
var count = 0;
window.onresize = function(){
    count++;
    console.log(count);
}

施行截图效果如下:

图片 1

如上resize的代码,轻巧的缩放一回就打字与印刷出累累,那并非大家想要的效果与利益,那是总结的测量检验,那若是我们换到ajax诉求的话,那么就能够缩放二次窗口会接连触发多次ajax央浼,上面咱们试着使用函数节流的操作试试一下;

函数节流的率先种方案封装如下:

function throttleFunc(method,context){ clearTimeout(method.tId); method.tId = setTimeout(function(){ method.call(context); },100); }

1
2
3
4
5
6
function throttleFunc(method,context){
     clearTimeout(method.tId);
     method.tId = setTimeout(function(){
         method.call(context);
     },100);
}

我们再来封装一下窗口缩放的demo

var count = 0; function myFunc() { count++; console.log(count); } window.onresize = function(){ throttleFunc(myFunc); } function throttleFunc(method,context){ clearTimeout(method.tId); method.tId = setTimeout(function(){ method.call(context); },100); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var count = 0;
function myFunc() {
   count++;
   console.log(count);
}
window.onresize = function(){
    throttleFunc(myFunc);
}
function throttleFunc(method,context){
     clearTimeout(method.tId);
     method.tId = setTimeout(function(){
         method.call(context);
     },100);
}

如上代码,大家再来看看效果,窗口缩放和推广功用会看出,只进行了一遍;打印了二遍。

上边的代码应用二个机械漏刻每隔100阿秒试行二回;

大家也足以利用闭包的方式对上边的函数实行再装进一下;

函数节流的第三种包装方法如下:

function throttle(fn, delay){ var timer = null; return function(){ var context = this, args = arguments; clearTimeout(timer); timer = setTimeout(function(){ fn.apply(context, args); }, delay); }; };

1
2
3
4
5
6
7
8
9
10
11
function throttle(fn, delay){
     var timer = null;
     return function(){
         var context = this,
             args = arguments;
         clearTimeout(timer);
         timer = setTimeout(function(){
             fn.apply(context, args);
         }, delay);
     };
};

地点第三种方案是行使闭包的章程形成贰个私家的效用域来存放沙漏timer,第三种方案的timer是由此传参数的样式引进的。

调用demo代码如下:

var count = 0; function myFunc() { count++; console.log(count); } var func = throttle(myFunc,100); window.onresize = function(){ func(); } function throttle(fn, delay){ var timer = null; return function(){ var context = this, args = arguments; clearTimeout(timer); timer = setTimeout(function(){ fn.apply(context, args); }, delay); }; };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var count = 0;
function myFunc() {
    count++;
    console.log(count);
}
var func = throttle(myFunc,100);
window.onresize = function(){
   func();
}        
function throttle(fn, delay){
     var timer = null;
     return function(){
         var context = this,
             args = arguments;
         clearTimeout(timer);
         timer = setTimeout(function(){
             fn.apply(context, args);
         }, delay);
     };
};

函数节流的骨干思念是:正是想让一个函数不要实行的太频仍,收缩部分过快的来节流函数,比方当大家转移窗口缩放的时候,浏览器的间距有十分大概率是16ms,那是浏览器自带的岁月间隔,我们不可能改换,而大家通过节流的方式得以试着改动一下以此区间,尽量稍微延长下那个调用时间,由此大家得以打包如下函数:

函数节流的第两种包装方法

function throttle3(fn,delay,runDelay){ var timer = null; var t_start; return function(){ var context = this, args = arguments, t_cur = new Date(); timer & clearTimeout(timer); if(!t_start) { t_start = t_cur; } if(t_cur - t_start >= runDelay) { fn.apply(context,args); t_start = t_cur; }else { timer = setTimeout(function(){ fn.apply(context,args); },delay); } } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function throttle3(fn,delay,runDelay){
      var timer = null;
      var t_start;
      return function(){
         var context = this,
             args = arguments,
             t_cur = new Date();
         timer & clearTimeout(timer);
         if(!t_start) {
             t_start = t_cur;
         }
         if(t_cur - t_start >= runDelay) {
              fn.apply(context,args);
              t_start = t_cur;
         }else {
              timer = setTimeout(function(){
                  fn.apply(context,args);
               },delay);
         }
    }
}

调用demo如下:

var count = 0; function myFunc() { count++; console.log(count); } var func = throttle3(myFunc,50,100); window.onresize = function(){ func();} function throttle3(fn,delay,runDelay){ var timer = null; var t_start; return function(){ var context = this, args = arguments, t_cur = new Date(); timer & clearTimeout(timer); if(!t_start) { t_start = t_cur; } if(t_cur - t_start >= runDelay) { fn.apply(context,args); t_start = t_cur; }else { timer = setTimeout(function(){ fn.apply(context,args); },delay); } } }

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
var count = 0;
function myFunc() {
   count++;
   console.log(count);
}
var func = throttle3(myFunc,50,100);
window.onresize = function(){
   func();}
function throttle3(fn,delay,runDelay){
      var timer = null;
      var t_start;
      return function(){
          var context = this,
              args = arguments,
              t_cur = new Date();
          timer & clearTimeout(timer);
          if(!t_start) {
              t_start = t_cur;
          }
          if(t_cur - t_start >= runDelay) {
                fn.apply(context,args);
                t_start = t_cur;
          }else {
                timer = setTimeout(function(){
                     fn.apply(context,args);
                },delay);
          }
      }
}

上边的第七个函数是包装后的函数,有八个参数,大家能够团结安装触发事件的时日距离,则代表,如上代码50ms接二连三调用函数,后多个调用会把前二个调用的守候处理掉,但每隔100ms会最少实践叁回,具体应用哪个种类艺术只要看本身的度量,不过小编个人以为第二种封装函数的艺术够大家使用的,当然据他们说第三种办法质量越来越好~

1 赞 3 收藏 评论

图片 2

14款基于javascript的数额可视化学工业具

2015/12/15 · JavaScript · 数据可视化

初稿出处: 百度EFE- Ceada   

俗话说,一图胜千言。图形化的新闻方可让大家对数据有进一步直观清晰的了然,让信息发表者越发急迅地出示自身的宗旨内容。在前端开荒中,假若贫乏适当工具,制作数据可视化图表会十分复杂。不过随着数据可视化概念逐步热销,有比较多优秀的图形开源库和塑造工具平地而起。上面,我们就拿里面前蒙受比显赫的 16个产品实行简易介绍。

特别捕获方法

小结

谈起底,用二个测量检验用例总括一下文中出现的各样去重方法:

JavaScript

var arr = [1,1,'1','1',0,0,'0','0',undefined,undefined,null,null,NaN,NaN,{},{},[],[],/a/,/a/] console.log(unique(arr));

1
2
var arr = [1,1,'1','1',0,0,'0','0',undefined,undefined,null,null,NaN,NaN,{},{},[],[],/a/,/a/]
console.log(unique(arr));

测量检验中从未概念对象的可比艺术,由此暗中认可景况下,对象不去重是正确的结果,去重是不科学的结果。

方法 结果 说明
indexOf#1 NaN被去掉
indexOf#2 NaN重复
includes 正确
双重循环#1 NaN重复
双重循环#2 NaN重复
对象#1 字符串和数字无法区分,对象、数组、正则表达式被去重
对象#2 对象、数组、正则表达式被去重
对象#3 对象、数组被去重,正则表达式被消失 JSON.stringify(/a/)结果为{},和空对象一样
Map 正确
Set 正确

最终的结尾:任何脱离场景谈工夫都以妄谈,本文也一致。去重那道题,未有正确答案,请依照气象选用切合的去重方法。

1 赞 3 收藏 评论

图片 3

1. 创办一个<canvas>成分,并得到Canvas画布渲染上下文

图片 4

< canvas>是八个双标签成分,通过width和height的值来安装画布的分寸。至于ctx(画布渲染上下文),可以知道为画布上的画笔,大家能够透过画笔在画布上随便的绘图图案。要是浏览器不援助canvas会一直展现<canvas>标签中间本身设定的文字。当然<canvas>标签中间也得以是一张当不帮衬canvas时需求替换突显的图纸。

 

2. 利用canvas的图像操作API绘制图像

绘制图像的主要API及参数表达:

图片 5

援用MDN上的一张图会比较清楚的看看种种参数的功能:

图片 6

drawImage就是把叁个image对象大概canvas上(以至是video对象上的的每一帧)钦赐地方和尺寸的图像绘制到当下的画布上。而在大家的需求中,是要把方方面面图像绘制到画布中。

图片 7

对应浏览器见到的效果:

图片 8

 

Chart.js

链接:

Chart.js 是叁个简短、面向对象,为设计和开荒者筹算的图样绘制工具库。它提供了四种基础图表类型。基于 Html5,响应式,帮忙全体今世浏览器。同一时间它不借助于任何外界工具库,本人轻量级,且协助模块化,即开荒者能够拆分 Chart.js 仅引进本身索要的一部分步入工程。在精细的身形中它同有时间帮助可互相图表。

try… catch

使用try... catch固然如此能够较好地拓宽非常捕获,不至于使得页面由于一处错误挂掉,但try ... catch抓获方式展示过于臃肿,多数代码应用try ... catch包裹,影响代码可读性。

对象和对象

在论及相比的时候,还有恐怕会境遇对象。具体来说,大概能够分成二种情况:纯对象、实例对象、其余类型的目的。

纯对象

纯对象(plain object)具体指什么并非特别明显,为压缩不必要的争持,下文中选取纯对象指代由字面量生成的、成员中不含函数和日期、正则表明式等类别的对象。

即使直接拿七个对象开展比较,不管是==还是===,不容争辩都以不等于的。不过在事实上行使时,这样的条条框框是或不是必然知足我们的供给?举个例证,大家的接纳中有七个布局项:

JavaScript

// 原来有五个属性 // var prop1 = 1; // var prop2 = 2; // 重构代码时两日性格被内置同多个目的中 var config = { prop1: 1, prop2: 2 };

1
2
3
4
5
6
7
8
// 原来有两个属性
// var prop1 = 1;
// var prop2 = 2;
// 重构代码时两个属性被放到同一个对象中
var config = {
    prop1: 1,
    prop2: 2
};

假若在一些场景下,大家需求相比较一次运营的计划项是还是不是一致。在重构前,大家独家比较三遍运维的prop1prop2就能够。而在重构后,大家恐怕必要比较config指标所代表的布局项是还是不是一律。在如此的光景下,直接用==或者===来相比对象,得到的实际不是我们希望的结果。

在那样的境况下,我们或然需求自定义一些艺术来拍卖对象的可比。常见的或是是由此JSON.stringify()对目的进行种类化之后再相比较字符串,当然这么些进度不要全盘保证,只是一个思路。

一旦您认为那个情状是杜撰的话,能够再回想一下断言库,一样是依照对象成员,决断结果是或不是和预期切合。

实例对象

实例对象主要指通过构造函数(类)生成的对象。那样的对象和纯对象同样,间接比较都是见仁见智的,但也会越过须要剖断是还是不是是同一对象的状态。日常来讲,因为这种对象有相比较复杂的内部结构(以致有局地多少在原型上),不大概直接从外表比较是或不是等于。相比较可靠的论断格局是由构造函数(类)来提供静态方法恐怕实例方法来决断是或不是等于。

JavaScript

var a = Klass(); var b = Klass(); Klass.isEqual(a, b);

1
2
3
var a = Klass();
var b = Klass();
Klass.isEqual(a, b);

其他对象

任何对象重要指数组、日期、正则表明式等那类在Object基础上派生出来的目的。那类对象各自有各自的特殊性,经常供给基于气象来组织判定方法,决定多少个对象是还是不是等于。

诸如,日期对象,可能供给通过Date.prototype.getTime()方法得到时间戳来决断是还是不是代表一致时刻。正则表明式可能供给通过toString()艺术得到到原始字面量来判定是或不是是同样的正则表明式。

技能选取

因为粒子数量众多,何况波及到图像像素处理,所以这里运用Canvas是不二增选。

 

注意,以下演示的代码只是关键代码,注重在于缓和思路。

Chartist.js

链接:

Chartist.js 是一个极其简单并且实用的 JavaScript 图表生成工具,它协助 SVG 格式,图表数据转变灵活,同时也支撑种种图纸表现方式。在工程中,Chartist.js 的 CSS 和 JavaScript 分离,因而代码不够长小,在选取时安插流程特别简约。它生成的是响应式图表,能够自行扶助分裂的浏览器尺寸和分辨率,越多的是,它也扶助自定义 SASS 架构。

跨域脚本不能够准确捕获格外

常见状态下,大家会把静态财富,如JavaScript本子放到特地的静态能源服务器,亦恐怕CDN,看以下例子:

<!DOCTYPE html> <html> <head> <title></title> </head> <body> <script type="text/javascript"> // 在index.html window.onerror = function(errorMessage, scriptUEnclaveI, lineNo, columnNo, error) { console.log('errorMessage: ' + errorMessage); // 卓殊新闻console.log('scriptUWranglerI: ' + scriptU奥迪Q5I); // 万分文件路线console.log('lineNo: ' + lineNo); // 万分行号 console.log('columnNo: ' + columnNo); // 格外列号 console.log('error: ' + error); // 相当旅馆新闻// ... // 相当上报 }; </script> <script src="./error.js"></script> </body> </html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html>
<head>
  <title></title>
</head>
<body>
  <script type="text/javascript">
    // 在index.html
    window.onerror = function(errorMessage, scriptURI, lineNo, columnNo, error) {
      console.log('errorMessage: ' + errorMessage); // 异常信息
      console.log('scriptURI: ' + scriptURI); // 异常文件路径
      console.log('lineNo: ' + lineNo); // 异常行号
      console.log('columnNo: ' + columnNo); // 异常列号
      console.log('error: ' + error); // 异常堆栈信息
      // ...
      // 异常上报
    };
 
  </script>
  <script src="./error.js"></script>
</body>
</html>

JavaScript

// error.js throw new Error('那是叁个不当');

1
2
// error.js
throw new Error('这是一个错误');

图片 9

结果展现,跨域之后window.onerror有史以来捕获不到科学的要命消息,而是统一再次来到多少个Script error

解决方案:对script标签扩大一个crossorigin=”anonymous”,何况服务器加多Access-Control-Allow-Origin14款基于javascript的数据可视化工具,营造高大上的Canvas粒子动画。。

<script src="" crossorigin="anonymous"></script>

1
<script src="http://cdn.xxx.com/index.js" crossorigin="anonymous"></script>

原始值和打包对象

看完NaN是还是不是头都大了。好了,大家来轻巧一下,看一看原始值和包裹对象这一对爱人。

借使您切磋过'a'.trim()那般的代码的话,不领会是还是不是发生过那样的疑问:'a'分明是贰个原始值(字符串),它干吗能够一贯调用.trim()方法吗?当然,非常的大概您曾经知道答案:因为JS在实行这样的代码的时候会对原始值做贰次包装,让'a'化为贰个字符串对象,然后试行那些目的的章程,试行完之后再把那些包裹对象脱掉。能够用下边包车型客车代码来掌握:

JavaScript

// 'a'.trim(); var tmp = new String('a'); tmp.trim();

1
2
3
// 'a'.trim();
var tmp = new String('a');
tmp.trim();

这段代码只是协助大家清楚的。但包装对象那一个概念在JS中却是真实存在的。

JavaScript

var a = new String('a'); var b = 'b';

1
2
var a = new String('a');
var b = 'b';

a便是一个卷入对象,它和b同等,代表贰个字符串。它们都得以采纳字符串的各样办法(比方trim()),也得以参与字符串运算(+号连接等)。

但他俩有叁个要害的界别:类型不一样!

JavaScript

typeof a; // object typeof b; // string

1
2
typeof a; // object
typeof b; // string

在做字符串相比较的时候,类型的两样会促成结果有局地竟然:

JavaScript

var a1 = 'a'; var a2 = new String('a'); var a3 = new String('a'); a1 == a2; // true a1 == a3; // true a2 == a3; // true a1 === a2; // false a1 === a3; // false a2 === a3; // false

1
2
3
4
5
6
7
8
9
var a1 = 'a';
var a2 = new String('a');
var a3 = new String('a');
a1 == a2; // true
a1 == a3; // true
a2 == a3; // true
a1 === a2; // false
a1 === a3; // false
a2 === a3; // false

千篇一律是代表字符串a的变量,在使用严刻比较时竟然不是格外的,在直觉上那是一件比较难接受的业务,在种种开销景况下,也非常轻便忽略那几个细节。

粒子动画轨迹

动画片位移的轨道,最广泛的正是单位时间内转移定位的位移值,从而实现动画效果。但要做到酷炫的效果与利益信任这种干燥固定的移动分明是丰硕的。所以位移能够借助缓动函数去实现单位时间内部管理体更换不均等的位移值,进而完结极度的机能。

Leaflet

链接:

Leaflet 是一个得以同时完美运营于桌面和平运动动端的 Javascript 可交互地图库。它使用 OpenStreetMap 的数码,并把可视化数据汇总在联合。Leaflet 库的内核库异常的小,但由丰盛的插件能够大幅拓宽其效用,通常被用来要求体现地理地点的品类。

sourceMap

日常来说在生育景况下的代码是透过webpack包裹后收缩混淆的代码,所以大家大概会碰着那样的标题,如图所示:

图片 10

我们开掘具备的报错的代码行数都在第一行了,为何吗?那是因为在生育条件下,大家的代码被压缩成了一行:

JavaScript

!function(e){var n={};function r(o){if(n[o])return n[o].exports;var t=n[o]={i:o,l:!1,exports:{}};return e[o].call(t.exports,t,t.exports,r),t.l=!0,t.exports}r.m=e,r.c=n,r.d=function(e,n,o){r.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:o})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,n){if(1&n&&(e=r(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(r.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var t in e)r.d(o,t,function(n){return e[n]}.bind(null,t));return o},r.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(n,"a",n),n},r.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},r.p="",r(r.s=0)}([function(e,n){throw window.onerror=function(e,n,r,o,t){console.log("errorMessage: "+e),console.log("scriptURI: "+n),console.log("lineNo: "+r),console.log("columnNo: "+o),console.log("error: "+t);var l={errorMessage:e||null,scriptURI:n||null,lineNo:r||null,columnNo:o||null,stack:t&&t.stack?t.stack:null};if(XMLHttpRequest){var u=new XMLHttpRequest;u.open("post","/middleware/errorMsg",!0),u.setRequestHeader("Content-Type","application/json"),u.send(JSON.stringify(l))}},new Error("那是多个谬误")}]);

1
!function(e){var n={};function r(o){if(n[o])return n[o].exports;var t=n[o]={i:o,l:!1,exports:{}};return e[o].call(t.exports,t,t.exports,r),t.l=!0,t.exports}r.m=e,r.c=n,r.d=function(e,n,o){r.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:o})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,n){if(1&n&&(e=r(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(r.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var t in e)r.d(o,t,function(n){return e[n]}.bind(null,t));return o},r.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(n,"a",n),n},r.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},r.p="",r(r.s=0)}([function(e,n){throw window.onerror=function(e,n,r,o,t){console.log("errorMessage: "+e),console.log("scriptURI: "+n),console.log("lineNo: "+r),console.log("columnNo: "+o),console.log("error: "+t);var l={errorMessage:e||null,scriptURI:n||null,lineNo:r||null,columnNo:o||null,stack:t&&t.stack?t.stack:null};if(XMLHttpRequest){var u=new XMLHttpRequest;u.open("post","/middleware/errorMsg",!0),u.setRequestHeader("Content-Type","application/json"),u.send(JSON.stringify(l))}},new Error("这是一个错误")}]);

在自个儿的支付进度中也遇到过这一个标题,笔者在付出四个效应组件库的时候,使用npm link了本身的机件库,但是出于组件库被npm link后是包装后的生育景况下的代码,全体的报错都一定到了第一行。

化解办法是开启webpacksource-map,大家使用webpack装进后的改换的一份.map的台本文件就足以让浏览器对不当地方实行追踪了。此处能够参见webpack document。

实际上就是webpack.config.js中加上一行devtool: 'source-map',如下所示,为示范的webpack.config.js

JavaScript

var path = require('path'); module.exports = { devtool: 'source-map', mode: 'development', entry: './client/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'client') } }

1
2
3
4
5
6
7
8
9
10
var path = require('path');
module.exports = {
    devtool: 'source-map',
    mode: 'development',
    entry: './client/index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'client')
    }
}

webpack包裹后转变对应的source-map,这样浏览器就能够稳定到具体错误的地方:

图片 11

开启source-map的后天不足是包容性,近来只有Chrome浏览器和Firefox浏览器才对source-map支撑。不过大家对这一类意况也是有消除办法。能够动用引入npm库来辅助source-map,能够参谋mozilla/source-map。这个npm库既可以够运行在客户端也足以运作在服务端,但是更为推荐的是在服务端使用Node.js对收到到的日志新闻时行使source-map浅析,以幸免源代码的泄漏导致危害,如下代码所示:

JavaScript

const express = require('express'); const fs = require('fs'); const router = express.Router(); const sourceMap = require('source-map'); const path = require('path'); const resolve = file => path.resolve(__dirname, file); // 定义post接口 router.get('/error/', async function(req, res) { // 获取前端传过来的报错对象 let error = JSON.parse(req.query.error); let url = error.scriptUENCOREI; // 压缩文件路径if (url) { let fileUrl = url.slice(url.indexOf('client/')) + '.map'; // map文件路线 // 深入分析sourceMap let consumer = await new sourceMap.SourceMapConsumer(fs.readFileSync(resolve('../' + fileUrl), 'utf8')); // 重返贰个promise对象 // 分析原始报错数据 let result = consumer.originalPositionFor({ line: error.lineNo, // 压缩后的行号 column: error.columnNo // 压缩后的列号 }); console.log(result); } }); module.exports = router;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const express = require('express');
const fs = require('fs');
const router = express.Router();
const sourceMap = require('source-map');
const path = require('path');
const resolve = file => path.resolve(__dirname, file);
// 定义post接口
router.get('/error/', async function(req, res) {
    // 获取前端传过来的报错对象
    let error = JSON.parse(req.query.error);
    let url = error.scriptURI; // 压缩文件路径
    if (url) {
        let fileUrl = url.slice(url.indexOf('client/')) + '.map'; // map文件路径
        // 解析sourceMap
        let consumer = await new sourceMap.SourceMapConsumer(fs.readFileSync(resolve('../' + fileUrl), 'utf8')); // 返回一个promise对象
        // 解析原始报错数据
        let result = consumer.originalPositionFor({
            line: error.lineNo, // 压缩后的行号
            column: error.columnNo // 压缩后的列号
        });
        console.log(result);
    }
});
module.exports = router;

如下图所示,大家已经能够看出,在服务端已经打响剖析出了具体错误的行号、列号,大家能够透过日记的主意进行记录,到达了前面三个非凡监察和控制的目标。

图片 12

==和===

在有个别稿子中,见到某部分数组去重的不二秘诀,在认清成分是不是等于时,使用的是==正如运算符。名闻遐迩,那个运算符在比较前会先查看成分类型,当类型不均等时会做隐式类型调换。那实际是一种非常不敬小慎微的做法。因为不可能区分在做隐匿类型转变后值一样的因素,比如0''falsenullundefined等。

再正是,还会有望出现局地只好黄种人问号的结果,举个例子:

JavaScript

[] == ![]; //true

1
[] == ![]; //true

3. 得到图像的像素新闻,并依附像素消息重新绘制出粒子效果概略图

canvas有二个叫getImageData的接口,通过该接口能够收获到画布上点名地方的全部像素的多少:

图片 13

把获得的imageData输出到调整台能够旁观,imageData满含八个属性:

图片 14

当中,width、height是读取图像像素消息完全区域的肥瘦和惊人,data是叁个Uint8ClampedArray类型的一维数组,包涵了百分百图片区域里每一个像素点的大切诺基GBA的整型数据。这里不可不要明白这么些数组所保存像素新闻的排序准绳,请看下图描述的data数组:

图片 15

每二个色值占领data数组索引的叁个任务,贰个像素有个4个值(Odyssey、G、B、A)占有数组的4个目录地点。根据数列法规能够通晓,要获取第n个岗位(n从1开端)的奥迪Q7、G、B像素音讯正是:奥迪Q3n = (n-1)*4 ,Gn = (n-1)*4+1 ,Bn = (n-1)*4+2  ,so easy~  当然,实际上海教室疑似三个回顾image.height行,image.width列像素的矩形并非独有的一行到告竣的,那一个n值在矩形中要计算下:

图片 16

鉴于二个像素是带有4个索引值(rgba)的,所以获得图像中第i行第j列的Sportage、G、B、A像素音讯就是Rij = [(j-1)*imageData.width + (i-1)]*4 ,Gij = [(j-1)*imageData.width + (i-1)]*4 + 1,Bij = [(j-1)*imageData.width + (i-1)]*4 + 2,Aij = [(j-1)*imageData.width + (i-1)]*4 + 3 。每一种像素值都得以获得了!

接下去将在把图像的粒子化概略图画出来了。那么,怎么做这一个概况图吗,大家先读取每种像素的新闻(用到上面的总计公式),假诺这么些像素的色值契合供给,就保存起来,用于绘制在画布上。其余,既然是做成粒子的功力,大家只需求把像素粒子保存一部分,突显在画布上。

具体做法是,设定每一行和每一列要出示的粒子数,分别是cols和rows,三个粒子代表八个单元格,那么每一种单元格的的宽高便是imageWidth/cols和imageHeight/rows,然后循环的剖断每一个单元格的首先个像素是不是满意像素值的尺度,假设满意了,就把那几个单元格的坐标保存到数组里,用作后续绘制图案用。

珍爱参考代码:

图片 17

用全部代码做出的demo及效果:

图片 18

由来,粒子概况图早就创设产生。

 

本文由云顶娱乐发布,转载请注明来源:14款基于javascript的数据可视化工具,营造高大上