/*
* ECharts3图表
* 作者:江鸿宾(QQ33080907)
* 最近修改:2017.07.01
* 本插件只用于作者参与的项目,未经许可请勿转载
*/
/*
需在
内部引入(echarts.common和echarts选其一):
*/
/*
如果网页导出为Word文档,需要预先用以下代码把Canvas渲染为图片
$('div.chart[_echarts_instance_]').each(function () {
$(this).width(550);
var mychart = echarts.getInstanceByDom(this);
mychart.resize();
mychart.setOption({ toolbox: { show: false } });
$(this).removeAttr('_echarts_instance_').html('
');
});
*/
(function () {
'use strict'
// 获取url
var $script = $('script').last()
var src = $script.attr('src')
// 获取参数
var c = src.match(/[?&]c=([^&]+)/) // 统计图类型,默认为折线图(line),其他为平滑曲线图(spline)、柱状图(column)、条形图(bar)、饼图(pie)、漏斗图(funnel)、地图(map),阶梯折线(step)
var s = src.match(/[?&]s=([^&]+)/) // 是否堆叠,默认不堆叠,只有折线图(line)、柱状图(column)、条形图(bar)能够使用堆叠方式,堆叠传入1,不堆叠传入0或留空
var t = src.match(/[?&]t=([^&]+)/) // 标题
var w = src.match(/[?&]w=([^&]+)/) // 宽度,默认100%
var h = src.match(/[?&]h=([^&]+)/) // 高度,默认400px
var x = src.match(/[?&]x=([^&]+)/) // 项目,逗号或竖线分割
var r = src.match(/[?&]r=([^&]+)/) // x轴标签旋转角度,默认0为不旋转,bar类型不支持
var v = src.match(/[?&]v=([^&]+)/) // 单序列采用值(与项目对应,逗号或竖线分割),多序列采用json数据(含首尾方括号,键/值必须用单/双引号包括,例如:v=[{'name':'你','data':[1,2]},{'name':'我','data':[2,3]}],数值之间可以用竖线或逗号)。注意:pie/funnel/map类型不支持多序列
var p = src.match(/[?&]p=([^&]+)/) // 渲染类型,默认canvas,图片传入1,不是图片传入0或留空
var l = src.match(/[?&]l=([^&]+)/) // 是否显示数字标签,默认显示,不显示传入0
var o = src.match(/[?&]o=([^&]+)/) // 颜色序列,用竖线或逗号分割,需要#开头,不传则用主题色
var d = src.match(/[?&]d=([^&]+)/) // 地图地区,省级传入拼音或汉字,市级传入汉字,默认为china,省地图:http://echarts.baidu.com/download-map.html,市地图:http://ecomfe.github.io/echarts-map-tool/
var z = src.match(/[?&]z=([^&]+)/) // 主题名称,默认为macarons,可参考:http://echarts.baidu.com/download-theme.html
var m = src.match(/[?&]m=([^&]+)/) // 是否标记最大值,标记传入1,默认0不标记,只有折线图和柱状图支持
// 处理参数
if (c === null || c.length < 1) { c = 'line' } else { c = c[1] }
if (s === null || s.length < 1) { s = false } else { s = s[1] === '1' }
if (t === null || t.length < 1) { t = '' } else { t = t[1] }
if (w === null || w.length < 1) { w = '100%' } else { w = w[1] + 'px' }
if (h === null || h.length < 1) { h = 400 } else { h = h[1] }
if (x === null || x.length < 1) { x = '' } else { x = x[1] }
if (r === null || r.length < 1) { r = 0 } else { r = r[1] }
if (v === null || v.length < 1) { v = '' } else { v = v[1] }
if (p === null || p.length < 1) { p = false } else { p = p[1] === '1' }
if (l === null || l.length < 1) { l = true } else { l = !(l[1] === '0') }
if (o === null || o.length < 1) { o = '' } else { o = o[1] }
if (d === null || d.length < 1) { d = 'china' } else { d = d[1] }
if (z === null || z.length < 1) { z = 'macarons' } else { z = z[1] }
if (m === null || m.length < 1) { m = false } else { m = m[1] === '1' }
// 有时避免查询字符串过长,采用隐藏表单传值
if (x === '') { x = $script.prevAll('input.x').first().val() }
if (v === '') { v = $script.prevAll('input.v').first().val() }
if (typeof (x) === 'undefined' || x === '') { x = $('#x').val() }
if (typeof (v) === 'undefined' || v === '') { v = $('#v').val() }
// 如果没有x数据,则什么都不做
if (typeof (x) === 'undefined' || x === '') { return }
// 创建容器
var rnd = Math.random().toString().substring(2, 8)
var div = ''
$script.after(div).remove()
var option = {}
var json = ''
var legend = null
var maxvalue = 0.0
var minvalue = 0.0
var MaxMin = 0
var i = 0
var j = 0
var MapPY = ''
var MapHZ = ''
// 图表标题
if (t === '') { option = { title: { show: false } } }
else { option = { title: { text: t } } }
// 颜色序列
if (o !== '') {
o = $.parseJSON('["' + o.replace(/\|/g, ',').replace(/,/g, '","') + '"]')
$.extend(true, option, { color: o })
}
// 饼图或漏斗图
if (c === 'pie' || c === 'funnel') {
$.extend(true, option, {
tooltip: { confine: true },
toolbox: { feature: { dataView: {}, restore: {}, saveAsImage: {} } },
series: {
type: c,
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
})
// 处理项目、数据
x = x.replace(/\|/g, ',').split(',')
v = v.replace(/\|/g, ',').split(',')
// 处理数据和图例(丢弃0值),j为数据之和
legend = ''
j = 0
for (i = 0; i < x.length; i++) {
v[i] = Number(v[i])
if (v[i] > 0) {
legend += ',"' + x[i] + '"'
json += ',{"name":"' + x[i] + '","value":' + v[i] + '}'
j += v[i]
}
}
legend = $.parseJSON('[' + legend.substring(1) + ']')
json = $.parseJSON('[' + json.substring(1) + ']')
// 饼图或者漏斗图不同的配置
if (c === 'pie') {
$.extend(true, option, {
tooltip: { formatter: '{b}:{c} ({d}%)' },
legend: { orient: 'vertical', left: 'right', top: 'middle' },
series: {
radius: [0, '70%'],
label: { normal: { formatter: '{b}:{c} ({d}%)' } }
}
})
} else if (c === 'funnel') {
$.extend(true, option, {
tooltip: { formatter: function (params) { return params.name + ':' + params.value + ' (' + (params.value / j * 100).toFixed(2) + '%)' } },
legend: { left: 'center', top: 'bottom' },
series: {
label: { normal: { formatter: function (params) { return params.name + ':' + params.value + ' (' + (params.value / j * 100).toFixed(2) + '%)' } } }
}
})
}
// 合并选项
$.extend(true, option, {
legend: { data: legend },
series: { data: json }
})
}
// 结束:饼图或漏斗图
// 地图
else if (c === 'map') {
$.extend(true, option, {
tooltip: { formatter: '{b}:{c}' },
toolbox: { feature: { dataView: {}, restore: {}, saveAsImage: {} } },
visualMap: { left: 'right', top: 'middle', calculable: true },
series: {
type: 'map',
roam: true,
scaleLimit: { min: 1, max: 2 },
label: { normal: { show: true }, emphasis: { show: true } }
}
})
// 处理省市拼音和汉字对应
var provinces = ['shanghai', 'hebei', 'shanxi', 'neimenggu', 'liaoning', 'jilin', 'heilongjiang', 'jiangsu', 'zhejiang', 'anhui', 'fujian', 'jiangxi', 'shandong', 'henan', 'hubei', 'hunan', 'guangdong', 'guangxi', 'hainan', 'sichuan', 'guizhou', 'yunnan', 'xizang', 'shanxi1', 'gansu', 'qinghai', 'ningxia', 'xinjiang', 'beijing', 'tianjin', 'chongqing', 'xianggang', 'aomen']
var provincesText = ['上海', '河北', '山西', '内蒙古', '辽宁', '吉林', '黑龙江', '江苏', '浙江', '安徽', '福建', '江西', '山东', '河南', '湖北', '湖南', '广东', '广西', '海南', '四川', '贵州', '云南', '西藏', '陕西', '甘肃', '青海', '宁夏', '新疆', '北京', '天津', '重庆', '香港', '澳门']
for (i = 0; i < provinces.length; i++) {
if (provinces[i] === d || provincesText[i] === d) {
MapPY = provinces[i]
MapHZ = provincesText[i]
break
}
}
// 如果不是省份地图则取传入值
if (MapPY === '') {
MapPY = d
MapHZ = d
}
// 处理数据,
x = x.replace(/\|/g, ',').split(',')
v = v.replace(/\|/g, ',').split(',')
// 处理省份名称
for (i = 0; i < x.length; i++) {
for (j = 0; j < provincesText.length; j++) {
if (x[i].indexOf(provincesText[j]) === 0) {
x[i] = provincesText[j]
break
}
}
}
// 小数前面是点的加一个零,获取序列中的最大值、最小值
minvalue = v[0]
for (i = 0; i < v.length; i++) {
if (i > 0) { json += ',' }
if (v[i].indexOf('.') === 0) { v[i] = '0' + v[i] }
if (v[i].indexOf('-.') === 0) { v[i] = '-0' + v[i].substring(1) }
if (Number(v[i]) > maxvalue) { maxvalue = v[i] }
if (Number(v[i]) < minvalue) { minvalue = v[i] }
json += '{"name":"' + x[i] + '","value":' + v[i] + '}'
}
json = $.parseJSON('[' + json + ']')
// 工具箱位置
if (t === '') { $.extend(true, option, { toolbox: { orient: 'vertical', left: 'right' } }) }
// 合并选项
$.extend(true, option, {
visualMap: { min: Number(minvalue), max: maxvalue },
series: {
map: MapHZ,
data: json
}
})
}
// 结束:地图
// 其他图表类型,只支持:折线图(line)、平滑曲线图(spline)、柱状图(column)、条形图(bar)、阶梯折线(step)
else {
// 图表类型
var type = c
if (c === 'column') { type = 'bar' } else if (c === 'spline' || c === 'step') { type = 'line' }
$.extend(true, option, {
// 网格
grid: { left: 'left', right: 0, containLabel: true },
// 鼠标提示触发类型,默认item触发
tooltip: {
trigger: 'axis',
backgroundColor: 'rgba(255,255,255,0.7)',
borderWidth: 1,
borderColor: '#48b',
textStyle: { color: '#000' }
},
toolbox: { feature: { dataView: {}, magicType: {}, restore: {}, saveAsImage: {} } }
})
// 处理x轴数据
x = $.parseJSON('["' + x.replace(/\|/g, ',').replace(/,/g, '","') + '"]')
// 处理y轴数据
v = v.replace(/\|/g, ',').replace(/'/g, '"')
// 坐标轴
// scale:脱离0值,即不用从0开始,自动分配y轴区间,默认false从0开始
// bar图:xy轴对调,y轴类目排列顺序反向
if (c === 'bar') {
$.extend(true, option, {
xAxis: { type: 'value', scale: true, minInterval: 1 },
yAxis: { type: 'category', data: x, inverse: true, axisLabel: { interval: 0 } }
})
}
else {
$.extend(true, option, {
xAxis: { type: 'category', data: x, axisLabel: { interval: 0, rotate: r } },
yAxis: { type: 'value', scale: true, minInterval: 1 }
})
}
// 处理工具提示bar和column为shadow,默认为直线(line)
if (c === 'bar' || c === 'column') { $.extend(true, option, { tooltip: { axisPointer: { type: 'shadow' } } }) }
// 多序列
if (v.indexOf('{') >= 0 || v.indexOf('[') >= 0) {
legend = []
json = $.parseJSON(v)
// 把数据中多余x个数的数据丢弃,获取最大值最小值
minvalue = json[0].data[0]
$.each(json, function (i, v) {
var tmpMin, tmpMax
v.data = v.data.slice(0, x.length)
// 只有ES6才支持展开运算符
// tmp_min=Math.min(...(v.data));
// tmp_max=Math.max(...(v.data));
tmpMin = Math.min.apply(null, v.data)
tmpMax = Math.max.apply(null, v.data)
if (tmpMin < minvalue) { minvalue = tmpMin }
if (tmpMax > maxvalue) { maxvalue = tmpMax }
})
// console.log(minvalue+'/'+maxvalue);
// 需要对每个序列(series)追加的属性
var item_ex = {
type: type,
smooth: c === 'spline',
step: c === 'step' ? 'middle' : false
}
// 是否显示数据标签
if (l) { $.extend(true, item_ex, { label: { normal: { show: true } } }) }
// 处理堆叠、数据标签位置
if (c === 'bar' && s) { $.extend(true, item_ex, { stack: '总量' }) }
else if (c === 'bar' && l) { $.extend(true, item_ex, { label: { normal: { position: 'right' } } }) }
else if (c === 'column' && l) { $.extend(true, item_ex, { label: { normal: { position: 'top' } } }) }
// 标最大值
if (m) { $.extend(true, item_ex, { markPoint: { data: [{ name: '最大值', type: 'max' }] } }) }
// 从序列中检索legend项,且追加属性
$.each(json, function (index, item) {
legend.push(item.name)
$.extend(item, item_ex)
})
// 合并选项(多序列增加堆叠和平铺工具箱按钮)
$.extend(true, option, {
toolbox: { feature: { magicType: { type: ['line', 'bar', 'stack', 'tiled'] } } },
legend: { data: legend, top: 'bottom' },
series: json
})
}
// 结束:多序列
// 单序列
else {
v = v.split(',')
// 小数前面是点的加一个零,获取序列中的最大值、最小值
minvalue = v[0]
for (i = 0; i < v.length; i++) {
if (v[i].indexOf('.') === 0) { v[i] = '0' + v[i] }
if (v[i].indexOf('-.') === 0) { v[i] = '-0' + v[i].substring(1) }
if (Number(v[i]) > maxvalue) { maxvalue = v[i] }
if (Number(v[i]) < minvalue) { minvalue = v[i] }
}
$.extend(true, option, {
grid: { bottom: 0 },
toolbox: { feature: { magicType: { type: ['line', 'bar'] } } },
tooltip: { formatter: '{b}:{c}' },
// 图例默认显示
legend: { show: false },
series: {
type: type,
smooth: c === 'spline',
step: c === 'step' ? 'middle' : false,
data: v.slice(0, x.length)
}
})
// 是否显示数据标签
if (l) { $.extend(true, option, { label: { normal: { show: true } } }) }
// 处理数据标签位置
if (c === 'bar' && l) { $.extend(true, option, { series: { label: { normal: { position: 'right' } } } }) }
else if (c === 'column' && l) { $.extend(true, option, { series: { label: { normal: { position: 'top' } } } }) }
// 标最大值
if (m) { $.extend(true, option, { series: { markPoint: { data: [{ name: '最大值', type: 'max' }] } } }) }
}
// 结束:单序列
// 最小值向下取整,最大值向上取整
minvalue = Math.floor(minvalue)
maxvalue = Math.ceil(maxvalue)
// console.log(minvalue+'/'+maxvalue);
if (c === 'bar') {
$.extend(true, option, { grid: { right: 30 } })
if (!s) { $.extend(true, option, { xAxis: { min: minvalue, max: maxvalue } }) }
}
// else { $.extend(true, option, { yAxis: { min: minvalue, max: maxvalue } }); }
// 处理y轴刻度分段数量
MaxMin = maxvalue - minvalue
if (MaxMin <= 5) {
if (c === 'bar') { $.extend(true, option, { xAxis: { splitNumber: MaxMin } }) }
else { $.extend(true, option, { yAxis: { splitNumber: MaxMin } }) }
}
}
// 结束:其它类型图表
// 绘制地图
if (c === 'map') {
var mapurl = ''
// 全国
if (d === 'china') { mapurl = '//echarts.baidu.com/asset/map/js/china.js' }
// 省
else if (MapPY !== MapHZ) { mapurl = '//echarts.baidu.com/asset/map/js/province/' + MapPY + '.js' }
// 市
else { mapurl = '/Scripts/map/' + MapHZ + '.js' }
$.ajax(mapurl, {
dataType: 'script',
cache: true,
success: function () { drawchart() }
})
}
// 绘制其他图表
else { drawchart() }
// 绘制
function drawchart() {
$.ajax('/Scripts/echarts/theme/' + z + '.js', {
dataType: 'script',
cache: true,
success: function () {
var mychart = echarts.init(document.getElementById('chart-' + rnd), z)
// console.log(JSON.stringify(option, null, 2));
if (p) {
$.extend(true, option, {
animation: false,
toolbox: { show: false }
})
mychart.setOption(option)
$('#chart-' + rnd).html('
')
} else { mychart.setOption(option) }
}
})
}
})()