Commit 0ccd06ef authored by 晓彤's avatar 晓彤

饼状图

parent fdd788bc
......@@ -137,3 +137,20 @@ body {
.global-svg .hover-circle, .hover-line {
opacity: 0;
}
.flex {
stroke-dasharray: 100;
stroke-dashoffset: 0;
animation: flex-draw 5s ease-in-out;
/* -webkit-animation: flex-draw 5s ease-in-out; */
}
@keyframes flex-draw {
from {
stroke-dashoffset: 100;
}
to {
stroke-dashoffset: 0;
}
}
......@@ -79,49 +79,54 @@ var _option;
// 根据接收数据,渲染出样式
function setOption(option, outId) {
_option = option;
let svg_width = document.querySelector('#global-svg-'+_outId).viewBox.baseVal.width;
let svg_height = document.querySelector('#global-svg-'+_outId).viewBox.baseVal.height;
// 判断是否传递数值
let _y = option.yAxis; // 左侧y轴样式
let _x = option.xAxis; // 底部x轴
let _aroundX = _x.outpadding ? _x.outpadding : 12; // x轴距离页面上下左右距离
let _aroundInX = _x.inpadding? _x.inpadding : 5; // 折线距离左右线段距离
let _aroundY = _y.padding ? _y.padding + _y.font.fontSize : 5 + _y.font.fontSize; // y轴距离页面边距左右距离
let _aroundTextY = _y.padding ? _y.padding : 5; // y轴文字距离页面左侧的距离
let _diffV = _y.max / (_y.totalLine - 1); // 计算y轴数据之间差值
let _x_startX = _aroundX + _aroundY + _aroundInX; // x轴底部开始位置
let x_padding = (svg_width - _aroundX * 2 - _aroundY - _aroundInX * 2) / (option.xAxis.data.length - 1); // 每段数据间距
let y_padding = (svg_height - _aroundX - _x.font.fontSize) / option.yAxis.totalLine;
// y轴展示
for (var i = 0; i < _y.totalLine; i++) {
// 数值展示
let _yP = (i * 1 + 1) * y_padding;
let _yText = document.createElementNS('http://www.w3.org/2000/svg', 'text');
_yText.setAttribute('text-anchor', 'middle');
_yText.setAttribute('alignment-baseline', 'middle');
_yText.setAttribute('x', _aroundTextY);
_yText.setAttribute('y', _yP);
_yText.setAttribute('transform', `translate(0, ${_yP * 2 }) scale(1, -1)`);
_yText.classList.add('y-text');
_yText.setAttribute('style', `font-size:${_countFont(_y.font.fontSize)};fill:${_y.font.color}`);
_yText.appendChild(document.createTextNode( Math.round(i * _diffV * 100) / 100));
document.querySelector('#global-svg-'+_outId+' #y-g').appendChild(_yText);
// 横线
let _yLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
_yLine.setAttribute('x1', _aroundY + _aroundX);
_yLine.setAttribute('y1', _yP); // y轴需要计算
_yLine.setAttribute('x2', svg_width - _aroundX); // svg宽度 - x轴padding
_yLine.setAttribute('y2', _yP); // y轴需要计算
_yLine.setAttribute('stroke', `${_y.yLineColor}`);
_yLine.setAttribute('stroke-width', '1');
document.querySelector('#global-svg-'+_outId+' #y-g').appendChild(_yLine);
}
let _aroundX, _aroundInX, _aroundY, _diffV, x_padding, y_padding;
if(_x || _y) {
_aroundX = _x.outpadding ? _x.outpadding : 12; // x轴距离页面上下左右距离
_aroundInX = _x.inpadding? _x.inpadding : 5; // 折线距离左右线段距离
_aroundY = _y.padding ? _y.padding + _y.font.fontSize : 5 + _y.font.fontSize; // y轴距离页面边距左右距离
let _aroundTextY = _y.padding ? _y.padding : 5; // y轴文字距离页面左侧的距离
_diffV = _y.max / (_y.totalLine - 1); // 计算y轴数据之间差值
let _x_startX = _aroundX + _aroundY + _aroundInX; // x轴底部开始位置
x_padding = (svg_width - _aroundX * 2 - _aroundY - _aroundInX * 2) / (option.xAxis.data.length - 1); // 每段数据间距
y_padding = (svg_height - _aroundX - _x.font.fontSize) / option.yAxis.totalLine;
// y轴展示
for (var i = 0; i < _y.totalLine; i++) {
// 数值展示
let _yP = (i * 1 + 1) * y_padding;
let _yText = document.createElementNS('http://www.w3.org/2000/svg', 'text');
_yText.setAttribute('text-anchor', 'middle');
_yText.setAttribute('alignment-baseline', 'middle');
_yText.setAttribute('x', _aroundTextY);
_yText.setAttribute('y', _yP);
_yText.setAttribute('transform', `translate(0, ${_yP * 2 }) scale(1, -1)`);
_yText.classList.add('y-text');
_yText.setAttribute('style', `font-size:${_countFont(_y.font.fontSize)};fill:${_y.font.color}`);
_yText.appendChild(document.createTextNode( Math.round(i * _diffV * 100) / 100));
document.querySelector('#global-svg-'+_outId+' #y-g').appendChild(_yText);
// 横线
let _yLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
_yLine.setAttribute('x1', _aroundY + _aroundX);
_yLine.setAttribute('y1', _yP); // y轴需要计算
_yLine.setAttribute('x2', svg_width - _aroundX); // svg宽度 - x轴padding
_yLine.setAttribute('y2', _yP); // y轴需要计算
_yLine.setAttribute('stroke', `${_y.yLineColor}`);
_yLine.setAttribute('stroke-width', '1');
document.querySelector('#global-svg-'+_outId+' #y-g').appendChild(_yLine);
}
// 底部x轴样式
for (let m in _x.data) {
// 底部x轴样式
for (let m in _x.data) {
let _xText = document.createElementNS('http://www.w3.org/2000/svg', 'text');
_xText.setAttribute('text-anchor', 'middle');
......@@ -155,8 +160,8 @@ function setOption(option, outId) {
_x_startX += x_padding;
}
// 折线图数值及样式
}
// 折线图、柱状图、饼状图数值及样式
let _barArr = [];
for(let l in option.series) {
......@@ -166,80 +171,193 @@ function setOption(option, outId) {
_gPathC.setAttribute('id', 'path-g-container-'+l);
document.querySelector('#global-svg-'+_outId+' #path-g').appendChild(_gPathC);
// 当type类型为bar时,重新计算柱状图之间间距
if(option.series[l].type == 'bar') {
x_padding = (svg_width - _aroundX * 2 - _aroundY - _aroundInX * 2 - option.series[l].normalStyle.width * option.series[l].data.length) / (option.xAxis.data.length - 1) + option.series[l].normalStyle.width // 每段数据间距
_barArr.push(l);
}
// 折线图、柱状图时,数据处理及展示
if (option.series[l].type == 'line' || option.series[l].type == 'bar' ) {
// 当type类型为bar时,重新计算柱状图之间间距
if(option.series[l].type == 'bar') {
x_padding = (svg_width - _aroundX * 2 - _aroundY - _aroundInX * 2 - option.series[l].normalStyle.width * option.series[l].data.length) / (option.xAxis.data.length - 1) + option.series[l].normalStyle.width // 每段数据间距
_barArr.push(l);
}
let path_data = [];
let start_x = _aroundX + _aroundY + _aroundInX; // 折线图数据开始值,y轴间距 + x轴距离y轴的间距
for (let s in option.series[l].data) {
let _data = option.series[l].data;
let _startY = y_padding * (_data[s] / _diffV) + y_padding;
path_data.push(`${start_x},${_startY}`);
let path_data = [];
let start_x = _aroundX + _aroundY + _aroundInX; // 折线图数据开始值,y轴间距 + x轴距离y轴的间距
for (let s in option.series[l].data) {
let _data = option.series[l].data;
let _startY = y_padding * (_data[s] / _diffV) + y_padding;
path_data.push(`${start_x},${_startY}`);
// type为line时
if (option.series[l].type == 'line') {
// 折线图上圆点显示
// hover时,竖线显示, 只生成一次,因为他们是一样的
if (l == 0) {
let hoverLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
hoverLine.setAttribute('x1', start_x);
hoverLine.setAttribute('y1', y_padding); // y轴需要计算
hoverLine.setAttribute('x2', start_x);
hoverLine.setAttribute('y2', (_y.totalLine) * y_padding); // y轴需要计算
hoverLine.setAttribute('stroke', option.series[l].hoverStyle.linestroke);
hoverLine.setAttribute('stroke-width', '1');
hoverLine.classList.add('hover-line');
hoverLine.classList.add('hover-line-'+s);
document.querySelector('#global-svg-'+_outId+' #path-deploy-line-g').appendChild(hoverLine);
}
// type为line时
if (option.series[l].type == 'line') {
// 折线图上圆点显示
// hover时,竖线显示, 只生成一次,因为他们是一样的
if (l == 0) {
let hoverLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
hoverLine.setAttribute('x1', start_x);
hoverLine.setAttribute('y1', y_padding); // y轴需要计算
hoverLine.setAttribute('x2', start_x);
hoverLine.setAttribute('y2', (_y.totalLine) * y_padding); // y轴需要计算
hoverLine.setAttribute('stroke', option.series[l].hoverStyle.linestroke);
hoverLine.setAttribute('stroke-width', '1');
hoverLine.classList.add('hover-line');
hoverLine.classList.add('hover-line-'+s);
document.querySelector('#global-svg-'+_outId+' #path-deploy-line-g').appendChild(hoverLine);
// 折线hover后,圆点放大
let hoverCircle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
hoverCircle.setAttribute('cx', start_x);
hoverCircle.setAttribute('cy', _startY)
hoverCircle.setAttribute('r', 5);
hoverCircle.setAttribute('stroke', option.series[l].hoverStyle.circlestroke);
hoverCircle.setAttribute('stroke-width', 3);
hoverCircle.setAttribute('fill', 'none');
hoverCircle.classList.add('hover-circle');
hoverCircle.classList.add('hover-circle-'+s);
document.querySelector('#global-svg-'+_outId+' #path-deploy-circle-g').appendChild(hoverCircle);
// 折线上设置圆点
let circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
circle.setAttribute('cx', start_x);
circle.setAttribute('cy', _startY);
circle.setAttribute('r', 3);
circle.setAttribute('stroke', 'white');
circle.setAttribute('stroke-width', 1);
circle.setAttribute('fill', option.series[l].normalStyle.circlestroke);
circle.setAttribute('transform-origin', `${start_x} ${_startY}`); // 圆点中心位置
circle.style.setProperty('--delay', `${(3 * parseInt(s) / _data.length)}s`);
circle.classList.add('point');
document.querySelector('#global-svg-'+_outId+' #path-deploy-circle-g').appendChild(circle);
}
// 折线hover后,圆点放大
let hoverCircle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
hoverCircle.setAttribute('cx', start_x);
hoverCircle.setAttribute('cy', _startY)
hoverCircle.setAttribute('r', 5);
hoverCircle.setAttribute('stroke', option.series[l].hoverStyle.circlestroke);
hoverCircle.setAttribute('stroke-width', 3);
hoverCircle.setAttribute('fill', 'none');
hoverCircle.classList.add('hover-circle');
hoverCircle.classList.add('hover-circle-'+s);
document.querySelector('#global-svg-'+_outId+' #path-deploy-circle-g').appendChild(hoverCircle);
// 折线上设置圆点
let circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
circle.setAttribute('cx', start_x);
circle.setAttribute('cy', _startY);
circle.setAttribute('r', 3);
circle.setAttribute('stroke', 'white');
circle.setAttribute('stroke-width', 1);
circle.setAttribute('fill', option.series[l].normalStyle.circlestroke);
circle.setAttribute('transform-origin', `${start_x} ${_startY}`); // 圆点中心位置
circle.style.setProperty('--delay', `${(3 * parseInt(s) / _data.length)}s`);
circle.classList.add('point');
document.querySelector('#global-svg-'+_outId+' #path-deploy-circle-g').appendChild(circle);
}
// 创建柱状图
if(option.series[l].type == 'bar') {
createPathBar(option, l, start_x, _startY, y_padding, s, _barArr.length);
}
// 创建柱状图
if(option.series[l].type == 'bar') {
createPathBar(option, l, start_x, _startY, y_padding, s, _barArr.length);
start_x += x_padding;
}
start_x += x_padding;
// 创建折线图及背景
if (option.series[l].type == 'line') {
createPathLine(option, l, path_data, y_padding);
}
}
// 创建折线图及背景
if (option.series[l].type == 'line') {
createPathLine(option, l, path_data, y_padding);
}
// 饼状图
if(option.series[l].type == 'pie') {
let _pieData = option.series[l].data;
let _cx = option.series[l].style.width / 2;
let _cy = option.series[l].style.width / 2;
let _r = option.series[l].style.width / 2;
let _inr = option.series[l].style.inWidth / 2; // 环行圆内部
let _viewboxX = (svg_width - option.series[l].style.width) / 2
document.querySelector('#global-svg-'+outId).setAttribute('viewBox', `${-_viewboxX} 100 ${svg_width} ${svg_height}`);
// 累计饼图总大小
let _pieTotal = 0;
for (var o in _pieData) {
_pieTotal += _pieData[o].value;
}
// 计算每个饼状图分片大小,其中角度的计算
let _angles = [];
let _anglesHalf = [];
for (var o in _pieData) {
_angles[o] = _pieData[o].value / _pieTotal * Math.PI * 2;
_anglesHalf[o] = (_pieData[o].value / _pieTotal * Math.PI * 2) / 2;
}
// 遍历饼状图的每个分片
let _startAngle = 0;
let _outXY = [];
let _inXY = [];
for (var o in _pieData) {
let _endAngle = _startAngle + _angles[o];
let _endAngleHalf = _startAngle + _anglesHalf[o];
let _x1 = _cx + (_r) * Math.sin(_startAngle);
let _y1 = _cy - _r * Math.cos(_startAngle);
let _x2 = _cx + _r * Math.sin(_endAngle);
let _y2 = _cy - _r * Math.cos(_endAngle);
// 环形时内圆
let _xin1 = _cx + _inr * Math.sin(_startAngle);
let _yin1 = _cy - _inr * Math.cos(_startAngle);
let _xin2 = _cx + _inr * Math.sin(_endAngle);
let _yin2 = _cy - _inr * Math.cos(_endAngle);
let _big = _endAngle - _startAngle > Math.PI ? 1 : 0; // 小弧
//计算线段及文字出现的位置
let _linex = _cx + (_r) * Math.sin(_endAngleHalf);
let _liney = _cy - (_r) * Math.cos(_endAngleHalf);
let _linex1 = _cx + (_r + 10) * Math.sin(_endAngleHalf);
let _liney1 = _cy - (_r + 10) * Math.cos(_endAngleHalf);
let _linex2 = _linex < 90 ? -(_cx * 2 + _viewboxX) : _cx * 2 + _viewboxX;
let _fontPosition = {x: _linex < 90 ? -_viewboxX : _linex2, y: _liney1, position: _linex < 90 ? 'left' : 'right'};
// 实心圆及周边线及文字位置
let _d, _lineD;
if(option.series[l].pieType == 'base') {
_d = `M${_cx} ${_cy} L${_x1} ${_y1} A${_r} ${_r} 0 ${_big} 1 ${_x2} ${_y2} Z`;
_lineD = `M${_linex} ${_liney} L${_linex1} ${_liney1} L${_linex2} ${_liney1}`;
}
// 空心圆(环形)
if(option.series[l].pieType == 'annular') {
_d = `M${_x1} ${_y1} A${_r} ${_r} 0 ${_big} 1 ${_x2} ${_y2} L${_xin2} ${_yin2} A${_inr} ${_inr} 0 ${_big} 0 ${_xin1} ${_yin1} Z`;
}
// 创建圆方法
createPathPie(l, _d, _pieData[o], _pieTotal, _lineD, _fontPosition);
_startAngle = _endAngle; // 当前的角结束就是下一个角的开始
}
}
}
}
// 创建饼状图
function createPathPie(l, d, data, total, lineD, fontPosition) {
console.log(lineD, fontPosition, '-------fontPosition')
// 创建饼图
let _pie = document.createElementNS('http://www.w3.org/2000/svg', 'path');
_pie.setAttribute('fill', data.color);
_pie.setAttribute('d', d);
_pie.classList.add('flex');
document.querySelector('#global-svg-'+_outId+' #path-g-container-'+l).appendChild(_pie);
// 创建说明线
if (lineD) {
let _pieLine = document.createElementNS('http://www.w3.org/2000/svg', 'path');
_pieLine.setAttribute('d', lineD);
_pieLine.setAttribute('fill', 'none');
_pieLine.setAttribute('stroke', data.color);
_pieLine.setAttribute('stroke-width', 1);
_pieLine.setAttribute('stroke-miterlimit', 10);
_pieLine.setAttribute('stroke-linecap', 'butt');
document.querySelector('#global-svg-'+_outId+' #path-deploy-line-g').appendChild(_pieLine);
// 创建文字说明
let _nub = Math.round(total / data.value * 100) / 100 + '%';
let _pieText = document.createElementNS('http://www.w3.org/2000/svg', 'text');
_pieText.setAttribute('x', fontPosition.x);
_pieText.setAttribute('y', fontPosition.y);
_pieText.setAttribute('transform', `translate(0, ${fontPosition.y * 2+2}) scale(1, -1)`);
_pieText.setAttribute('text-anchor', fontPosition.position == 'left' ? 'start' : 'end');
_pieText.setAttribute('style', `font-size:12;fill:${data.color}`);
_pieText.appendChild(document.createTextNode(`占比${_nub}`));
document.querySelector('#global-svg-'+_outId+' #path-deploy-line-g').appendChild(_pieText);
}
}
/*
* 创建柱状图
......
......@@ -109,7 +109,7 @@
]
}
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option, 'main');
myChart.setOption(option);
</script>
</html>
```
......@@ -16,6 +16,11 @@
<div id = 'tongbar' width = '425' height = '236'></div>
</div>
<!-- 饼图 -->
<div style = 'width:100%;height:400px;margin-top:100px;margin-left:100px;'>
<div id = 'tongpie' width = '425' height = '340'></div>
</div>
</body>
<script type="text/javascript" src = './chart/chart.js'></script>
<script type="text/javascript">
......@@ -132,5 +137,35 @@
]
}
myChartBar.setOption(optionbar, 'tongbar');
// 饼图
var myChartPie = chart.init(document.getElementById('tongpie'));
var optionpie = {
series: [
{
type: 'pie',
pieType: 'base', // base: 基础 separate: 分离 annular: 环形
data: [
{value: 5.6 , color: 'red', name: '1'},
{value: 1, color: 'green', name: '2'},
{value: 0.8, color: '#953C96', name: '3'},
{value: 0.5, color: 'blue', name: '4'},
{value: 0.5, color: 'yellow', name: '5'},
{value: 3.8, color: 'pink', name: '6'},
// {value: 1048 , color: 'red', name: '1'},
// {value: 735, color: 'green', name: '2'},
// {value: 580, color: '#953C96', name: '3'},
// {value: 484, color: 'blue', name: '4'},
// {value: 300, color: 'yellow', name: '5'},
],
style: {
width: 180,
inWidth: 111,
}
}
]
};
myChartPie.setOption(optionpie, 'tongpie');
</script>
</html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment