用500行纯前端代码在浏览器中营造贰个Tableau,基于jquery自定义图片热区效果

用500行纯前端代码在浏览器中塑造三个Tableau

2018/05/16 · 幼功技术 ·
BI,
Tableau,
数码可视化

初藳出处: naughty   

在Gartner最新的对商务智能软件的标准解析报告中,Tableau持续领跑。Microsoft因为PowerBI展现卓越也处于领导者象限。而未来的领导职员像SAP,SAS,IBM,MicroStrategy等稳步被延长了间隔。

图片 1

Tableau因为其手疾眼快,优越的数额表现已经化为BI领域里的确的带头羊。而其数据驱动的可视化和焦点情想是源于于Leland
Wilkinson的The
Grammar Of
Graphics ,
相符受到该酌量潜濡默化的还应该有悍马H2的图形库ggplot。

图片 2

在数量可视化开源领域里,咱们对百度支付的echarts可谓耳闻则诵,echarts经过长此现在的开垦进取,其效果实在非常苍劲,可用非凡来形容。不过蚂蚁金服开源的基于The
Grammar Of
Graphics
的语法驱动的可视化库G2,令人日前生龙活虎亮。那大家就看看怎么样行使G2和500行左右的纯前端代码来促成一个的好像Tableau的多寡拆解剖判功效。

  • 亲自过问参见 
  • 代码参见 https://gist.github.com/gangtao/e053cf9722b64ef8544afa371c2daaee 

 

当今照管下发出来,希望大家一块学习呢

数码加载

先是步是加载数据:

图片 3

数码加载首要运用了多少个库:

  • axios  基于Promise的HTTP客户端
  • alasql 基于JS的开源SQL数据库
  • jquery datatable JQuery的数量表格插件

多少通过自己贮存在GitHub中的csv格式的文书,以REST央求的措施来加载。上面包车型客车代码把Axios的Promise形成async/wait情势。

// Ajax async request const request = { get: url => { return new
Promise((resolve, reject) => { axios .get(url) .then(response => {
resolve({ data: response.data }); }) .catch(error => { resolve({
data: error }); }); }); } };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Ajax async request
const request = {
  get: url => {
    return new Promise((resolve, reject) => {
      axios
        .get(url)
        .then(response => {
          resolve({ data: response.data });
        })
        .catch(error => {
          resolve({ data: error });
        });
    });
  }
};

包装好后,大家就能够用request.get()方法发送REST央浼,获取csv文件。

let csv = await request.get(url);

1
let csv = await request.get(url);

这一步或然会境遇跨域央浼的主题素材,github上的公文扶助跨域。

把多少存款和储蓄在三个SQL数据库中,那样做的功利是为着下一步做多少希图的时候,能够方便的运用SQL来开展查询和解析。

JavaScript

class SqlTable { constructor(data) { this.data = data; } async
query(sql) { // following line of code does not run in full page view
due to security concern. // const query_str =
sql.replace(/(?<=FROMs+)w+/, “CSV(?)”); const query_str =
sql.replace(“table”, “CSV(?)”); return await alasql.promise(query_str,
[this.data]); } }

1
2
3
4
5
6
7
8
9
10
11
12
class SqlTable {
  constructor(data) {
    this.data = data;
  }
 
  async query(sql) {
    // following line of code does not run in full page view due to security concern.
    // const query_str = sql.replace(/(?<=FROMs+)w+/, "CSV(?)");
    const query_str = sql.replace("table", "CSV(?)");
    return await alasql.promise(query_str, [this.data]);
  }
}

SqlTable是一个对数据表的卷入,把csv数据存在SQL数据库表中,提供二个query(卡塔 尔(英语:State of Qatar)方法。这里要做的是把SQL查询个从 “SELECT
* FROM table” 变成 “SELECT * FROM CSV(?)”
表示查询参数是CSV数据。因为codepen的安全性约束,运营前向寻觅的replace语句(这里的regex表示把前边是“FROM
”词的替换为CSV(?)的卡塔尔国在full page
view下是无法实施的,所以笔者用了贰个更简便的只要,客商的表名正是table,那样做有好些个标题,我们只要在codepen之外的条件,能够用注释掉的代码。

然后把”SELECT * FROM table”的查询结果(JSON Array卡塔尔用datatable来展现。

function sanitizeData(jsonArray) { let newKey;
jsonArray.forEach(function(item) { for (key in item) { newKey =
key.replace(/s/g, “”).replace(/./g, “”); if (key != newKey) {
item[newKey] = item[key]; delete item[key]; } } }); return
jsonArray; } function displayData(tableId, data) { // tricky to clone
array let display_data = JSON.parse(JSON.stringify(data));
display_data = sanitizeData(display_data); let columns = []; for
(let item in display_data[0]) { columns.push({ data: item, title:
item }); } $(“#” + tableId).DataTable({ data: display_data, columns:
columns, destroy: true }); }

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
function sanitizeData(jsonArray) {
  let newKey;
  jsonArray.forEach(function(item) {
    for (key in item) {
      newKey = key.replace(/s/g, "").replace(/./g, "");
      if (key != newKey) {
        item[newKey] = item[key];
        delete item[key];
      }
    }
  });
  return jsonArray;
}
 
function displayData(tableId, data) {
  // tricky to clone array
  let display_data = JSON.parse(JSON.stringify(data));
  display_data = sanitizeData(display_data);
  let columns = [];
  for (let item in display_data[0]) {
    columns.push({ data: item, title: item });
  }
  $("#" + tableId).DataTable({
    data: display_data,
    columns: columns,
    destroy: true
  });
}

这一步有两点要注意:

  1. 数码中,若是列的名字中有隐含点,空格等字符,譬喻Iris数据汇总的Sepal.Length,datatable是爱莫能助平常展现的,这里要调用sanitizeData(卡塔 尔(阿拉伯语:قطر‎方法把列名,也正是JsonArray中Json对象的属性名中的点和空格去掉。
  2. sanitizeData(卡塔 尔(阿拉伯语:قطر‎方法会改变输入对象,所以在传出以前做了一个深度拷贝,这里运用JSON的stringfy和parse方法能够对JSON宽容的靶子有效的正片。

这里要注意,Iris数据聚集在datatable中的列名都不呈现点,但骨子里数据并从未更换。

 

先看效果图:
图片 4
用了jquery.image-maps.js那个插件 下载地址
//www.jb51.net/jiaoben/57930.html
原理是:
由此拖动总结出脚下热区可活动模块的left top right bottom
对应area的 coords 属性集成上边包车型大巴任务,就足以兑现热区了。
相应的模块代码是:

数量计划

数据加载完毕,我们赶到第二步的数目策画阶段。数据打算是数据科学项目最花时间的一步,日常需求对数码开展大气的保洁,变形,抽取等工作,使得数据变得可用。

在此一步大家做了两件事:

一是显示数据的二个摘要,让大家开始明白多少的概略,为更加的数据变形和管理做好筹算。

这些是Iris数据集的摘要:

图片 5

function isString(o) { return typeof o == “string” || (typeof o ==
“object” && o.constructor === String); } function summaryData(data) {
let summary = {}; summary.count = data.length; summary.fields = [];
for (let p in data[0]) { let field = {}; field.name = p; if (
isString(data[0][p]) ) { field.type = “string”; } else { field.type
= “number”; } summary.fields.push(field); } for (let f of
summary.fields) { if ( f.type == “number” ) { f.max = d3.max(data, x
=> x[f.name]); f.min = d3.min(data, x => x[f.name]); f.mean =
d3.mean(data, x => x[f.name]); f.median = d3.median(data, x =>
x[f.name]); f.deviation = d3.deviation(data, x => x[f.name]); }
else { f.values = Array.from(new Set(data.map(x => x[f.name]))); }
} return summary; }

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
function isString(o) {
    return typeof o == "string" || (typeof o == "object" && o.constructor === String);
}
 
function summaryData(data) {
  let summary = {};
  summary.count = data.length;
  summary.fields = [];
  for (let p in data[0]) {
    let field = {};
    field.name = p;
    if ( isString(data[0][p]) ) {
      field.type = "string";
    } else {
      field.type = "number";
    }
    summary.fields.push(field);
  }
  
  for (let f of summary.fields) {
      if ( f.type == "number" ) {
        f.max = d3.max(data, x => x[f.name]);
        f.min = d3.min(data, x => x[f.name]);
        f.mean = d3.mean(data, x => x[f.name]);
        f.median = d3.median(data, x => x[f.name]);
        f.deviation = d3.deviation(data, x => x[f.name]);
      } else {
        f.values = Array.from(new Set(data.map(x => x[f.name])));
      }
  }
  return summary;
}

此处大家接纳数据的档期的顺序剖断出每四个字段是数值型依然字符型。对于字符型的字段,咱们应用JS6的Set来赢得全部的Unique数据。对于数值型,大家利用d3的max,min,mean,median,deviation方法总结出相应的最大值,最小值,平均数,中位数和不是。

另叁个正是选拔SQL查询来对数码开展更为的加工。

图片 6

上航海用教室的事例中大家使用节制标准获得叁个Iris数据的子集。

别的G2还提供了Dataset的功能:

  • 源数据的深入分析,将csv, dsv,geojson
    转成标准的JSON,查看Connector
  • 加工数据,蕴含 filter,map,fold(补多少)
    等操作,查看 Transform
  • 总计函数,汇总计算、百分比、封箱
    等总结函数,查看 Transform
  • 分外数据管理,包涵 地理数据、矩形树图、桑基图、文字云
    的多寡管理,查看 Transform

数码管理是二个异常的大的话题,大家的对象是运用尽可能少的代码完成叁个数码分析的工具,所以这一步仅仅是采用alasql提供的SQL查询来拍卖数据。

 

复制代码 代码如下:

数量突显

多少管理好后便是大家的核心内容,数据显示了。

图片 7

这一步关键是采用select2提供的选料控件创设图形语法来驱动数据展现。如上海图书馆所示,对应的G2代码图形语法为:

g2chart.facet(‘rect’, { fields: [ ‘Admit’, ‘Dept’ ], eachView(view) {
view.interval().position(‘Gender*Freq’).color(‘Gender’).label(‘Freq’);
} });

1
2
3
4
5
6
g2chart.facet(‘rect’, {
  fields: [ ‘Admit’, ‘Dept’ ],
  eachView(view) {
    view.interval().position(‘Gender*Freq’).color(‘Gender’).label(‘Freq’);
  }
});

图形语法首要含有以下多少个至关主要的要素:

 

<!–模块展现 begin–>
<div class=”modeShow”>
<div id=”debug”></div>
<div class=”imgMap mapBox”>
<img src=”../images/hot_images_map.png” name=”test” border=”0″
usemap=”#Map1″ width=”980″ height=”450″ ref=’imageMaps’ />
<map name=”Map1″>
<area shape=”rect” coords=”300,80,500,150″ href=”mall.10010.com”
/>
</map>
</div>
</div>
<!–模块突显 end—>

几何标识 吉优metry

几何标志概念了应用什么的几何图形来表征数据。G2现在帮衬如下这一个几何标志:

geom 类型 描述
point 点,用于绘制各种点图。
path 路径,无序的点连接而成的一条线,常用于路径图的绘制。
line 线,点按照 x 轴连接成一条线,构成线图。
area 填充线图跟坐标系之间构成区域图,也可以指定上下范围。
interval 使用矩形或者弧形,用面积来表示大小关系的图形,一般构成柱状图、饼图等图表。
polygon 多边形,可以用于构建色块图、地图等图表类型。
edge 两个点之间的链接,用于构建树图和关系图中的边、流程图中的连接线。
schema 自定义图形,用于构建箱型图(或者称箱须图)、蜡烛图(或者称 K 线图、股票图)等图表。
heatmap 用于热力图的绘制。

那边要介意,intervalstack是法定支持的,可是文书档案未有关系,在翻阅G2的API文书档案的时候,作者也发觉文书档案讲的不是很精通,有成都百货上千地点还未讲领悟什么使用API。那也是开源软件值得改革之处。

 

js代码:

图形属性 Attributes

图片属性对应视觉编码中的不相同因素,大家能够参照作者的另生机勃勃博客 数码可视化中的视觉属性 。

图形属性主要有以下二种。

  1. position:地点,二维坐标系内映射至 x 轴、y 轴;
  2. color:颜色,满含了颜色、饱和度和亮度;
  3. size:大小,不一致的几何标识对大小的概念相差十分大;
  4. shape:形状,几何标志的造型决定了有些具体图表类型的表现情势,举例点图,能够采纳圆点、三角形、图片表示;线图能够有折线、曲线、点线等表现方式;
  5. opacity:折射率,图形的发光度,这一个性子从某种意义上的话能够动用颜色代表,供给选拔‘rgba’ 的花样,所以在 G2 中大家独立出来。

在塑造语法的时候,大家把图片属性绑定二个要么多个数据字段。

 

复制代码 代码如下:

坐标系 Coordinates

坐标系是将二种职位标度结合在一块构成的
2 维定位系统,描述了数据是何等映射到图片所在的平面。

G2提供了以下两种坐标系:

coordType 说明
rect 直角坐标系,目前仅支持二维,由 x, y 两个互相垂直的坐标轴构成。
polar 极坐标系,由角度和半径 2 个维度构成。
theta 一种特殊的极坐标系,半径长度固定,仅仅将数据映射到角度,常用于饼图的绘制。
helix 螺旋坐标系,基于阿基米德螺旋线。

 

(function($) {
jQuery.fn.imageMaps = function(setting) {
var $container = this;
if ($container.length == 0) return false;
$container.each(function(){
var container = $(this);
var $images = container.find(‘img[ref=imageMaps]’);
$images.wrap(‘<div class=”image-maps-conrainer
image-maps-conrainerEdit”
style=”position:relative;”></div>’).css(‘border’,’1px solid
#ccc’);
$images.each(function(){
var _img_conrainer = $(this).parent();
_img_conrainer.append(‘<div class=”button-conrainer”><a
href=”javascript:void(0)” class=”addHot”>增多火爆</a><a
href=”javascript:void(0)” class=”addImg”>上传图片</a><a
class=”delSub delMode”
href=”javascript:void(0)”>删除×</a></div>’).append(‘<div
class=”link-conrainer”><ul></ul><div
class=”clr”></div></div><div
class=”clr”></div><span
class=”numFloor”>模块-1</span>’).append($.browser.msie ?
$(‘<div class=”position-conrainer”
style=”position:absolute”></div>’).css({
background:’#fff’,
opacity:0
}) : ‘<div class=”position-conrainer”
style=”position:absolute”></div>’);
var _img_offset = $(this).offset();
var _img_conrainer_offset = _img_conrainer.offset();
_img_conrainer.find(‘.position-conrainer’).css({
top: _img_offset.top – _img_conrainer_offset.top,
left: _img_offset.left – _img_conrainer_offset.left,
width:$(this).width(),
height:$(this).height(),
border:’1px solid transparent’
});
var map_name = $(this).attr(‘usemap’).replace(‘#’,”);
if(map_name !=”){
var index = 1;
var _link_conrainer = _img_conrainer.find(‘.link-conrainer ul’);
var _position_conrainer =
_img_conrainer.find(‘.position-conrainer’);
var image_param = $(this).attr(‘name’) == ” ? ” : ‘[‘+
$(this).attr(‘name’) + ‘]’;
container.find(‘map[name=’+map_name+’]’).find(‘area[shape=rect]’).each(function(){
var coords = $(this).attr(‘coords’);
$(this).attr(‘ref’,”1″);
_link_conrainer.append(‘<li ref=”‘+index+'”
class=”map-link”><span
class=”link-number-text”>热点’+index+'</span>: <input
type=”text” size=”60″ name=”link’+index+'” class=”linkHref”
value=”‘+$(this).attr(‘href’)+'” /><input type=”hidden”
class=”rect-value” name=”rect’+index+'” value=”‘+coords+'”
/></li>’);
coords = coords.split(‘,’);
_position_conrainer.append(‘<div ref=”‘+index+'”
class=”map-position”
style=”left:’+coords[0]+’px;top:’+coords[1]+’px;width:’+(coords[2]-coords[0])+’px;height:’+(coords[3]-coords[1])+’px;”><div
class=”map-position-bg”></div><span
class=”link-number-text”>热点’+index+'</span><span
class=”delete”>X</span><span
class=”resize”></span></div>’);
index++;
});
}
});
});
$container.find(‘.button-conrainer .addHot’).live(“click”,function(){
var _link_conrainer = $(this).parent().parent().find(‘.link-conrainer
ul’);
var _position_conrainer =
$(this).parent().parent().find(‘.position-conrainer’);
var index = _link_conrainer.find(‘.map-link’).length +1;
var _coordsMap = $(this).parent().parent().next(‘map’);
var image =
$(this).parent().parent().find(‘img[ref=imageMaps]’).attr(‘name’);
image = (image == ” ? ” : ‘[‘+ image + ‘]’);
_link_conrainer.append(‘<li ref=”‘+index+'”
class=”map-link”><span
class=”link-number-text”>热点’+index+'</span>: <input
type=”text” size=”60″ name=”link’+index+'” class=”linkHref” value=””
/><input type=”hidden” class=”rect-value” name=”rect’+index+'”
value=”300,80,500,150″ /></li>’);
_position_conrainer.append(‘<div ref=”‘+index+'”
class=”map-position”
style=”left:300px;top:80px;width:200px;height:70px;”><div
class=”map-position-bg”></div><span
class=”link-number-text”>热点’+index+'</span><span
class=”delete”>X</span><span
class=”resize”></span></div>’);
var coords = _link_conrainer.find(‘input[name=rect’+ index
+’]’).val();
_coordsMap.append(‘<area ref=”‘+index+'” href=”” coords=”‘+ coords
+'” shape=”rect”>’);
$(“input[name=’link”+index+”‘]”).val(“请输入本热门对应的链接地址”);
bind_map_event();
define_css();
//添加map热区
});
//修正链接地址
$(“.linkHref”).live(“blur”,function(){
var valueHref = $(this).val();
var thisRef = $(this).parent().attr(‘ref’);
var appArea = $(this).parents(“.link-conrainer”).parent().next(‘map’);
$(this).val(valueHref);
appArea.find(‘area[ref=’+thisRef+’]’).attr(“href”,valueHref);
});
//绑定map事件
function bind_map_event(){
$(‘.position-conrainer .map-position
.map-position-bg’).each(function(){
var map_position_bg = $(this);
var conrainer = $(this).parent().parent();
map_position_bg.unbind(‘mousedown’).mousedown(function(event){
map_position_bg.data(‘mousedown’, true);
map_position_bg.data(‘pageX’, event.pageX);
map_position_bg.data(‘pageY’, event.pageY);
map_position_bg.css(‘cursor’,’move’);
return false;
}).unbind(‘mouseup’).mouseup(function(event){
map_position_bg.data(‘mousedown’, false);
map_position_bg.css(‘cursor’,’default’);
return false;
});
conrainer.mousemove(function(event){
if (!map_position_bg.data(‘mousedown’)) return false;
var dx = event.pageX – map_position_bg.data(‘pageX’);
var dy = event.pageY – map_position_bg.data(‘pageY’);
if ((dx == 0) && (dy == 0)){
return false;
}
var map_position = map_position_bg.parent();
var p = map_position.position();
var left = p.left+dx;
if(left <0) left = 0;
var top = p.top+dy;
if (top < 0) top = 0;
var bottom = top + map_position.height();
if(bottom > conrainer.height()){
top = top-(bottom-conrainer.height());
}
var right = left + map_position.width();
if(right > conrainer.width()){
left = left-(right-conrainer.width());
}
map_position.css({
left:left,
top:top
});
map_position_bg.data(‘pageX’, event.pageX);
map_position_bg.data(‘pageY’, event.pageY);
bottom = top + map_position.height();
right = left + map_position.width();
var newArea = new Array(left,top,right,bottom).join(‘,’);
var mapApp = conrainer.parent().next(‘map’);
mapApp.find(‘area[ref=’+map_position.attr(‘ref’)+’]’).attr(“coords”,newArea);
$(‘.link-conrainer li[ref=’+map_position.attr(‘ref’)+’]
.rect-value’).val(newArea);
return false;
}).mouseup(function(event){
map_position_bg.data(‘mousedown’, false);
map_position_bg.css(‘cursor’,’default’);
return false;
});
});
$(‘.position-conrainer .map-position .resize’).each(function(){
var map_position_resize = $(this);
var conrainer = $(this).parent().parent();
map_position_resize.unbind(‘mousedown’).mousedown(function(event){
map_position_resize.data(‘mousedown’, true);
map_position_resize.data(‘pageX’, event.pageX);
map_position_resize.data(‘pageY’, event.pageY);
return false;
}).unbind(‘mouseup’).mouseup(function(event){
map_position_resize.data(‘mousedown’, false);
return false;
});
//点击撤消拖动
conrainer.unbind(‘click’).click(function(event){
map_position_resize.data(‘mousedown’, false);
return false;
});
conrainer.mousemove(function(event){
if (!map_position_resize.data(‘mousedown’)) return false;
var dx = event.pageX – map_position_resize.data(‘pageX’);
var dy = event.pageY – map_position_resize.data(‘pageY’);
if ((dx == 0) && (dy == 0)){
return false;
}
var map_position = map_position_resize.parent();
var p = map_position.position();
var left = p.left;
var top = p.top;
var height = map_position.height()+dy;
if((top+height) > conrainer.height()){
height = height-((top+height)-conrainer.height());
}
if (height <20) height = 20;
var width = map_position.width()+dx;
if((left+width) > conrainer.width()){
width = width-((left+width)-conrainer.width());
}
if(width <50) width = 50;
map_position.css({
width:width,
height:height
});
map_position_resize.data(‘pageX’, event.pageX);
map_position_resize.data(‘pageY’, event.pageY);
bottom = top + map_position.height();
right = left + map_position.width();
var newArea = new Array(left,top,right,bottom).join(‘,’);
var mapApp = conrainer.parent().next(‘map’);
mapApp.find(‘area[ref=’+map_position.attr(‘ref’)+’]’).attr(“coords”,newArea);
$(‘.link-conrainer li[ref=’+map_position.attr(‘ref’)+’]
.rect-value’).val(newArea);
return false;
}).mouseup(function(event){
map_position_resize.data(‘mousedown’, false);
return false;
});
});
$(‘.position-conrainer .map-position
.delete’).unbind(‘click’).click(function(){
var ref = $(this).parent().attr(‘ref’);
var _link_conrainer =
$(this).parent().parent().parent().find(‘.link-conrainer ul’);
var _coordsMap = $(this).parent().parent().parent().next(‘map’);
var _position_conrainer =
$(this).parent().parent().parent().find(‘.position-conrainer’);
_link_conrainer.find(‘.map-link[ref=’+ref+’]’).remove();
_position_conrainer.find(‘.map-position[ref=’+ref+’]’).remove();
_coordsMap.find(‘area[ref=’+ref+’]’).remove();
var index = 1;
_link_conrainer.find(‘.map-link’).each(function(){
$(this).attr(‘ref’,index).find(‘.link-number-text’).html(‘热点’+index);
index ++;
});
index = 1;
_position_conrainer.find(‘.map-position’).each(function(){
$(this).attr(‘ref’,index).find(‘.link-number-text’).html(‘热点’+index);
index ++;
});
index = 1;
_coordsMap.find(‘area’).each(function(){
$(this).attr(‘ref’,index);
index ++;
});
});
}
bind_map_event();
function define_css(){
//样式定义
$container.find(‘.map-position .resize’).css({
display:’block’,
position:’absolute’,
right:0,
bottom:0,
width:5,
height:5,
cursor:’nw-resize’,
background:’#000′
});
}
define_css();
};
})(jQuery);

分面 Facet

分面,将生龙活虎份数据遵照有些维度分隔成几何子集,然后创设叁个图片的矩阵,将每三个数据子集绘制到图片矩阵的窗格中。分面其实提供了多少个效用:

  1. 规行矩步钦定的维度划分数据集;
  2. 对图纸进行制版。

G2扶植以下的分面类型:

分面类型 说明
rect 默认类型,指定 2 个维度作为行列,形成图表的矩阵。
list 指定一个维度,可以指定一行有几列,超出自动换行。
circle 指定一个维度,沿着圆分布。
tree 指定多个维度,每个维度作为树的一级,展开多层图表。
mirror 指定一个维度,形成镜像图表。
matrix 指定一个维度,形成矩阵分面。

注意,在自己的代码中,为了简化使用,只扶植list和rect,当绑定一个字段的时候用list,绑定七个字段的时候用rect。

除开上边提到的因素,当然还会有不菲其余的要素大家并未有满含和支撑,举例:坐标轴,图例,提示等等。

至于图形的语法的越多内容,请仿效这里。

转移图形语法的宗旨代码如下:

function getFacet(faced, grammarScript) { let facedType = “list”; let
facedScript = “” grammarScript =
grammarScript.replace(chartScriptName,”view”); if ( faced.length == 2 )
{ facedType = “rect”; } let facedFields = faced.join(“‘, ‘”) facedScript
= facedScript + `${ chartScriptName }.facet(‘${ facedType }’, {n`;
facedScript = facedScript + ` fields: [ ‘${ facedFields }’ ],n`;
facedScript = facedScript + ` eachView(view) {n`; facedScript =
facedScript + ` ${ grammarScript };n`; facedScript = facedScript + `
}n`; facedScript = facedScript + `});n`; return facedScript }
function getGrammar() { let grammar = {}, grammarScript =
chartScriptName + “.”; grammar.geom = $(‘#geomSelect’).val();
grammar.coord = $(‘#coordSelect’).val(); grammar.faced =
$(‘#facetSelect’).val(); geom_attributes.map(function(attr){
grammar[attr] = $(‘#’ + attr + “attr”).val(); }); grammarScript =
grammarScript + grammar.geom + “()”;
geom_attributes.map(function(attr){ if (grammar[attr].length > 0)
{ grammarScript = grammarScript + “.” + attr + “(‘” +
grammar[attr].join(“*”) + “‘)”; } }); if (grammar.coord) {
grammarScript = grammarScript + “;n ” + chartScriptName + “.” +
“coord(‘” + grammar.coord + “‘);”; } else { rammarScript = grammarScript

  • “;”; } if ( grammar.faced ) { if ( grammar.faced.length == 1 ||
    grammar.faced.length == 2 ) { grammarScript = getFacet(grammar.faced,
    grammarScript); } } console.log(grammarScript) return grammarScript; }
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
function getFacet(faced, grammarScript) {
  let facedType = "list";
  let facedScript = ""
  grammarScript = grammarScript.replace(chartScriptName,"view");
  if ( faced.length == 2 ) {
      facedType = "rect";
  }
  let facedFields = faced.join("’, ‘")
  facedScript = facedScript + `${ chartScriptName }.facet(‘${ facedType }’, {n`;
  facedScript = facedScript + `  fields: [ ‘${ facedFields }’ ],n`;
  facedScript = facedScript + `  eachView(view) {n`;
  facedScript = facedScript + `    ${ grammarScript };n`;
  facedScript = facedScript + `  }n`;
  facedScript = facedScript + `});n`;
  return facedScript
}
 
function getGrammar() {
  let grammar = {}, grammarScript = chartScriptName + ".";
  grammar.geom = $(‘#geomSelect’).val();
  grammar.coord = $(‘#coordSelect’).val();
  grammar.faced = $(‘#facetSelect’).val();
  geom_attributes.map(function(attr){
    grammar[attr] = $(‘#’ + attr + "attr").val();
  });
  
  grammarScript = grammarScript + grammar.geom + "()";
  geom_attributes.map(function(attr){
    if (grammar[attr].length > 0) {
      grammarScript = grammarScript + "." + attr + "(‘" + grammar[attr].join("*") + "’)";
    }
  });
  
  if (grammar.coord) {
    grammarScript = grammarScript + ";n " + chartScriptName + "." + "coord(‘" + grammar.coord + "’);";
  } else {
    rammarScript = grammarScript + ";";
  }
  
  if ( grammar.faced ) {
    if ( grammar.faced.length == 1 ||
        grammar.faced.length == 2 ) {
      grammarScript = getFacet(grammar.faced, grammarScript);
    }
  }
  
  console.log(grammarScript)
  return grammarScript;
}

这里有几点要在意:

  • 行使JS的模版字符串能够有效的协会代码片段
  • 利用eval实施组织好的语法驱动的代码来响应select的change事件,以拿到杰出的交互作用性。在生育条件,要在乎该办法的安全性隐患,因为纯前端,eval能拉动的威逼一点都一点都不大,临盆中,能够把那些奉行放在安全的沙箱中运转
  • 你要求掌握图形语法,实际不是随意的组巴拿马城能使得出可行的图片。

此处对于select2的多选,有二个小的唤醒,在缺省气象下,多选的逐条是平素的逐生机勃勃,并不依赖选用的生龙活虎意气风发,不过不菲图纸语法和字段的各种有关,所以大家使用如下的点子来对症用药select的接收事件。

function updateSelect2Order(evt) { let element =
evt.params.data.element; let $element = $(element); $element.detach();
$(this).append($element); $(this).trigger(“change”); }

1
2
3
4
5
6
7
function updateSelect2Order(evt) {
  let element = evt.params.data.element;
  let $element = $(element);
  $element.detach();
  $(this).append($element);
  $(this).trigger("change");
}

那般做即是每趟选中后,把前段时间入选的种类移到数码最后之处。

 

页面引用:$(‘.imgMap’).imageMaps();

风华正茂部分事例

好了,上边大家就来看有的例子,明白一下怎么采用图形语法来剖析和追究数据。

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注