/* * 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) } } }) } })()