澳门新萄京官方网站-www.8455.com-澳门新萄京赌场网址

简单来说Logo类,折线图数据绑定难题

2019-07-14 作者:澳门新萄京赌场网址   |   浏览(64)

用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 ,一样面对该思索影响的还会有奥迪Q5的图形库ggplot。

图片 2

在多少可视化开源领域里,我们对百度支付的echarts可谓听得多了自然能详细说出来,echarts经过多年的腾飞,其职能确实丰裕强劲,可用优良来描写。不过蚂蚁金服开源的基于The Grammar Of Graphics的语法驱动的可视化库G2,令人耳目一新。那我们就看看如何使用G2和500行左右的纯前端代码来兑现贰个的临近Tableau的数目剖判作用。

  • 示范参见 
  • 代码参见 https://gist.github.com/gangtao/e053cf9722b64ef8544afa371c2daaee 

 

现行反革命照拂下发出来,希望大家一道学习啊

近些日子整治下发出来,希望我们齐声学习啊

highcharts 折线图数据绑定难题

因为编辑器会对代码有所破坏,所以提供贰个在线演示

数码加载

第一步是加载数据:

图片 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()方法。这里要做的是把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. 简单来说Logo类,折线图数据绑定难题。sanitizeData()方法会更动输入对象,所以在扩散从前做了三个纵深拷贝,这里运用JSON的stringfy和parse方法能够对JSON包容的指标有效的正片。

这里要注意,Iris数据集中在datatable中的列名都不呈现点,但实质上数目并未变动。

 

先看作用图:
图片 4
用了jquery.image-maps.js这一个插件 下载地址 //www.jb51.net/jiaoben/57930.html
原理是:
通过拖动总计出脚下热区可活动模块的left top right bottom
对应area的 coords 属性集成上面包车型地铁职位,就能够实现热区了。
相应的模块代码是:

先看效用图:
图片 5
用了jquery.image-maps.js那一个插件 下载地址
原理是:
经过拖动总计出脚下热区可活动模块的left top right bottom
对应area的 coords 属性集成上边包车型地铁职位,就足以兑现热区了。
对应的模块代码是:

chart 代码

 var chart = new Highcharts.chart('container', { title: { text: XMMC, x: -20 //center }, subtitle: { text: '', x: -20 }, xAxis: { categories: [] }, yAxis: { title: { text: '金额' }, plotLines: [{ value: 0, width: 1, color: '#808080' }] }, tooltip: { valueSuffix: '万元' }, legend: { layout: 'vertical', align: 'right', verticalAlign: 'middle', borderWidth: 0 }, series: [{ name: '缴存', data: [] //[7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6] //}, { //name: '使用', //data: [-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5] //}, { //name: '余额', //data: [-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6, 17.9, 14.3, 9.0, 3.9, 1.0] }] });

复制代码 代码如下:

多少图谋

多少加载完结,大家来到第二步的多寡筹算阶段。数据妄想是数码精确项目最花时间的一步,经常要求对数据开始展览大气的清洗,变形,收取等职业,使得数据变得可用。

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

一是展现数据的多少个摘要,让大家开端询问多少的大概,为更为的数额变形和管理做好准备。

以此是Iris数据集的摘要:

图片 6

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查询来对数据进行越来越加工。

图片 7

上图的例证中大家选取限制条件得到三个Iris数据的子集。

另外G2还提供了Dataset的功能:

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

数据管理是叁个相当大的话题,大家的对象是采纳尽只怕少的代码完成贰个数目解析的工具,所以这一步仅仅是运用alasql提供的SQL查询来管理数量。

 

复制代码 代码如下:

复制代码 代码如下:

x轴

 $.ajax({ type: "post", url: "tjfx.ashx?action=GetCategories", cache: false, success: function  { var dataTemp = data; var arr = new Array(); arr.push(dataTemp[0].Column1); arr.push(dataTemp[0].Column2); arr.push(dataTemp[0].Column3); arr.push(dataTemp[0].Column4); arr.push(dataTemp[0].Column5); arr.push(dataTemp[0].Column6); arr.push(dataTemp[0].Column7); arr.push(dataTemp[0].Column8); arr.push(dataTemp[0].Column9); arr.push(dataTemp[0].Column10); arr.push(dataTemp[0].Column11); arr.push(dataTemp[0].Column12); chart.xAxis[0].setCategories; }, error: function () { alert("请求超时,请重试!"); } });

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ";
<html xmlns=";
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>smipleChart</title>
<style type="text/css">

数码呈现

数据管理好后便是大家的宗旨内容,数据展现了。

图片 8

这一步关键是采取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—>

<!--模块显示 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—>

series

$.ajax({
type: "post",
url: "tjfx.ashx",
data: { "action": "GetChartData", "xmdah": XMDAH },
cache: false,
success: function {
//alert(JSON.stringify;
dataTmp = "";
$.each(data, function {
dataTmp = "[" field.a ", "

  • field.b ", "
  • field.c ", "
  • field.d ", "
  • field.e ", "
  • field.f ", "
  • field.g ", "
  • field.h ", "
  • field.i ", "
  • field.j ", "
  • field.k ", "
  • field.l "]" ",";
    });
    dataTmp = dataTmp.substring(0, dataTmp.length - 1);
    alert;
    chart.series[0].setData;
    },
    error: function () {
    alert("诉求超时,请重试!");
    }
    });

.cc{
height:450px; width:800px; border:1px solid #999; position:relative; margin:20px;
简单来说Logo类,折线图数据绑定难题。}
</style>
</head>

几何标识 吉优metry

几何标志概念了运用什么的几何图形来表征数据。G2今后协助如下那些几何标识:

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

那边要细心,intervalstack是法定扶助的,然则文书档案未有关系,在翻阅G2的API文书档案的时候,作者也发觉文书档案讲的不是很领悟,有那多少个地方尚未评释白怎样采纳API。那也是开源软件值得创新的地点。

 

js代码:

js代码:

x轴和series 获取到的多少都木反常

alert 出的series 数据也应当没问题
图片 9

可是来得出来x轴多了除年份之外的数额,series 也木有绑上。。。
图片 10
请问问大神们何地错了?

<body>
<div id='t'></div>
<div id='t1'>

图片属性 Attributes

图形属性对应视觉编码中的分裂因素,大家能够仿效小编的另一博客 数量可视化中的视觉属性 。

图片属性首要有以下三种。

  1. position:地方,二维坐标系内映射至 x 轴、y 轴;
  2. color:颜色,包罗了颜色、饱和度和亮度;
  3. size:大小,差别的几何标识对大小的概念有差别;
  4. shape:形状,几何标志的形态决定了某些具体图表类型的表现方式,比方点图,能够应用圆点、三角形、图片表示;线图能够有折线、曲线、点线等表现格局;
  5. opacity:光滑度,图形的反射率,那特性子从某种意义上来讲能够采取颜色代表,须要采用‘rgba’ 的样式,所以在 G2 中我们独立出来。

在营造语法的时候,大家把图纸属性绑定多个依然三个数据字段。

 

复制代码 代码如下:

复制代码 代码如下:

</div>

坐标系 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);

(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);

<div id='line' class="cc"></div>
<div id='area' class="cc"></div>
<div id='zhu' class="cc"></div>
<div id='zhu1' class="cc" style="height:600px;"></div>
<div id='pie' class="cc"></div>
<div id='pies' class="cc"></div>
<div id='segment' class="cc"></div>
<div id='vv' class="cc" style='height:300px; width:520px;'></div>
<script type="text/javascript">
(function(doc,undefined){
var win = this,
hasSVG = win.SVGAngle || doc.implementation.hasFeature("", "1.1"),
isIE = /msie/i.test(navigator.userAgent) && !win.opera,
path = hasSVG?'d':'path',
seal = hasSVG?'z':'e',
math = Math,
mathRound = math.round,
mathFloor = math.floor,
mathCeil = math.ceil,
mathMax = math.max,
mathMin = math.min,
mathAbs = math.abs,
mathCos = math.cos,
mathSin = math.sin,
M = 'M',
L = 'L';

分面 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();

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

win.$ = function(Id){
return document.getElementById(Id);
};

一对例子

好了,上边大家就来看有的例证,了然一下怎么样行使图形语法来剖判和研究数据。

 

先看效用图: 用了jquery.image-maps.js那几个插件 下载地址 原理是: 通过...

win.extend = function(){
var target = arguments[0] || {}, i = 1, length = arguments.length, deep = true, options;
if ( typeof target === "boolean" ) {
deep = target;
target = arguments[1] || {};
i = 2;
}
if ( typeof target !== "object" && Object.prototype.toString.call(target)!="[object Function]")
target = {};
for(;i<length;i ){
if ( (options = arguments[ i ]) != null )
for(var name in options){
var src = target[ name ], copy = options[ name ];
if ( target === copy )
continue;
if ( deep && copy && typeof copy === "object" && !copy.nodeType ){
target[ name ] = arguments.callee( deep, src || ( copy.length != null ? [ ] : { } ), copy );
}
else if(copy !== undefined)
target[ name ] = copy;
}

艾丽丝数据集散点图

图片 11

图片语法:

g2chart.point().position('Sepal.Length*Petal.Length').color('Species').size('Sepal.Width')

1
g2chart.point().position('Sepal.Length*Petal.Length').color('Species').size('Sepal.Width')

 

}
return target;
};

Car数据集折线图

图片 12

图片语法:

g2chart.line().position('id*speed');

1
g2chart.line().position('id*speed');

切换来极坐标:

图片 13

图片语法:

g2chart.line().position('id*speed'); g2chart.coord('polar');

1
2
g2chart.line().position('id*speed');
g2chart.coord('polar');

 

win.each = function ( object, callback, args ) {
var name, i = 0, length = object.length;
if ( args ) {
args = Array.prototype.slice.call(arguments).slice(2);
if ( length === undefined ) {
for ( name in object )
if ( callback.apply( object[ name ],[name,object[ name ]].concat(args) ) === false )
break;
} else
for ( ; i < length; i )
if ( callback.apply( object[ i ],[i,object[ i ]].concat(args)) === false ) //
break;
} else {
if ( length === undefined ) {
for ( name in object )
if ( callback.call( object[ name ], name, object[ name ] ) === false )
break;
} else
for ( var value = object[0];
i < length && callback.call( value, i, value ) !== false; value = object[ i] ){}
}
return object;
};
//---------------------------------------------------------------
function processPoint( x ){
return isIE ? ~~x.toFixed(0) : ~~x.toFixed(0) 0.5;
};
function calTextLen(txt, cssStr){
var span = doc.createElement('span');
if(cssStr){
typeof cssStr === 'string'
? span.style.cssText = cssStr
: extend(span.style,cssStr);
}else{
extend(span.style,{
fontSiz : '12px',
fontFamily : '"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif'
});
}
span.innerHTML = txt || '';
span.style.visibility = 'hidden';
doc.body.appendChild(span);
var width = span.offsetWidth,
height = span.offsetHeight;
doc.body.removeChild(span);
return {w:width,h:height};
};
function angle(r,center,o,jingdu){
var hudu = Math.PI*2*(o/360),
x = center[0] r*Math.sin(hudu),
y = center[1] -r*Math.cos(hudu);
return [x.toFixed(jingdu||0),y.toFixed(jingdu||0)];
}

伯克利数据柱状图

图片 14

多少管理:

SELECT SUM(Freq) as f , Gender FROM table GROUP BY Gender

1
SELECT SUM(Freq) as f , Gender FROM table GROUP BY Gender

图形语法:

g2chart.interval().position('Gender*f').color('Gender').label('f');

1
g2chart.interval().position('Gender*f').color('Gender').label('f');

 

function xx(a,b,lineNum){

Beck雷数据堆集柱状图

图片 15

数据管理:

SELECT SUM(Freq) as f , Gender , Admit FROM table GROUP BY Gender, Admit

1
SELECT SUM(Freq) as f , Gender , Admit FROM table GROUP BY Gender, Admit

图片语法:

g2chart.intervalStack().position('Gender*f').color('Admit')

1
g2chart.intervalStack().position('Gender*f').color('Admit')

 

var t = 10000;
var stf = ((b*t-a*t)/lineNum)/t,
arr = [1,2,2.5,5,10],
c = 1,
v;

Beck雷数据饼图

图片 16

数据管理:

SELECT SUM(Freq) as f , Gender FROM table GROUP BY Gender

1
SELECT SUM(Freq) as f , Gender FROM table GROUP BY Gender

图形语法:

g2chart.intervalStack().position('f').color('Gender').label('f'); g2chart.coord('theta')

1
2
g2chart.intervalStack().position('f').color('Gender').label('f');
g2chart.coord('theta')

 

// 分水岭的基数是 [1,2,2.5,5,10] 那么些手续是搜索 间隔 属于哪个范围
if(stf<arr[0]){
while( stf<arr[0] ){
c = c*10;
arr[0]=arr[0]/c;
}
each([1,2,2.5,5,10],function(i,o){
arr[i]= o/c;
});
}else if(stf>arr[4]){
while( stf>arr[4] ){
c = c*10;
arr[4] = arr[4]*c;
}
each([1,2,2.5,5,10],function(i,o){
arr[i]= o*c;
});
}

Beck雷数据分面包车型大巴施用

图片 17

图表语法:

g2chart.facet('rect', { fields: [ 'Dept', 'Admit' ], eachView(view) { view.coord('theta'); view.intervalStack().position('Freq').color('Gender'); } });

1
2
3
4
5
6
7
g2chart.facet('rect', {
  fields: [ 'Dept', 'Admit' ],
  eachView(view) {
    view.coord('theta');
    view.intervalStack().position('Freq').color('Gender');
  }
});

更加多的深入分析图形留给大家去品尝

 

//上边找到间隔后 找到间隔中最相仿的一个
each(arr,function(i,o){
if(stf<o){
v = o;
return false;
}
});
//a 是非常的小的
//b是最大 的
a = (a*t-mathAbs((a%v)*t))/t;
b = (b*t (b%v===0?0:(v-b%v))*t)/t;

总结

本文分享了一个应用纯前端才干创设三个近乎Tableau的BI应用的例证,整个代码总结:

  • JS 370 行 JS6
  • HTML 69 9 5 = 83
  • CSS 21

总计474 行,用那样少的代码就会成功五个看上去还不易的BI工具,还算不错啊。当然这里关键是由于开源社区提供了那般多好的前端库以供应用,笔者要做的单独是让它们有效的干活在一同。这些只好算是个原型,从效益和品质上的话都不成熟,可是能在浏览器中不借助于任何的服务器来兑现BI的数码剖判成效,应该会有多数少人想要在大团结的应用中嵌三个吧?

结合本身事先分享的TensorflowJS的文章,下边一步大概是参加预测效果,为数据剖判到场智能,前端选拔的前景,不可捉摸!

 

//看看还剩几条线未有画

参考

  • axios  基于Promise的HTTP客户端
  • alasql 基于JS的开源SQL数据库
  • jquery datatable JQuery的数额表格插件
  • select2 JQuery的选项控件插件
  • 连带博客 运用开源软件飞速搭建数据分析平台 
  • 连带博客 数量可视化中的视觉属性

    2 赞 1 收藏 评论

图片 18

var num = Math.max(0,lineNum - Math.round((b-a)/v));

if(a>=0){
//让图相比较靠中间
/*while(num!==0){
num%2===0
? a = (a*t-v*t)/t
: b = (b*t v*t)/t;
num--;
}*/

//坐标比较整数化
if(a!=0&&num!=0){
while(a!=0&&num!=0){
a = (a*t-v*t)/t;
num--;
if((a*t-v*num*t)/10000>0&&a===0)
break;
}
}

if(num!=0){
while(num!==0){
b = (b*t v*t)/t
num--;
}
}

}else{
//让图相比较靠中间
/*while(num!==0){
num%2===0
? b = (b*t v*t)/t
: a = (a*t-v*t)/t
num--;
}*/
//坐标相比整数化
if(b<0&&num!=0){
while(b!=0&&num!=0){
b = (b*t v*t)/t;
num--;
if((b*t v*num*t)/t<0&&a===0)
break;
}
}
if(num!=0){
while(num!==0){
a = (a*t-v*t)/t
num--;
}
}

}
return {min:a,max:b,stf:v};
}
//---------------------------------------------------------------------------------------------------------------
//对svg vml成分的有的创设 修改属性 样式 删除 == 一些的操作
win.vector = function(){};
win.vector.prototype = {
$c : function(graphic,nodeName){
this.element = this[0] = doc.createElementNS('', nodeName);
this.graphic = graphic;
return this;
},
attr: function(hash,val){
var elem = this.element,
key,
value;
if(typeof hash === 'string'){
if(val === undefined){
return elem.getAttribute(hash);
}else{
elem.setAttribute(hash, val);
return this;
}
} else {
for(key in hash){
value = hash[key];
if(key === path){
value && value.join
&&(value = value.join(' '));

/(NaN| |^$)/.test(value)
&&(value = 'M 0 0');
}
elem.setAttribute(key, value)
}
}
return this;
},
css: function(hash){
var str = '';
for(var key in hash){
if(isIE && key == "opacity"){
this.element.style['filter'] = "alpha(opacity=" hash[key] * 100 ")";
}else{
this.element.style[key] = hash[key];
}
}
return this;
},
on: function(eventName, handler){
var self = this;
this.element.addEventListener(eventName,function(){
handler.call(self)
},false);
return this;
},
appendTo: function(parent){
if(parent){
parent.element
? parent.element.appendChild(this.element)
: parent.appendChild(this.element)

} else {
this.graphic.container.appendChild(this.element);
}
return this;
},
addText: function(str){
var elem = this.element;
if(elem.nodeName === 'text'){
elem.appendChild(doc.createTextNode(str.toString() || ' '));
}
return this;
},
setOpacity : function(v){
this.attr('fill-opacity',v)
},
toFront: function() {
this.element.parentNode.appendChild(this.element)
return this;
},
show: function(){
this.element.style.display = 'block';
return this;
},
hide: function(){
this.element.style.display = 'none';
return this;
}
};
//---------------------------------------------------------------------------------------------------------------

//---------------------------------------------------------------------------------------------------
//假使是vml修改个中的一对艺术
if(!hasSVG){
//-------------创建vml环境-----------------
doc.createStyleSheet().addRule(".vml", "behavior:url(#default#VML);display:inline-block;position:absolute;left:0px;top:0px");
!doc.namespaces.vml && ! "v1";
doc.namespaces.add("vml", "urn:schemas-microsoft-com:vml");

//-------------修改部分方法-----------------
extend(vector.prototype,{
$c : function(graphic,nodeName){
var name = nodeName || 'shape';
this.element= this[0] = (name === 'div' || name === 'span')
? doc.createElement(name)
: doc.createElement('<vml:' name ' class="vml">');
this.graphic = graphic;
return this;
},
on : function(eventName, handler){
var self = this;
this.element.attachEvent("on" eventName,function(){
handler.call(self);
});
return this;
},
addText : function(txt){
var elem = this.element;
elem.innerHTML = txt || '';
return this;
},
setOpacity : function(v){
this.opacity.opacity=v;
}
});
}
//---------------------------------------------------------------------------------------------------

//画图类
//------------------------------------------------------------
win.smipleChart = function(){
this.init.apply(this,arguments);
};
smipleChart.prototype = {
options : {
charts : {
paddingRight : 20,
radius : 200,
style : {
fontFamily : '"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif',
fontSize : '12px',
background : '#FFFFFF'
}
},
title : {
text : '',
y : 10,
style : {
fontFamily:'Verdana,Arial,Helvetica,sans-serif',
fontSize:'16px',
fontWeight:'bold'
}
},
subTitle : {
text : '',
y : 30,
style : {
fontFamily:'Verdana,Arial,Helvetica,sans-serif',
fontSize:'12px',
color: '#111'
}
},
yUnit : {
text : '',
style : {
fontFamily:'Verdana,Arial,Helvetica,sans-serif',
fontSize:'12px',
color: '#111'
},
lineNum :10
}
},
init : function(container,options,width,height){
this.width = width || container.offsetWidth;
this.height = height || container.offsetHeight;
this.mainGroup = {};

//svg 里面画图 必须有叁个svg标签 vml就用div了
this.container = hasSVG
? new vector().$c(1,'svg')
.attr({
xmlns : '',
version : '1.1'
})
.css({fontSize : '12px'})
.appendTo(container).element
: new vector().$c(1,'div')
.css({
fontSize : '12px',
width : this.width 'px',
height : this.height 'px'
})
.appendTo(container).element;
var c = extend(true,{},this.options)
var opts = this.opts = extend(true,c,options),
style = extend(opts.charts.style,{
width : this.width,
height : this.height
});

//总结油画盘子的时候供给的一对参数
this.getDrawArea()
.createTooltip() //创制提示新闻的规模
.drawTitle() //画标题
//画盘子

if('line,area,pie'.indexOf(opts.charts.type)>=0){
opts.charts.panel = 'x';
}

if(' pie,pies'.indexOf(opts.charts.type)<0){
this.drawPanel();
}

this.drawLegend(opts.legend.type); //画色块条

var type = {
line : 'drawLine',
area : 'drawArea',
columns : 'drawColumns',
pie : 'drawPie',
pies : 'drawPies',
segment : 'drawSegment'
}[opts.charts.type];
this[type]();

},
createElement : function(nodeName){
return new vector().$c(this,nodeName);
},
group: function(name){
return this.createElement(isIE?'div':'g').attr('mark',name);
},
getDrawArea : function(){
var opts = this.opts,
width = this.width,
height = this.height,
title = opts.title,
subTitle = opts.subTitle,
area = {
// 去掉坐标轴左边的刻度文本宽度(预估) 80为定值 侧面只留80的间距
areaWidth : width - 80,
// 去掉坐标轴底下的文书和标线的万丈
areaHeight : height - 40,
//原点的X地方 上面会总计到
startX : 0,
//原点的Y地方 上边会估计到
startY : 0,
//中央的x坐标 画饼图的时候需求明白圆心的地方
centerX: 0,
//大旨的y坐标 画饼图的时候必要明白圆心的职位
centerY: 0
};

//假若主题目存在 减去主标题标惊人 不然 减去10的高
area.areaHeight -=(title.text !== '')
? title.y
: 10;

// 去掉副标题中度
area.areaHeight -=(subTitle.text !== '')
? subTitle.y
: 10

area.startX = 80;
area.startY = height - 40;

//圆心的职位
area.centerX = width / 2;
area.centerY = height / 2;

//侧面留部分空当
area.areaWidth -=20;
//上边也留部分距离
area.areaHeight -=15;

opts.area = area;

return this;

},
drawTitle : function(){
var opts = this.opts,
self = this,
arr = [opts.title,opts.subTitle,opts.yUnit],
//3个标题坐标的职责的基本参数
config = [
{
x : this.width / 2,
y : opts.title.y
},
{
x : this.width / 2,
y : opts.subTitle.y
},
{
x : opts.yUnit.x,
y : this.height / 2 - 20
}
],
tpanel = this.group('title')
.appendTo();

each(arr,function(i,title){
var text = title.text;
if(text){
var elem = self.baseDraw('span',{
'text-anchor':'left',
x : mathMax(config[i].x - calTextLen(text,title.style).w/2,10),
y : config[i].y
},calTextLen(title.text,title.style).h)
.css(title.style)
.addText(text)
.appendTo(tpanel);

//倘若为2的时候 就证实是副标题 将它竖过来
if(i===2){
hasSVG
? elem.attr({transform : 'rotate(270, ' (opts.yUnit.x 10) ', ' self.height / 2 ')'})
: (elem.element.style.filter ='progid:DXImageTransform.Microsoft.BasicImage(rotation=3)')
}

}
});
return this;
},

//画盘子 比较麻烦
drawPanel : function(type){
var opts = this.opts,
self = this,
area = opts.area,
isSegment= opts.charts.type==='segment',
//盘子的档次 是横盘子 依然纵盘子
type = opts.charts.panel || 'x';

// 底板
var drawAreaWidth = area.areaWidth,
drawAreaHeight = area.areaHeight,
//原点的坐标
startX = area.startX,
startY = area.startY;

var allData = [],
minValue = 0,
maxValue = 10,
lineNum = mathMax(opts.yUnit.lineNum,2),
min = opts.yUnit.min,
staff;

//组合具备的数据
each(opts.chartData,function(i,o){
isSegment
? each(o.data,function(j,d){
allData[j]
? allData[j] = allData[j] (~~d)
: allData[j] = ~~d;
})
: allData = allData.concat(o.data)
});

//给具有的数目排序 为了上边求最大值 最小值
allData.sort(function(a,b){return a-b});

//求出最大值 最小值
maxValue = allData[allData.length - 1];

each(allData,function(i,o){
if(o){
minValue = o;
return false;
}
});

//主盘子容器
this.panel = this.group('panel').appendTo();

var dd = xx(minValue,maxValue,lineNum),
min = dd.min,
max = dd.max,
f = dd.stf;

//表示画的是横坐标
if(type.toLowerCase()==='x'){
//横坐标单位距离
var xPices = drawAreaWidth / opts.xUnit.units.length,
//单位距离的大旨点
offset = xPices / 2,

yPices = drawAreaHeight / lineNum;

//--------------------------------画横向的点和文字---------------------------------------------------------
each(opts.xUnit.units,function(i,d){
self.baseDraw('path',{
border : 1,
borderColor : '#C0C0C0',
isfill : false,
path : [
M,
processPoint(startX (i * xPices)),
processPoint(startY),
L,
processPoint(startX (i*xPices)),
processPoint(startY 5)
]
}).
appendTo(self.panel);
var y = hasSVG?5:10,
span = self.baseDraw('span',{
x : startX offset (i * xPices),
y : startY y,
'text-anchor':'middle'
})
.css({
fontFamily:'Verdana,Arial,Helvetica,sans-serif',
fontSize:'12px'
})
.addText(opts.xUnit.units[i])
.appendTo(self.panel)
.element;

//vml没有x y的定义 所以要轻易span宽度的四分之二 今后用span都亟需减小
!hasSVG
span.style.left = parseInt(span.style.left) - span.offsetWidth/2 'px';

});
//--------------------------------画纵向的点和文字-----------------------------------------------------------------------
for(i=0;i<=lineNum;i ){
self.baseDraw('path',{
border : 1,
borderColor : '#C0C0C0',
isfill : false,
path : [M, startX, processPoint(startY - (i * yPices)), L, processPoint(startX drawAreaWidth), processPoint(startY - (i *yPices))]
})
.css({zIndex:-10})
.appendTo(self.panel);

var span = self.baseDraw('span',{
x : startX - 15,
y : startY - i * yPices-calTextLen(min i*f '').h/2,
'text-anchor':'middle'
})
.css({
'font-family':'Verdana,Arial,Helvetica,sans-serif',
'font-size':'12px',
width: '40px',
display:'block',
textAlign:'right'
})
.addText((min*1000 (i*1000*f/1000)*1000)/1000 '')
.appendTo(self.panel)
.element;

if(!hasSVG){
span.style.top = parseInt(span.style.top) span.offsetHeight/2 -5 'px';
span.style.left = parseInt(span.style.left) -35 'px'
}
}

}else{
//横坐标单位距离
var yPices = drawAreaHeight / (opts.xUnit.units.length),
//单位距离的中央点
offset = Math.round(yPices / 2);

var x = hasSVG?25:70,
vv = hasSVG?0:5;

each(opts.xUnit.units,function(i,d){

self.baseDraw('path',{
border : 1,
borderColor : '#C0C0C0',
isfill : false,
path : [
M,
processPoint(startX-5),
processPoint(startY-i * yPices),
L,
processPoint(startX),
processPoint(startY-i * yPices),
]
})
.appendTo(self.panel);
var span = self.baseDraw('span',{
x : startX - x,
y : startY -i * yPices-offset-calTextLen(d).h/2 vv,
'text-anchor':'middle'
})
.css({
fontFamily:'Verdana,Arial,Helvetica,sans-serif',
fontSize:'12px',
width : '60px',
textAlign:'right'
})
.addText(d)
.appendTo(self.panel)

});

var xPices = drawAreaWidth / lineNum;

for(var i=0;i<=lineNum;i ){
self.baseDraw('path',{
border : 1,
borderColor : '#C0C0C0',
isfill : false,
path : [
M,
processPoint(startX (i * xPices)),
processPoint(startY),
L,
processPoint(startX (i*xPices)),
processPoint(startY - drawAreaHeight)
]
}).
appendTo(self.panel);

var span = self.baseDraw('span',{
x : startX - calTextLen(min i*f '').w/2 i * xPices,
y : startY,
'text-anchor':'left'
})
.css({
fontFamily:'Verdana,Arial,Helvetica,sans-serif',
fontSize:'12px'
})
.addText(min i*f '')
.appendTo(self.panel)
.element;
}

}

//-----------------------------------------------------------------------------------------------------
//在画区域图的时候还索要源点的岗位啊
//因为坐标很只怕是负数 并且也能不是从0开首的 所以 上jianju
var jianju =0
if(min>0)jianju = min;
if(max<0)jianju = max;
//总括开首的职位
startX = opts.charts.panel==='x' ? startX :startX-xPices*(min/f);
startY = opts.charts.panel==='x' ? startY yPices*(min/f) : startY;

opts.draw = {
startX : startX, // X 轴起点
startY : startY , // Y 轴起点
xPices : xPices, // X 轴每份的上升的幅度
yPices : yPices, // Y 轴每份的大幅度
offset : offset, // X 单分核心点地方偏移量
jianju : jianju*yPices/f,
feed : f // Y 轴的每份有个别许
};
return this;
},

createTooltip : function(){
//一个组
this.tipC = this.group('tip')
.css({zIndex: 200,height:'20px',width:'20px',position:'absolute'})
.appendTo()
.hide()

//画一个框框baseDraw
this.tipBox = this.baseDraw('rect',{arc:0.22,fill:'#fff',border:2,borderColor:'#606060'})
.appendTo(this.tipC)

//因为svg里面包车型大巴g可以直接固定 然而vml里面包车型地铁group渲染异常的慢 所以改div 所以这里的父不一洋
var p = isIE ?this.tipBox :this.tipC;

this.tipTxtContainer = this.baseDraw('text',{fill:'#000000',x:5,y:19,'text-anchor':'left'})
.css({
fontFamily:'Verdana,Arial,Helvetica,sans-serif',
fontSize:'12px',
background: '#FFF'
})
.appendTo(p);

this.tipText = doc.createTextNode('');
this.tipTxtContainer[0].appendChild(this.tipText);
return this;
},
showTooltip : function(obj, x, y,data){
var txt =obj.name ((' : ' data)||''),
size = calTextLen(txt,this.tipTxtContainer[0].style.cssText),
pos = {x : x - (size.w 5 * 2)/2 ,y : y - 32};
this.tipC
.toFront()
.show();

if(hasSVG){
this.tipC.attr({transform:'translate(' pos.x ',' pos.y ')'});

this.tipBox
.attr({width : size.w 5 * 2,height : size.h 5 * 2,stroke : obj.color||'#606060'});
}else{
this.tipC.css({left:pos.x,top:pos.y});

this.tipBox
.css({width:size.w 5 * 2,height : size.h 5 * 2})
this.tipBox[0].strokeColor = obj.color||'#606060';
}

this.tipText.nodeValue = txt || '';
},
hideTooltip: function(){
this.tipC.hide();
},

drawLegend : function(type,redraw){
var self = this,
opts = this.opts,
//颜色块的尺寸
t_width = 20,
t_height = 20,
//块之间的偏离
t_space = 5,
datas = opts.chartData,
len = datas.length,
css = opts.legend.style,

//最大尺寸 假如是纵着的 须要最大的长短
maxWidth = 10,
maxHeight = 30,
//这些事物的职位
orig_pos = opts.legend.pos?opts.legend.pos:[2,2],

//显示遮盖组的函数
handle = function(i){
var g = self.mainGroup['chart' i];
if(g.show){
g.chart.hide();
g.show = false;
hasSVG
? this.attr({fill:'#ccc'})
: this[0].style.color = '#ccc'
}else{
g.chart.show();
g.show = true;
hasSVG
? this.attr({fill:'#000'})
: this[0].style.color = '#000'
}
},

arr = [];

type = type ||'lateral';
var legendPanel = self.group('Legend')
.appendTo();
if(type==='lateral'){
//假使是横着的
var top = orig_pos[1] 5,
th = hasSVG?0:3,
left = orig_pos[0] 5;
each(datas, function(i,d){
left = i===0 ? left : t_space left;
//计算有所left的岗位
self.baseDraw('rect',{
arc : 0.1,
fill : d.color,
border : 1,
borderColor : d.color,
left : left,
top : top,
width : t_width 'px',
height : t_height 'px'
})
.appendTo(legendPanel);
left = left t_width 2 t_space;
var w = calTextLen(d.name,css).w
self.baseDraw('span',{
'text-anchor':'left',
x : left,
y : top th
})
.css(extend(css,{cursor:'pointer'}))
.on('click',function(){
if(opts.charts.type==='pies')return;
handle.call(this,i);
})
.addText(d.name)
.appendTo(legendPanel);
left = left w;

});
this.baseDraw('rect',{
arc : 0.1,
fill : 'none',
border : 1.5,
borderColor : '#666666',
width : left t_space- orig_pos[0],
height : maxHeight,
left : orig_pos[0],
top : orig_pos[1]
})
.appendTo(legendPanel);
}else{

var top = orig_pos[1] 5,
th = hasSVG?0:3,
left = orig_pos[0] 5;
each(datas, function(i,d){
top = i===0 ? top : t_space top;
self.baseDraw('rect',{
arc : 0.1,
fill : d.color,
border : 1,
borderColor : d.color,
left : left,
top : top,
width : t_width 'px',
height : t_height 'px'
})
.appendTo(legendPanel);

var h = calTextLen(d.name,css).h;

self.baseDraw('span',{
'text-anchor':'left',
x : left t_width 2 t_space,
y : top th
})
.css(extend(css,{cursor:'pointer'}))
.addText(d.name)
.on('click',function(){
if(opts.charts.type==='pies')return;
handle.call(this,i);
})
.appendTo(legendPanel);
top = top h t_space;
maxWidth = Math.max(maxWidth,calTextLen(d.name,css).w);
});
this.baseDraw('rect',{
arc : 0.1,
fill : 'none',
border : 1.5,
borderColor : '#666666',
width : maxWidth 22 15,
height : top t_space-orig_pos[1],
left : orig_pos[0],
top : orig_pos[1]
})
.appendTo(legendPanel);
}
return this;
},
drawLine : function(){
var self = this,
opts = this.opts;
draw = opts.draw;
each(opts.chartData,function(i,o){
var id = 'chart' i,
lineGroup = self.group(id)
.appendTo();
self.mainGroup[id]={chart:lineGroup,show:true};
var path = [M],
data = o.data,
line;

for(var i = 0; i < data.length; i ){
if( data[i] == null){
//要是那一个数目不设有 何况不是第贰个数据 路线上加 M
if(path[path.length - 1] !== M)
path.push(M);
}else{
//假若不是第三个数据 路线增多L
i !== 0 && path.push("L");
//假诺前方贰个是null 並且不是第多个 把非常L去掉
if(i > 0 && data[i - 1] == null)
path.pop();
//计算出 点的x,y的位置
var x = draw.startX draw.offset (i * draw.xPices),
y = draw.startY - (data[i] * (draw.yPices / draw.feed));
if(isIE){
x = parseInt(x);
y = parseInt(y);
}
path.push(x);
path.push(y);
//画点
self.baseDraw('circle',{
x : x,
y : y,
r : 4,
fillColor : o.color
})
.attr({data:data[i]})
.css({zIndex:10,cursor:'pointer'})
.on('mouseover',(function(o,x,y){
return function(){
hasSVG
? (this[0].setAttribute('r','5'),line.attr({'stroke-width':2.5}))
: (this[0].strokeWeight = 3,line[0].strokeWeight = 2.5);
self.showTooltip(o,x,y,this.attr('data'));
}

})(o,x,y))
.on('mouseout',function(){
hasSVG
? (this[0].setAttribute('r','4'),line.attr({'stroke-width':1.5}))
: (this[0].strokeWeight = 1,line[0].strokeWeight = 1.5);
self.hideTooltip()
})
.on('click',function(){lineGroup.toFront(); })
.appendTo(lineGroup);

}
};
//画折线
line = self.baseDraw('path',{
border : 1.5,
borderColor : o.color,
isfill : false,
path : path
})
.css({zIndex:5})
.on('mouseover',function(){
hasSVG
? this.attr({'stroke-width':2.5})
: (this[0].strokeWeight = 2.5);
})
.on('mouseout',function(){
hasSVG
? this.attr({'stroke-width':1.5})
: (this[0].strokeWeight = 1.5);
})
.on('click',function(){lineGroup.toFront(); })
.appendTo(lineGroup);
});
return this;
},
drawArea : function(){
var self = this,
opts = this.opts,
draw = opts.draw;
each(opts.chartData,function(i,o){
var id = 'chart' i,
areaGroup = self.group(id).appendTo();
self.mainGroup[id] = {chart : areaGroup,show : true};
//有2个路线 一个是区域的路线 多个是线的门道

var areaPath = [M, (draw.startX draw.offset).toFixed(0), (draw.startY-draw.jianju).toFixed(0)],
path = [M],
data = o.data,
line;
for(var n=0,l=data.length;n<l;n ){
//假诺数据是空的
var len = areaPath.length;
if( data[n] === null){
//假使眼下的一个不是m 就再一次画 所以加上 M
if(path[path.length - 1] !== M)
path.push(M);

//假诺第4个 也许前面包车型地铁都为bull 修改起源坐标
len===3
&&(areaPath[1] = (draw.startX (n 1)*draw.xPices draw.offset).toFixed(0));

//假如前方二个不是截止标记符 区域图停止 假如第二个数据是null 则不开始展览上边的操作
if(areaPath[len - 1] !== seal&&n!==0){
areaPath=areaPath.concat([
areaPath[len - 2],
(draw.startY-draw.jianju).toFixed(0),
seal
]);
}
}else{
n !== 0 && path.push(L);
areaPath.push(L);
//尽管前方的老大数据是null 把后面包车型大巴那几个L去掉
if(n > 0 && data[n - 1] == null){
path.pop();
//尽管是第一个为null 不删除L
n!==1&&areaPath.pop();
}

var x = draw.startX draw.offset (n * draw.xPices),
y = draw.startY - ((data[n]) * (draw.yPices / draw.feed));
if(isIE){
x = parseInt(x);
y = parseInt(y);
}
path.push(x);
path.push(y);

if(areaPath[len - 1] === seal){
areaPath = areaPath.concat([
M,
x,
parseInt(draw.startY-draw.jianju),
L,
x,
y
]);
}else{
areaPath.push(x);
areaPath.push(y);
}

//如若是最终三个点
if(n === l - 1){

areaPath.push(x);

areaPath.push(parseInt(draw.startY-draw.jianju));
}

//画点
self.baseDraw('circle',{
x : x,
y : y,
r : 4,
fillColor : o.color
})
.attr({data:data[n]})
.on('mouseover',(function(o,x,y){
return function(){
hasSVG
? (this[0].setAttribute('r','5'),line.attr({'stroke-width':2.5}))
: (this[0].strokeWeight = 3,line[0].strokeWeight = 2.5);
self.showTooltip(o,x,y,this.attr('data'));
}

})(o,x,y))
.on('mouseout',function(){
hasSVG
? (this[0].setAttribute('r','4'),line.attr({'stroke-width':1.5}))
: (this[0].strokeWeight = 1,line[0].strokeWeight = 1.5);
self.hideTooltip()
})
.on('click',function(){areaGroup.toFront(); })
.css({zIndex:10,cursor:'pointer'})
.appendTo(areaGroup);

}
}

areaPath.push(seal)

self.baseDraw('path',{
border : 0,
isfill : true,
fillColor : o.color,
opacity : 0.5,
path : areaPath
})
.css({zIndex:5})
.appendTo(areaGroup);

line = self.baseDraw('path',{
border : 2.5,
borderColor : o.color,
isfill : false,
path : path
})
.on('mouseover',function(){
hasSVG
? this.attr({'stroke-width':2.5})
: (this[0].strokeWeight = 2.5);
})
.on('mouseout',function(){
hasSVG
? this.attr({'stroke-width':1.5})
: (this[0].strokeWeight = 1.5);
})
.on('click',function(){areaGroup.toFront(); })
.css({zIndex:-1})
.appendTo(areaGroup);
});
return this;
},
drawColumns : function(){
var self = this,
opts = this.opts,
draw = opts.draw,
chartData = opts.chartData,
dataLen = chartData.length,
//七个柱子之间的距离
columnSpace = 3,
//一个岗位中 全数的间隔之和
columnPadding = columnSpace * dataLen columnSpace,
//每一个柱子的上涨的幅度
columnSize = self.opts.charts.panel==='x'
? Number(((draw.xPices - columnPadding) / dataLen).toFixed(0))
: Number(((draw.yPices - columnPadding) / dataLen).toFixed(0));

each(chartData, function(i,o){
var data = o.data,
id = 'chart' i,
isX = opts.charts.panel==='x',
colGroup = self.group(id).appendTo(),
//每一个点起来的职务
start = self.opts.charts.panel==='x'
? draw.startX columnSpace i*(columnSize columnSpace)
: draw.startY columnSpace i*(columnSize columnSpace)

self.mainGroup[id] = {chart:colGroup,show:true};

for(var j = 0,l=data.length; j < l ; j ){
if(data[j]===null) continue;
//假如是股盘的整理子
if(isX){
var x = Number((start j *draw.xPices ).toFixed(0)),
y = Number((draw.startY).toFixed(0)),
height = Number((data[j] * (draw.yPices / draw.feed)).toFixed(0)),
path = [
M,
x,
y,
L,
x,
y -height,
L,
x columnSize,
y - height,
L,
x columnSize,
y,
seal
];
var pos = [x columnSize/2,data[j]>0?y-height:draw.startY];
}else{

var x = Number((draw.startX).toFixed(0)),
width = Number((data[j]*((draw.xPices / draw.feed))).toFixed(0)),
y = Number((start - (j 1) *draw.yPices ).toFixed(0)),
path = [
M,
x,
y,
L,
x width,
y ,
L,
x width,
y columnSize,
L,
x ,
y columnSize,
seal
];
var pos = [draw.startX width/2,y-columnSize];
}

self.baseDraw('path',{
border : 0,
isfill : true,
fillColor : o.color,
opacity : 1,
path : path
})
.attr({data:data[j]})
.css({zIndex:5,cursor:'pointer'})
.on('mouseover',(function(x,y,d){

return function(){

this.setOpacity(0.85);

self.showTooltip(o,x,y,this.attr('data'));
}

})(pos[0],pos[1],data[j])

)
.on('mouseout',(function(x,y){
return function(){
this.setOpacity(1);
self.hideTooltip();
}
})(x,y))
.appendTo(colGroup);

}
});
return this;
},
drawPie : function(){
var self = this,
opts = this.opts,
area = opts.area,
rx = area.centerX,
ry = area.centerY,
inc = 0,
total = 0,
data = [],
cumulative = -0.25, // start at top;
circ = 2 * Math.PI,
radiu = mathMin(opts.charts.radius,mathMin(area.areaWidth/2,area.areaHeight/2)),
fraction,
half_fraction;

each(opts.chartData,function(i,o){
typeof o.data ==='object'
? (data.push((function(o){
var all =0;
for(var i in o)
all =~~o[i]
return all
})(o.data)))
:data.push(mathAbs(o.data))

});

each(data,function(i,o){
total = total o;
});

each(data,function(i,o){
var pieGroup = self.group('chart' i).appendTo(),
s = inc/total*360,
e = (inc o)/total*360,
name = opts.chartData[i].name,
size = calTextLen(name),
dot = angle(radiu,[rx,ry],s (e-s)/2,2),
x = rx (dot[0]-rx)/2 - size.w/2,
y = ry (dot[1]-ry)/2 - size.h/2,
len = Math.sqrt((x-rx)*(x-rx) (y-ry)*(y-ry)),
moveDisplacement = ((x-rx)*8/len) ',' ((y-ry)*8/len);

inc = inc o;

var value = Number(o);
fraction = total ? value / total : 0;
half_fraction = total ? (value / 2) / total : 0;

var start = cumulative * circ;
half_cumulative = cumulative half_fraction;
cumulative = fraction;

var end = cumulative * circ;

self.baseDraw('pie',{
config : opts.chartData[i],
s : start,
e : end,
r : radiu,
innerR : 0
})
.css({zIndex:5,cursor:'pointer'})
.attr({move:moveDisplacement})
.on('mouseover',function(){
this.setOpacity(0.85);
})
.on('mouseout',function(){
this.setOpacity(1);
})
.on('click',function(){
var m = this.attr('move')
if(m.indexOf(' ')>0){
hasSVG
? this.attr({
transform: 'translate(0,0)'
})
: this.css({
left : '0px',
top : '0px'
})
this.attr({move:m.replace(' ','')});

}else{
var s= m.split(',');
hasSVG
? this.attr({
transform: 'translate(' m ')'
})
: this.css({
left : s[0] 'px',
top : s[1] 'px'
})

this.attr({move:m ' '});
}
})
.appendTo(pieGroup);

self.mainGroup['chart' i] = {chart:pieGroup,show:true};

self.baseDraw('span',{
x : x,
y : y,
fill : '#fff',
'text-anchor':'left'
})
.css({
fontFamily : 'Verdana,Arial,Helvetica,sans-serif',
fontSize : '12px',
position : 'absolute',
color : '#fff',
zIndex : 10
})
.addText(name)
.appendTo(pieGroup);
});

},
drawPies : function(){

var self = this,
opts = this.opts,
area = opts.area,
rx = area.centerX,
ry = area.centerY,
total = 0,
data = [],
chartData = opts.chartData,
cumulative = -0.25, // start at top;
circ = 2 * Math.PI,
radiu = mathMin(opts.charts.radius,mathMin(area.areaWidth/2,area.areaHeight/2)),
fraction,
half_cumulative,
half_fraction;

each(chartData,function(i,o){
each(o.data,function(j,d){
data[j]
? data[j] =mathAbs(d)
: data[j] =mathAbs(d)
});

});
//看有多少个数据来生成来生成内半径
var len = data.length,
innerSpace = radiu / 10;
Rpice = (radiu - innerSpace) / len,
piesGroup = this.group('pies').appendTo();

each(data,function(i,d){
var inc = 0 ;
if(d===0) return;
each(chartData,function(j,o){
if(~~o.data[i]===0)return;
var outR = radiu - Rpice * i,
innerR = radiu - Rpice * (i 1),
value = ~~o.data[i],
fraction = value / d;
half_fraction = (value/2)/d ,
start = cumulative * circ,
s = inc/d*360,
e = (inc value)/d*360;

inc = inc value;
var name = o.name,
size = calTextLen(name),
dot = angle(radiu,[rx,ry],s (e-s)/2,2),
px = dot[0]>rx?1:-1,
py = dot[1]>ry?1:-1;
var x = rx px*innerSpace ((dot[0]-rx-px*innerSpace)/len)*(len-i-1) ((dot[0]-rx-px*innerSpace)/len)/2- size.w/2,
y = ry py*innerSpace ((dot[1]-ry-py*innerSpace)/len)*(len-i-1) ((dot[1]-ry-py*innerSpace)/len)/2- size.h/2;

half_cumulative = cumulative half_fraction,
cumulative = fraction,
end = cumulative * circ;

self.baseDraw('pie',{
config : o,
s : start,
e : end,
r : outR,
innerR : innerR
})
.css({zIndex:5,cursor:'pointer'})
.on('mouseover',function(){
this.setOpacity(0.85);
})
.on('mouseout',function(){
this.setOpacity(1);
})
.appendTo(piesGroup);
self.baseDraw('span',{
x : x,
y : y,
fill : '#fff',
'text-anchor':'left'
})
.css({
fontFamily : 'Verdana,Arial,Helvetica,sans-serif',
fontSize : '12px',
position : 'absolute',
color : '#fff',
zIndex : 10
})
.addText(name)
.appendTo(piesGroup);

})
});

},
drawSegment : function(){
var self = this,
opts = this.opts,
draw = opts.draw,
chartData = opts.chartData,
columnPad = 5,
columnWidth = draw.xPices - columnPad * 2;

each(chartData,function(i,c){

});
},
baseDraw : function(type,config){
var self = this
arg = arguments;
return {
rect : function(){
var set = {};
set.rx = set.ry = config.arc*30 || 5;
set.width = config.width || 50;
set.height = config.height || 50;
set.fill = config.fill || '#fff';
set['fill-opacity'] = config.opacity || 0.85;
set['stroke-width'] = config.border || 2;
set.stroke = config.borderColor || '#606060';
set.transform = 'translate(' (config.left||0) ',' (config.top||0) ')';
return self.createElement('rect')
.attr(set)

},
text : function(){
return self.createElement('text')
.attr(config)
},
span : function(){
var elem= self.createElement('text')
.attr(config)
.attr({
y : config.y (arg[2]||15)
})
return elem;
},
path : function(){
var set = {};
set['stroke-width'] = config.border;
set.stroke = config.borderColor || '#C0C0C0';
set.fill = config.isfill?config.fillColor:'none';
set.d = config.path;
config.opacity
&&(set['fill-opacity'] = config.opacity);

return self.createElement('path')
.attr(set);
},
circle : function(){
var set = {};
set.cx = config.x;
set.cy = config.y;
set.r = config.r;
set.fill = config.fillColor;
return self.createElement('circle')
.attr(set);
},
pie : function(){
//config,s,e,r,index
var opts = self.opts,
s = config.s,
r = config.r,
e = config.e - 0.000001,
id = 'chart' config.index,
area = opts.area,
rx = area.centerX,
ry = area.centerY,
cosStart = mathCos(s),
sinStart = mathSin(s),
cosEnd = mathCos(e),
sinEnd = mathSin(e),
color = config.config.color,
innerR = config.innerR,
longArc = e - s < Math.PI ? 0 : 1,
path = [
M,
rx r * cosStart,
ry r * sinStart,
'A',
r,
r,
0,
longArc,
1,
rx r * cosEnd,
ry r * sinEnd,
L,
rx innerR * cosEnd,
ry innerR * sinEnd,
'A', // arcTo
innerR, // x radius
innerR, // y radius
0, // slanting
longArc, // long or short arc
0, // clockwise
rx innerR * cosStart,
ry innerR * sinStart,
'Z'
];

return self.baseDraw('path',{
border : 1,
border : '#fff',
isfill : true,
fillColor : color,
opacity : 1,
path : path

})

}
}[type]();
}
};

//---------------------------------------------------------------------------------------------------
//如若是vml 修改smipleChart.prototype中的一些主意
!hasSVG
&&extend(smipleChart.prototype,{
baseDraw : function(type,config){
var self = this,
width = this.width,
height = this.height,
name = arguments[2];
return {
rect : function(){
var attr = {},
css = {};
attr.arcsize = config.arc || 0.2 '';
if(config.fill==='none'){
attr.filled = 'f'
}else{
attr.filled = 't';
attr.fillcolor = config.fill || '#fff';
}

attr.strokeWeight = config.border || 2;
attr.strokeColor = config.borderColor || '#606060';
css.width = config.width || 50 'px';
css.height = config.height || 50 'px';
css.zIndex = 10;
css.left = config.left||0 'px';
css.top = config.top ||0 'px';

return self.createElement('roundrect')
.attr(attr)
.css(css)
},
text : function(){
return self.createElement('TextBox')
.attr({inset : "2px,2px,2px,2px" })
},
span : function(){
return self.createElement('span').
css({
position:'absolute',
left : config.x 'px',
top : config.y 'px'
})
},
path : function(){
var attr = {},
css = {
width : width 'px',
height : height 'px'
};

if(config.border===0){
attr.Stroked = 'f';
attr.strokeWeight =0;
}else{
attr.strokeWeight = config.border||1 ;
}
attr.strokeColor = config.borderColor || "#C0C0C0";
attr.filled = config.isfill?'t':'f';
attr.filled==='t'
&&(attr.fillcolor=config.fillColor||"#C0C0C0");
attr.coordsize = width ',' height;
attr.path = config.path;
var elem = self.createElement()
.attr(attr)
.css(css);
if(config.opacity){
var fill = self.createElement('fill')
.attr({
type : 'fill',
color : config.fillColor||"#C0C0C0",
opacity : config.opacity
})
.appendTo(elem);
//那那个目的的四个属性援用设置透明的因素 现在会用到
elem.opacity = fill[0];
}
return elem;

},
circle : function(){
var attr ={
strokeWeight : 1,
coordsize : width ',' height,
filled : 't'
},
css ={
width : width 'px',
height : height 'px'
}
x = config.x,
y = config.y,
r = config.r;
attr.strokeColor=attr.fillcolor = config.fillColor

attr.path =[
'wa', // clockwisearcto
x - r, // left
y - r, // top
x r, // right
y r, // bottom
x r, // start x
y, // start y
x r, // end x
y, // end y
'e' // close
];
return self.createElement()
.attr(attr)
.css(css)
},
pie : function(){
////config,s,e,r,index

var opts = self.opts,
area = opts.area,
r = config.r,
rx = area.centerX,
ry = area.centerY,
innerR= config.innerR||0,
sDot = angle(r,[rx,ry],s,2),
eDot = angle(r,[rx,ry],e,2),
color = config.config.color,
s = config.s,
e = config.e,
e = e - s == 2 * Math.PI ? e - 0.001 : e,
cosStart = mathCos(s),
sinStart = mathSin(s),
cosEnd = mathCos(e),
sinEnd = mathSin(e),

path = [
'wa', // clockwisearcto
(rx - r).toFixed(0), // left
(ry - r).toFixed(0), // top
(rx r).toFixed(0), // right
(ry r).toFixed(0), // bottom
(rx r * cosStart).toFixed(0), // start x
(ry r * sinStart).toFixed(0), // start y
(rx r * cosEnd).toFixed(0), // end x
(ry r * sinEnd).toFixed(0), // end y

'at', // clockwisearcto
(rx - innerR).toFixed(0), // left
(ry - innerR).toFixed(0), // top
(rx innerR).toFixed(0), // right
(ry innerR).toFixed(0), // bottom
(rx innerR * cosEnd).toFixed(0), // start x
(ry innerR * sinEnd).toFixed(0), // start y
(rx innerR * cosStart).toFixed(0), // end x
(ry innerR * sinStart).toFixed(0), // end y

'x', // finish path
'e' // close
];

return self.baseDraw('path',{
border : 1,
border : '#fff',
isfill : true,
fillColor : color,
opacity : 1,
path : path
})

}
}[type]();
}
});

//---------------------------------------------------------------------------------------------------
})(document);

window.onload = function(){
var config = {
charts : {
type : 'line',
radius : 150,
panel : 'x',
style: {
fontFamily: '"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif', // default font
fontSize: '12px'
}
},
title : {
text : '线性Logo' ,
y : 10,
style : {
color: 'black',
fontSize: '16px'
}
},
subTitle : {
text : '线性Logo副标题',
y : 35,
style: {
color: '#111',
fontSize: '12px'
}
},
legend : {
enable : true,
//type : 'lateral', // lateral 横向 或 lengthwise 纵向
type : 'lateral',
pos : [10,10],
style:{
fontFamily: '"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif', // default font
fontSize: '12px',
magin:'0px'
}
},
yUnit : {
text : '线性Logo侧题目',
x : 20,
style: {
color : '#111',
fontSize : '12px'
}
},
xUnit : {
units: [
'一月',
'二月',
'三月',
'四月',
'五月',
'六月',
'七月',
'八月',
'九月',
'十月',
'十一月',
'十二月'
]
},
chartData : [
{

name : 'xcv',
color : '#4572A7',
data : [-18,45,-38,29,95,-45,77]
}, {

name: 'frfr',
color: '#AA4643',
data: [-44,12,78,-100,13,4,-56,-34]
}, {
name: 'AAAAA',
color: '#89A54E',

data: [null,78,83,null,22,-78,2,44,78]
}, {
name: 'BBBB',
color: '#80699B',
data: [null, 58, 35, null, 52, 47, 26, -55, 39, 123,15,66]
}
]
};

new smipleChart($('line'),config);
config.charts.type ='area';
config.title.text ='区域Logo'
config.subTitle.text='区域图标副标题'
config.yUnit.text ='区域Logo侧标题'

new smipleChart($('area'),config);
config.title.text ='柱状Logo'
config.subTitle.text='柱状Logo副标题'
config.yUnit.text ='柱状Logo侧题目'
config.charts.type ='columns';
config.chartData =[
{

name : 'xcv',
color : '#4572A7',

data : [-0.01,-0.62,0,0.55,null,0.78,-0.63,-0.82,null,null,0.33]
}, {

name: 'frfr',
color: '#AA4643',
data: [-0.22,0.82,0.55,1.32,0.33,0.95,null,1,0.65,null,0.78]
}, {
name: 'AAAAA',
color: '#89A54E',

data: [null,0.62,0.34,null,0.63,0,-0.23,-1,0.62,0.45,null,-0.56]
}
]

new smipleChart($('zhu'),config);
config.charts.panel='y'
new smipleChart($('zhu1'),config);
config.charts.type ='pie';
config.title.text ='饼图Logo'
config.subTitle.text='饼图Logo副标题'
config.yUnit.text =''
config.legend.type='lengthwise';
config.chartData =[
{

name : 'aaa',
color : '#4572A7',

data : [433,123,null,66]
}, {

name: 'bbb',
color: '#AA4643',
data: [45,33,33,511]
}, {
name: 'ccc',
color: '#89A54E',

data: [55,null,75,333]
}
]
config.legend.pos= [680,30]
new smipleChart($('pie'),config);
config.charts.type ='pies';
config.title.text ='多层饼图Logo'
config.subTitle.text='多层饼图Logo副标题'
config.legend.type='lateral';
config.legend.pos= [330,400]
new smipleChart($('pies'),config);

config.chartData =[
{

name : 'xcv',
color : '#4572A7',

data : [433,355,275,null,588,323,576,32,99]
}, {

name: 'frfr',
color: '#AA4643',
data: [45,666,100,null,677,56,88,633,55,64]
}, {
name: 'AAAAA',
color: '#89A54E',

data: [55,162,75,null,364,0,637,112,163,615]
}
]
config.yUnit.lineNum = 2;
config.title.text ='比不大的'
config.subTitle.text='只设置了2条线'
config.yUnit.text ='小测标题' ;

config.charts.type ='line';
config.legend.pos= [10,10]
new smipleChart($('vv'),config);
config.yUnit.lineNum = 10;
config.charts.panel = 'x';
config.charts.type ='segment';
//new smipleChart($('segment'),config);

}
</script>
</body>
</html>

复制代码 代码如下: !DOCTYPE html PUBLIC "-//W3C//DTD X...

本文由澳门新萄京官方网站发布于澳门新萄京赌场网址,转载请注明出处:简单来说Logo类,折线图数据绑定难题

关键词: