G2
G2
G6
F2
L7
墨者学院
关于 G2
图表示例
API 文档
使用教程
English
折线图
基础折线图
双折线图
多折线图
其他折线图
条形图
分组条形图
堆叠条形图
基础条形图
柱状图
基础柱状图
分组柱状图
堆叠柱状图
直方图
饼图
环图
玫瑰图
基础饼图
嵌套饼图
点图
散点图
面积图
基础面积图
堆叠面积图
区间面积图
箱形图
箱型图
烛形图
烛形图
热力图
热力图
仪表盘
仪表盘
漏斗图
漏斗图
地图
地图
雷达图
雷达图
分面
分面
关系图
关系图
其他图表
其他
迷你图
组件使用
组件
环图
2017 年西安居民人均消费支出
源码
复制成功
复制失败
全屏
复制
运行
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,height=device-height"> <title>2017 年西安居民人均消费支出</title> <style>::-webkit-scrollbar{display:none;}html,body{overflow:hidden;height:100%;margin:0;}</style> </head> <body> <div id="mountNode"></div> <script>/*Fixing iframe window.innerHeight 0 issue in Safari*/document.body.clientHeight;</script> <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g2-3.5.1/dist/g2.min.js"></script> <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.data-set-0.10.1/dist/data-set.min.js"></script> <script src="https://gw.alipayobjects.com/os/antv/assets/lib/jquery-3.2.1.min.js"></script> <style> .g2-guide-html { width: 100px; height: 80px; vertical-align: middle; text-align: center; line-height: 0.4 } .g2-guide-html .title { font-size: 12px; color: #8c8c8c; font-weight: 300; } .g2-guide-html .value { font-size: 30px; color: #000; font-weight: bold; } </style> <script> var startAngle = -Math.PI / 2 - Math.PI / 4; var data = [{ type: '居住', value: 7140 }, { type: '食品烟酒', value: 3875 }, { type: '交通通信', value: 2267 }, { type: '教育、文化、娱乐', value: 1853 }, { type: '医疗保健', value: 1685 }, { type: '衣着', value: 1179 }, { type: '生活用品及服务', value: 1088 }, { type: '其他用品及服务', value: 583 }]; var ds = new DataSet(); var dv = ds.createView().source(data); dv.transform({ type: 'percent', field: 'value', dimension: 'type', as: 'percent' }); var chart = new G2.Chart({ container: 'mountNode', forceFit: true, height: window.innerHeight, padding: 'auto' }); chart.source(dv); chart.legend(false); chart.coord('theta', { radius: 0.75, innerRadius: 0.5, startAngle: startAngle, endAngle: startAngle + Math.PI * 2 }); chart.intervalStack().position('value').color('type', ['#0a4291', '#0a57b6', '#1373db', '#2295ff', '#48adff', '#6fc3ff', '#96d7ff', '#bde8ff']).opacity(1).label('percent', { offset: -20, textStyle: { fill: 'white', fontSize: 12, shadowBlur: 2, shadowColor: 'rgba(0, 0, 0, .45)' }, formatter: function formatter(val) { return parseInt(val * 100) + '%'; } }); chart.guide().html({ position: ['50%', '50%'], html: '<div class="g2-guide-html"><p class="title">总计</p><p class="value">19670</p></div>' }); chart.render(); //draw label var OFFSET = 20; var APPEND_OFFSET = 50; var LINEHEIGHT = 60; var coord = chart.get('coord'); // 获取坐标系对象 var center = coord.center; // 极坐标圆心坐标 var r = coord.radius; // 极坐标半径 var canvas = chart.get('canvas'); var canvasWidth = chart.get('width'); var canvasHeight = chart.get('height'); var labelGroup = canvas.addGroup(); var labels = []; addPieLabel(chart); canvas.draw(); chart.on('afterpaint', function() { addPieLabel(chart); }); //main function addPieLabel() { var halves = [[], []]; var data = dv.rows; var angle = startAngle; for (var i = 0; i < data.length; i++) { var percent = data[i].percent; var targetAngle = angle + Math.PI * 2 * percent; var middleAngle = angle + (targetAngle - angle) / 2; angle = targetAngle; var edgePoint = getEndPoint(center, middleAngle, r); var routerPoint = getEndPoint(center, middleAngle, r + OFFSET); //label var label = { _anchor: edgePoint, _router: routerPoint, _data: data[i], x: routerPoint.x, y: routerPoint.y, r: r + OFFSET, fill: '#bfbfbf' }; // 判断文本的方向 if (edgePoint.x < center.x) { label._side = 'left'; halves[0].push(label); } else { label._side = 'right'; halves[1].push(label); } } // end of for var maxCountForOneSide = parseInt(canvasHeight / LINEHEIGHT, 10); halves.forEach(function(half, index) { // step 2: reduce labels if (half.length > maxCountForOneSide) { half.sort(function(a, b) { return b._percent - a._percent; }); half.splice(maxCountForOneSide, half.length - maxCountForOneSide); } // step 3: distribute position (x and y) half.sort(function(a, b) { return a.y - b.y; }); antiCollision(half, index); }); } function getEndPoint(center, angle, r) { return { x: center.x + r * Math.cos(angle), y: center.y + r * Math.sin(angle) }; } function drawLabel(label) { var _anchor = label._anchor, _router = label._router, fill = label.fill, y = label.y; var labelAttrs = { y: y, fontSize: 12, // 字体大小 fill: '#808080', text: label._data.type + '\n' + label._data.value, textBaseline: 'bottom' }; var lastPoint = { y: y }; if (label._side === 'left') { // 具体文本的位置 lastPoint.x = APPEND_OFFSET; labelAttrs.x = APPEND_OFFSET; // 左侧文本左对齐并贴着画布最左侧边缘 labelAttrs.textAlign = 'left'; } else { lastPoint.x = canvasWidth - APPEND_OFFSET; labelAttrs.x = canvasWidth - APPEND_OFFSET; // 右侧文本右对齐并贴着画布最右侧边缘 labelAttrs.textAlign = 'right'; } // 绘制文本 var text = labelGroup.addShape('Text', { attrs: labelAttrs }); labels.push(text); // 绘制连接线 var points = void 0; if (_router.y !== y) { // 文本位置做过调整 points = [[_anchor.x, _anchor.y], [_router.x, y], [lastPoint.x, lastPoint.y]]; } else { points = [[_anchor.x, _anchor.y], [_router.x, _router.y], [lastPoint.x, lastPoint.y]]; } labelGroup.addShape('polyline', { attrs: { points: points, lineWidth: 1, stroke: fill } }); } function antiCollision(half, isRight) { var startY = center.y - r - OFFSET - LINEHEIGHT; var overlapping = true; var totalH = canvasHeight; var i = void 0; var maxY = 0; var minY = Number.MIN_VALUE; var boxes = half.map(function(label) { var labelY = label.y; if (labelY > maxY) { maxY = labelY; } if (labelY < minY) { minY = labelY; } return { size: LINEHEIGHT, targets: [labelY - startY] }; }); if (maxY - startY > totalH) { totalH = maxY - startY; } while (overlapping) { boxes.forEach(function(box) { var target = (Math.min.apply(minY, box.targets) + Math.max.apply(minY, box.targets)) / 2; box.pos = Math.min(Math.max(minY, target - box.size / 2), totalH - box.size); }); // detect overlapping and join boxes overlapping = false; i = boxes.length; while (i--) { if (i > 0) { var previousBox = boxes[i - 1]; var box = boxes[i]; if (previousBox.pos + previousBox.size > box.pos) { // overlapping previousBox.size += box.size; previousBox.targets = previousBox.targets.concat(box.targets); // overflow, shift up if (previousBox.pos + previousBox.size > totalH) { previousBox.pos = totalH - previousBox.size; } boxes.splice(i, 1); // removing box overlapping = true; } } } } // step 4: normalize y and adjust x i = 0; boxes.forEach(function(b) { var posInCompositeBox = startY; // middle of the label b.targets.forEach(function() { half[i].y = b.pos + posInCompositeBox + LINEHEIGHT / 2; posInCompositeBox += LINEHEIGHT; i++; }); }); // (x - cx)^2 + (y - cy)^2 = totalR^2 half.forEach(function(label) { var rPow2 = label.r * label.r; var dyPow2 = Math.pow(Math.abs(label.y - center.y), 2); if (rPow2 < dyPow2) { label.x = center.x; } else { var dx = Math.sqrt(rPow2 - dyPow2); if (!isRight) { // left label.x = center.x - dx; } else { // right label.x = center.x + dx; } } drawLabel(label); }); } </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,height=device-height"> <title>2017 年西安居民人均消费支出</title> <style>::-webkit-scrollbar{display:none;}html,body{overflow:hidden;height:100%;margin:0;}</style> </head> <body style="background: #1f1f1f;"> <div id="mountNode"></div> <script>/*Fixing iframe window.innerHeight 0 issue in Safari*/document.body.clientHeight;</script> <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g2-3.5.1/dist/g2.min.js"></script> <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.data-set-0.10.1/dist/data-set.min.js"></script> <script src="https://gw.alipayobjects.com/os/antv/assets/lib/jquery-3.2.1.min.js"></script> <script>G2.Global.setTheme('dark');</script> <style> .g2-guide-html { width: 100px; height: 80px; vertical-align: middle; text-align: center; line-height: 0.4 } .g2-guide-html .title { font-size: 12px; color: #8c8c8c; font-weight: 300; } .g2-guide-html .value { font-size: 30px; color: #000; font-weight: bold; } </style> <script> var startAngle = -Math.PI / 2 - Math.PI / 4; var data = [{ type: '居住', value: 7140 }, { type: '食品烟酒', value: 3875 }, { type: '交通通信', value: 2267 }, { type: '教育、文化、娱乐', value: 1853 }, { type: '医疗保健', value: 1685 }, { type: '衣着', value: 1179 }, { type: '生活用品及服务', value: 1088 }, { type: '其他用品及服务', value: 583 }]; var ds = new DataSet(); var dv = ds.createView().source(data); dv.transform({ type: 'percent', field: 'value', dimension: 'type', as: 'percent' }); var chart = new G2.Chart({ container: 'mountNode', forceFit: true, height: window.innerHeight, padding: 'auto' }); chart.source(dv); chart.legend(false); chart.coord('theta', { radius: 0.75, innerRadius: 0.5, startAngle: startAngle, endAngle: startAngle + Math.PI * 2 }); chart.intervalStack().position('value').color('type', ['#0a4291', '#0a57b6', '#1373db', '#2295ff', '#48adff', '#6fc3ff', '#96d7ff', '#bde8ff']).opacity(1).label('percent', { offset: -20, textStyle: { fill: 'white', fontSize: 12, shadowBlur: 2, shadowColor: 'rgba(0, 0, 0, .45)' }, formatter: function formatter(val) { return parseInt(val * 100) + '%'; } }); chart.guide().html({ position: ['50%', '50%'], html: '<div class="g2-guide-html"><p class="title">总计</p><p class="value">19670</p></div>' }); chart.render(); //draw label var OFFSET = 20; var APPEND_OFFSET = 50; var LINEHEIGHT = 60; var coord = chart.get('coord'); // 获取坐标系对象 var center = coord.center; // 极坐标圆心坐标 var r = coord.radius; // 极坐标半径 var canvas = chart.get('canvas'); var canvasWidth = chart.get('width'); var canvasHeight = chart.get('height'); var labelGroup = canvas.addGroup(); var labels = []; addPieLabel(chart); canvas.draw(); chart.on('afterpaint', function() { addPieLabel(chart); }); //main function addPieLabel() { var halves = [[], []]; var data = dv.rows; var angle = startAngle; for (var i = 0; i < data.length; i++) { var percent = data[i].percent; var targetAngle = angle + Math.PI * 2 * percent; var middleAngle = angle + (targetAngle - angle) / 2; angle = targetAngle; var edgePoint = getEndPoint(center, middleAngle, r); var routerPoint = getEndPoint(center, middleAngle, r + OFFSET); //label var label = { _anchor: edgePoint, _router: routerPoint, _data: data[i], x: routerPoint.x, y: routerPoint.y, r: r + OFFSET, fill: '#bfbfbf' }; // 判断文本的方向 if (edgePoint.x < center.x) { label._side = 'left'; halves[0].push(label); } else { label._side = 'right'; halves[1].push(label); } } // end of for var maxCountForOneSide = parseInt(canvasHeight / LINEHEIGHT, 10); halves.forEach(function(half, index) { // step 2: reduce labels if (half.length > maxCountForOneSide) { half.sort(function(a, b) { return b._percent - a._percent; }); half.splice(maxCountForOneSide, half.length - maxCountForOneSide); } // step 3: distribute position (x and y) half.sort(function(a, b) { return a.y - b.y; }); antiCollision(half, index); }); } function getEndPoint(center, angle, r) { return { x: center.x + r * Math.cos(angle), y: center.y + r * Math.sin(angle) }; } function drawLabel(label) { var _anchor = label._anchor, _router = label._router, fill = label.fill, y = label.y; var labelAttrs = { y: y, fontSize: 12, // 字体大小 fill: '#808080', text: label._data.type + '\n' + label._data.value, textBaseline: 'bottom' }; var lastPoint = { y: y }; if (label._side === 'left') { // 具体文本的位置 lastPoint.x = APPEND_OFFSET; labelAttrs.x = APPEND_OFFSET; // 左侧文本左对齐并贴着画布最左侧边缘 labelAttrs.textAlign = 'left'; } else { lastPoint.x = canvasWidth - APPEND_OFFSET; labelAttrs.x = canvasWidth - APPEND_OFFSET; // 右侧文本右对齐并贴着画布最右侧边缘 labelAttrs.textAlign = 'right'; } // 绘制文本 var text = labelGroup.addShape('Text', { attrs: labelAttrs }); labels.push(text); // 绘制连接线 var points = void 0; if (_router.y !== y) { // 文本位置做过调整 points = [[_anchor.x, _anchor.y], [_router.x, y], [lastPoint.x, lastPoint.y]]; } else { points = [[_anchor.x, _anchor.y], [_router.x, _router.y], [lastPoint.x, lastPoint.y]]; } labelGroup.addShape('polyline', { attrs: { points: points, lineWidth: 1, stroke: fill } }); } function antiCollision(half, isRight) { var startY = center.y - r - OFFSET - LINEHEIGHT; var overlapping = true; var totalH = canvasHeight; var i = void 0; var maxY = 0; var minY = Number.MIN_VALUE; var boxes = half.map(function(label) { var labelY = label.y; if (labelY > maxY) { maxY = labelY; } if (labelY < minY) { minY = labelY; } return { size: LINEHEIGHT, targets: [labelY - startY] }; }); if (maxY - startY > totalH) { totalH = maxY - startY; } while (overlapping) { boxes.forEach(function(box) { var target = (Math.min.apply(minY, box.targets) + Math.max.apply(minY, box.targets)) / 2; box.pos = Math.min(Math.max(minY, target - box.size / 2), totalH - box.size); }); // detect overlapping and join boxes overlapping = false; i = boxes.length; while (i--) { if (i > 0) { var previousBox = boxes[i - 1]; var box = boxes[i]; if (previousBox.pos + previousBox.size > box.pos) { // overlapping previousBox.size += box.size; previousBox.targets = previousBox.targets.concat(box.targets); // overflow, shift up if (previousBox.pos + previousBox.size > totalH) { previousBox.pos = totalH - previousBox.size; } boxes.splice(i, 1); // removing box overlapping = true; } } } } // step 4: normalize y and adjust x i = 0; boxes.forEach(function(b) { var posInCompositeBox = startY; // middle of the label b.targets.forEach(function() { half[i].y = b.pos + posInCompositeBox + LINEHEIGHT / 2; posInCompositeBox += LINEHEIGHT; i++; }); }); // (x - cx)^2 + (y - cy)^2 = totalR^2 half.forEach(function(label) { var rPow2 = label.r * label.r; var dyPow2 = Math.pow(Math.abs(label.y - center.y), 2); if (rPow2 < dyPow2) { label.x = center.x; } else { var dx = Math.sqrt(rPow2 - dyPow2); if (!isRight) { // left label.x = center.x - dx; } else { // right label.x = center.x + dx; } } drawLabel(label); }); } </script> </body> </html>
图表用法
数据来源:MTA
相关链接
BizCharts
Viser