| var $chart = $('#cheat-chart'); |
| var width = $chart.width(); |
| var heightRatio = width > 400 ? 0.5 : 1.5; |
| var height = width * heightRatio; |
| var maxWidth = 848; |
| $chart.height(height); |
| |
| var highlightFill = 'rgba(132, 181, 228, 0.5)'; |
| |
| var grid = { |
| left: 60, |
| top: 100, |
| bottom: 70, |
| right: 100 |
| }; |
| grid.width = width - grid.left - grid.right; |
| grid.height = height - grid.top - grid.bottom; |
| |
| var xScale = grid.width / (maxWidth - grid.left - grid.right); |
| var yScale = grid.height / (maxWidth * heightRatio - grid.top - grid.bottom); |
| |
| var chart; |
| var option; |
| |
| var $detail = $('#cheat-detail'); |
| |
| var selectedRegion = null; |
| $(window).click(function (e) { |
| // When click outside of chart or detail area, cancel selection |
| if (e.target !== $('#cheat-chart canvas')[0] |
| && $(e.target).closest($('#cheat-detail')).length < 1 |
| ) { |
| selectedRegion = null; |
| _doUnhighlight(option.graphic.elements, true); |
| chart.setOption(option); |
| } |
| }); |
| |
| var baseOption = { |
| title: { |
| text: '图表的标题', |
| left: 5, |
| top: 5 |
| }, |
| tooltip: { |
| trigger: 'axis', |
| axisPointer: { |
| type: 'cross' |
| }, |
| silent: true, |
| renderMode: 'richText' |
| }, |
| toolbox: { |
| right: 15, |
| top: 5, |
| feature: { |
| dataView: { |
| show: true, |
| readOnly: false |
| }, |
| magicType: { |
| show: true, |
| type: ['line', 'bar'] |
| }, |
| restore: { |
| show: true |
| }, |
| saveAsImage: { |
| show: true |
| } |
| } |
| }, |
| visualMap: { |
| inRange: { |
| symbolSize: [5, 20], |
| color: ['#2F4554', '#C23431'] |
| }, |
| min: 0, |
| max: 25, |
| seriesIndex: 2, |
| left: 80, |
| top: 80, |
| itemWidth: 20, |
| itemHeight: 80, |
| calculable: true |
| }, |
| dataZoom: { |
| type: 'slider', |
| show: true, |
| yAxisIndex: 1 |
| }, |
| legend: { |
| data: ['蒸发量', '降水量', '平均温度'], |
| top: 35, |
| left: 5 |
| }, |
| grid: grid, |
| xAxis: [{ |
| type: 'category', |
| data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'] |
| }], |
| yAxis: [{ |
| type: 'value', |
| name: '水量', |
| min: 0, |
| max: 250, |
| interval: 50, |
| axisLabel: { |
| formatter: '{value} ml' |
| } |
| }, |
| { |
| type: 'value', |
| name: '温度', |
| min: 0, |
| max: 25, |
| interval: 5, |
| axisLabel: { |
| formatter: '{value} °C' |
| } |
| } |
| ], |
| series: [{ |
| name: '蒸发量', |
| type: 'bar', |
| data: [2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3], |
| silent: true |
| }, |
| { |
| name: '降水量', |
| type: 'bar', |
| data: [2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3], |
| silent: true |
| }, |
| { |
| name: '平均温度', |
| type: 'line', |
| yAxisIndex: 1, |
| data: [2.0, 2.2, 3.3, 5, 6.3, 10.2, 20.3, 23.4, 23.0, 16.5, 12.0, 6.2], |
| silent: true, |
| symbol: 'circle', |
| markPoint: { |
| data: [{ |
| coord: ['4月', 5], |
| value: '5℃' |
| }] |
| } |
| } |
| ], |
| graphic: { |
| elements: [{ |
| type: 'sector', |
| position: [220, 140], |
| shape: { |
| r: 50, |
| r0: 20, |
| cx: 0, |
| cy: 0, |
| startAngle: 0, |
| endAngle: Math.PI * 1.2 |
| }, |
| style: { |
| fill: '#C23431' |
| } |
| }, { |
| type: 'text', |
| position: [210, 120], |
| style: { |
| text: '绘制图形和文字', |
| fill: '#2F4554', |
| font: '14px Arial' |
| } |
| }] |
| }, |
| timeline: { |
| data: [ |
| '2010', '2011', '2012', '2013', '2014', '2015', '2016' |
| ], |
| axisType: 'category', |
| show: true, |
| autoPlay: false |
| } |
| }; |
| |
| var baseActions = [{ |
| type: 'showTip', |
| seriesIndex: 0, |
| dataIndex: 7, |
| position: [width * 0.65, height * 0.45] |
| }]; |
| |
| var regions = [{ |
| left: grid.left, |
| top: grid.top, |
| width: grid.width, |
| height: grid.height, |
| option: { |
| id: 'grid', |
| desc: '直角坐标系内绘图区域' |
| } |
| }, { |
| group: (function () { |
| var group = []; |
| for (var i = 0; i < 12; ++i) { |
| group.push({ |
| left: grid.left + grid.width / 12 * (i + 0.05), |
| bottom: grid.bottom, |
| width: grid.width / 12 * 0.9, |
| height: grid.height / 25 * baseOption.series[2].data[i] + 10 |
| }); |
| } |
| return group; |
| })(), |
| option: { |
| id: 'series.itemStyle', |
| desc: '系列的图形样式,对不同类型的图表有不同的意义。\n对折线图而言,这个配置项用于设置拐点处图形的样式;对柱状图而言,用于设置柱子的样式。该配置项是对整个系列的图形做设置,如果要对其中的某一个特定数据点做设置,应使用 <a href="option.html#series-line.data.itemStyle" target="_blank"><code>series.data.itemStyle</code></a>。' |
| } |
| }, { |
| left: 10, |
| top: 5, |
| width: 100, |
| height: 24, |
| option: { |
| id: 'title', |
| desc: '图表的标题' |
| } |
| }, { |
| left: 10, |
| top: 35, |
| width: 238, |
| height: 24, |
| option: { |
| id: 'legend', |
| desc: '图例,展现了不同系列的标记、颜色和名字' |
| } |
| }, { |
| right: 15, |
| top: 5, |
| width: 133, |
| height: 29, |
| option: { |
| id: 'toolbox', |
| desc: '工具栏,提供操作图表的工具,可自定义' |
| } |
| }, { |
| left: 5, |
| top: grid.top - 35, |
| width: 70, |
| height: grid.height + 40, |
| option: { |
| id: 'yAxis', |
| desc: '直角坐标系 grid 中的 y 轴' |
| } |
| }, { |
| left: grid.left - 3, |
| top: grid.top, |
| width: 6, |
| height: grid.height, |
| option: { |
| id: 'yAxis.axisLine', |
| desc: 'y 轴轴线' |
| } |
| }, { |
| left: grid.left + grid.width - 15, |
| top: grid.top - 35, |
| width: 60, |
| height: grid.height + 40, |
| option: { |
| id: 'yAxis', |
| desc: '直角坐标系 grid 中的 y 轴;第二个 y 轴默认显示在右边' |
| } |
| }, { |
| left: grid.width + grid.left - 3, |
| top: grid.top, |
| width: 6, |
| height: grid.height, |
| option: { |
| id: 'yAxis.axisLine', |
| desc: 'y 轴轴线' |
| } |
| }, { |
| group: [{ |
| left: grid.left + grid.width - 20, |
| top: grid.top - 30, |
| width: 40, |
| height: 20 |
| }, { |
| left: 38, |
| top: grid.top - 30, |
| width: 40, |
| height: 20 |
| }], |
| option: { |
| id: 'yAxis.name', |
| desc: 'y 轴名称,可以通过<code>nameLocation</code>改变位置' |
| } |
| }, { |
| group: (function () { |
| var group = []; |
| for (var i = 0; i < 6; ++i) { |
| group.push({ |
| left: 11, |
| top: grid.top + grid.height / 5 * i - 9, |
| width: 42, |
| height: 18 |
| }); |
| } |
| for (var i = 0; i < 6; ++i) { |
| group.push({ |
| left: grid.left + grid.width, |
| top: grid.top + grid.height / 5 * i - 9, |
| width: 42, |
| height: 18 |
| }); |
| } |
| return group; |
| })(), |
| option: { |
| id: 'yAxis.axisLabel', |
| desc: '坐标轴刻度标签' |
| } |
| }, { |
| group: (function () { |
| var group = []; |
| for (var i = 0; i < 5; ++i) { |
| group.push({ |
| left: grid.left, |
| top: grid.top + grid.height / 5 * i - 3, |
| width: width - grid.left - grid.right, |
| height: 6 |
| }); |
| } |
| return group; |
| })(), |
| option: { |
| id: 'yAxis.splitLine', |
| desc: '坐标轴分割线,除此之外,还有 <code>splitArea</code> 设置背景色分割' |
| } |
| }, { |
| group: (function () { |
| var group = []; |
| for (var i = 0; i < 6; ++i) { |
| group.push({ |
| left: 50, |
| top: grid.top + grid.height / 5 * i - 5, |
| width: 10, |
| height: 10 |
| }); |
| } |
| for (var i = 0; i < 6; ++i) { |
| group.push({ |
| left: grid.left + grid.width, |
| top: grid.top + grid.height / 5 * i - 5, |
| width: 10, |
| height: 10 |
| }); |
| } |
| return group; |
| })(), |
| option: { |
| id: 'yAxis.axisTick', |
| desc: '坐标轴刻度' |
| } |
| }, { |
| left: grid.left, |
| bottom: grid.bottom - 3, |
| width: grid.width, |
| height: 6, |
| option: { |
| id: 'xAxis', |
| desc: '直角坐标系 grid 中的 x 轴' |
| } |
| }, { |
| left: grid.left, |
| bottom: grid.bottom - 3, |
| width: grid.width, |
| height: 6, |
| option: { |
| id: 'xAxis.axisLine', |
| desc: 'x 轴轴线' |
| } |
| }, { |
| group: (function () { |
| var group = []; |
| for (var i = 0; i < 12; ++i) { |
| group.push({ |
| left: grid.left + grid.width * (i + 0.5) / 12 - 20 * xScale, |
| bottom: grid.bottom - 25, |
| width: 40 * xScale, |
| height: 20 |
| }); |
| } |
| return group; |
| })(), |
| option: { |
| id: 'xAxis.axisLabel', |
| desc: '坐标轴刻度标签' |
| } |
| }, { |
| group: (function () { |
| var group = []; |
| for (var i = 0; i < 13; ++i) { |
| group.push({ |
| left: grid.left + grid.width * (i / 12) - 5, |
| bottom: grid.bottom - 5, |
| width: 10, |
| height: 10 |
| }); |
| } |
| return group; |
| })(), |
| option: { |
| id: 'xAxis.axisTick', |
| desc: '坐标轴刻度' |
| } |
| }, { |
| left: width * 0.65 - 5, |
| top: height * 0.45 - 5, |
| width: 118, |
| height: 80, |
| option: { |
| id: 'tooltip', |
| desc: '提示框' |
| } |
| }, { |
| left: grid.width / 12 * 7.5 + grid.left - 3, |
| top: grid.top, |
| width: 6, |
| height: grid.height, |
| option: { |
| id: 'tooltip.axisPointer.lineStyle', |
| desc: '提示框坐标轴指示器的线条样式' |
| } |
| }, { |
| left: grid.left, |
| bottom: grid.height / 250 * 162.2 + grid.bottom - 4, |
| width: grid.width, |
| height: 6, |
| option: { |
| id: 'tooltip.axisPointer.crossStyle', |
| desc: '提示框坐标轴指示器的十字线样式' |
| } |
| }, { |
| group: [{ |
| left: 5, |
| bottom: grid.height / 250 * 162.2 + grid.bottom - 10, |
| width: 50, |
| height: 20 |
| }, { |
| left: width - grid.right + 3, |
| bottom: grid.height / 250 * 162.2 + grid.bottom - 10, |
| width: 43, |
| height: 20 |
| }, { |
| left: grid.width / 12 * 7.5 + grid.left - 16, |
| bottom: grid.bottom - 24, |
| width: 32, |
| height: 20 |
| }], |
| option: { |
| id: 'tooltip.axisPointer.label', |
| desc: '提示框坐标轴指示器的文字' |
| } |
| }, { |
| left: baseOption.visualMap.left, |
| top: baseOption.visualMap.top, |
| width: 60, |
| height: 110, |
| option: { |
| id: 'visualMap', |
| desc: '视觉映射,可以将数据值映射到图形的形状、大小、颜色等。\n除了这个例子中连续型的视觉映射之外,还有<a href="option.html#series-line.data.itemStyle" target="_blank">离散型的视觉映射</a>。' |
| } |
| }, { |
| group: [{ |
| left: baseOption.visualMap.left + 20, |
| top: baseOption.visualMap.top, |
| width: 40, |
| height: 20 |
| }, { |
| left: baseOption.visualMap.left + 20, |
| top: baseOption.visualMap.top + 90, |
| width: 40, |
| height: 20 |
| }], |
| option: { |
| id: 'visualMap.calculable', |
| desc: '是否显示拖拽用的手柄(手柄能拖拽调整选中范围)' |
| } |
| }, { |
| right: 5, |
| top: grid.top - 5, |
| height: grid.height + 12, |
| width: 34, |
| option: { |
| id: 'dataZoom', |
| desc: '区域缩放,用来放大一部分的数据,以看清细节' |
| } |
| }, { |
| left: 160, |
| top: 105, |
| width: 150, |
| height: 90, |
| option: { |
| id: 'graphic', |
| desc: '绘制图形元素,包括:image, text, circle, sector, ring, polygon, polyline, rect, line, bezierCurve, arc, group 等' |
| } |
| }, { |
| left: 150, |
| top: grid.top + grid.height + 20, |
| width: grid.width - 120, |
| height: 45, |
| option: { |
| id: 'timeline', |
| desc: '多个 option 切换,展现不同时间段的数据' |
| } |
| }, { |
| left: grid.left + grid.width / 12 * 3, |
| width: grid.width / 12, |
| bottom: grid.bottom + grid.height / 5, |
| height: 50, |
| option: { |
| id: 'series.markPoint', |
| desc: '标记点。\n除此之外,还可以用 <code>markLine</code> 设置标记线,<code>markArea</code> 设置标记区域' |
| } |
| }]; |
| |
| setSheet(baseOption, baseActions, regions); |
| |
| function setSheet(baseOption, actions, regions) { |
| getBaseChart(width, height, baseOption, actions, function (baseImage) { |
| chart = echarts.init($chart[0]); |
| |
| option = { |
| graphic: { |
| } |
| }; |
| |
| var elements = []; |
| |
| var createRect = function (region, regionId, group) { |
| return { |
| type: 'rect', |
| left: region.left, |
| top: region.top, |
| right: region.right, |
| bottom: region.bottom, |
| shape: { |
| width: region.width, |
| height: region.height |
| }, |
| style: { |
| fill: 'transparent', |
| stroke: 'transparent' |
| }, |
| onmouseover: function () { |
| highlight(chart, elements, regionId, option, group || region); |
| }, |
| onmouseout: function () { |
| unhighlightAll(chart, elements, option); |
| if (selectedRegion) { |
| setDetailHtml(selectedRegion.option); |
| } |
| }, |
| onclick: function (e) { |
| // Selecting region |
| if (selectedRegion) { |
| _doUnhighlight(elements, true); |
| } |
| selectedRegion = group || region; |
| highlight(chart, elements, regionId, option, group || region, true); |
| e.event.stopPropagation(); |
| } |
| }; |
| }; |
| |
| for (var i = 0; i < regions.length; ++i) { |
| var shape; |
| if (regions[i].group) { |
| var group = regions[i].group; |
| shape = { |
| type: 'group', |
| children: [], |
| width: '100%', |
| height: '100%' |
| }; |
| for (var g = 0; g < group.length; ++g) { |
| var rect = createRect(group[g], i, regions[i]); |
| shape.children.push(rect); |
| } |
| } |
| else { |
| shape = createRect(regions[i], i); |
| } |
| elements.push(shape); |
| } |
| |
| elements.push({ |
| type: 'image', |
| style: { |
| image: baseImage, |
| width: width, |
| height: height |
| }, |
| silent: true, |
| z: -1 |
| }); |
| |
| option.graphic.elements = elements; |
| |
| chart.setOption(option); |
| }); |
| } |
| |
| function getBaseChart(width, height, option, actions, callback) { |
| var canvas = document.createElement('canvas'); |
| canvas.width = width; |
| canvas.height = height; |
| var chart = echarts.init(canvas, null, { |
| devicePixelRatio: 2 |
| }); |
| option.animation = false; |
| option = { |
| baseOption: option |
| }; |
| chart.setOption(option); |
| |
| for (var i = 0; actions && i < actions.length; ++i) { |
| chart.dispatchAction(actions[i]); |
| } |
| |
| if (typeof callback === 'function') { |
| setTimeout(function () { |
| callback(canvas.toDataURL()); |
| }, 10); |
| } |
| } |
| |
| function highlight(chart, elements, highlightIndex, option, region, isSelect) { |
| setDetailHtml(region.option); |
| |
| if (!isSelect) { |
| _doUnhighlight(elements); |
| } |
| |
| if (elements[highlightIndex].type === 'group') { |
| var children = elements[highlightIndex].children; |
| for (var i = 0; i < children.length; ++i) { |
| if (isSelect) { |
| children[i].style.stroke = '#24c'; |
| } |
| else { |
| children[i].style.fill = highlightFill; |
| } |
| } |
| } |
| else { |
| if (isSelect) { |
| elements[highlightIndex].style.stroke = '#24c'; |
| } else { |
| elements[highlightIndex].style.fill = highlightFill; |
| } |
| } |
| chart.setOption(option); |
| } |
| |
| function unhighlightAll(chart, elements, option) { |
| $detail.text(''); |
| _doUnhighlight(elements); |
| chart.setOption(option); |
| } |
| |
| function _doUnhighlight(elements, isSelect) { |
| for (var i = 0; i < elements.length; ++i) { |
| if (elements[i].type === 'rect') { |
| elements[i].style.fill = 'transparent'; |
| if (isSelect) { |
| elements[i].style.stroke = 'transparent'; |
| } |
| } |
| else if (elements[i].type === 'group') { |
| var children = elements[i].children; |
| for (var j = 0; j < children.length; ++j) { |
| children[j].style.fill = 'transparent'; |
| if (isSelect) { |
| children[j].style.stroke = 'transparent'; |
| } |
| } |
| } |
| } |
| } |
| |
| function setDetailHtml(option) { |
| var link = option.id; |
| switch (link) { |
| case 'series.itemStyle': |
| link = 'series-line.itemStyle'; |
| break; |
| |
| case 'dataZoom.handleStyle': |
| link = 'dataZoom-slider.handleStyle'; |
| break; |
| |
| case 'series.markPoint': |
| link = 'series-line.markPoint'; |
| break; |
| } |
| |
| var html = [ |
| '<h3>', |
| option.id, |
| '</h3>', |
| '<p class="desc">点击图形固定说明文字</p>', |
| '<p>', |
| option.desc.split('\n').join('</p><p>'), |
| '</p>', |
| '<p>', |
| '<a href="./option.html#' + link + '" target="_blank">', |
| '查看配置项手册', |
| '</a>', |
| '</p>' |
| ].join(''); |
| |
| $detail.html(html); |
| } |