📄 piechart.js
字号:
/*----------------------------------------------------------------------------\
| Chart 1.0 |
|-----------------------------------------------------------------------------|
| Created by Emil A Eklund |
| (http://eae.net/contact/emil) |
|-----------------------------------------------------------------------------|
| Client side chart painter, supports line, area and bar charts and stacking, |
| uses Canvas (mozilla, safari, opera) or SVG (mozilla, opera) for drawing. |
| Can be used with IECanvas to allow the canvas painter to be used in IE. |
|-----------------------------------------------------------------------------|
| Copyright (c) 2006 Emil A Eklund |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| This program is free software; you can redistribute it and/or modify it |
| under the terms of the MIT License. |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| Permission is hereby granted, free of charge, to any person obtaining a |
| copy of this software and associated documentation files (the "Software"), |
| to deal in the Software without restriction, including without limitation |
| the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| and/or sell copies of the Software, and to permit persons to whom the |
| Software is furnished to do so, subject to the following conditions: |
| The above copyright notice and this permission notice shall be included in |
| all copies or substantial portions of the Software. |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| DEALINGS IN THE SOFTWARE. |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| http://eae.net/license/mit |
|-----------------------------------------------------------------------------|
| Dependencies: canvaschartpainter.js - Canvas chart painter implementation. |
| canvaschart.css - Canvas chart painter styles. |
| or: svgchartpainter.js - SVG chart painter implementation. |
|-----------------------------------------------------------------------------|
| 2006-01-03 | Work started. |
| 2006-01-05 | Added legend and axis labels. Changed the painter api slightly |
| | to allow two-stage initialization (required for ie/canvas) and |
| | added legend/axis related methods. Also updated bar chart type |
| | and added a few options, mostly related to bar charts. |
| 2006-01-07 | Updated chart size calculations to take legend and axis labels |
| | into consideration. Split painter implementations to separate |
| | files. |
| 2006-01-10 | Fixed bug in automatic range calculation. Also added explicit |
| | cast to float for stacked series. |
| 2006-04-16 | Updated constructor to set painter factory based on available |
| | and supported implementations. |
| 2007-02-01 | Brought chart related methods of PainterFactory classes into |
| | the Chart class, and reduced PainterFactory to simpler drawing |
| | primitives only. (by Ashutosh Bijoor -bijoor@gmail.com) |
|-----------------------------------------------------------------------------|
| Created 2006-01-03 | All changes are in the log above. | Updated 2007-02-01 |
\----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------\
| Chart |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| Chart class, control class that's used to represent a chart. Uses a painter |
| class for the actual drawing. This is the only class that should be used |
| directly, the other ones are internal. |
\----------------------------------------------------------------------------*/
function Chart(el) {
this._cont = el;
this._yMin = null;
this._yMax = null;
this._xGridDensity = 0;
this._yGridDensity = 0;
this._flags = 0;
this._series = new Array();
this._labelPrecision = 0;
this._horizontalLabels = new Array();
this._barWidth = 10;
this._barDistance = 2;
this._bars = 0;
this._showLegend = true;
this._painter = null;
/*
* Determine painter implementation to use based on what's available and
* supported. CanvasChartPainter is the prefered one, JsGraphicsChartPainter
* the fallback one as it works in pretty much any browser. The
* SVGChartPainter implementation one will only be used if set explicitly as
* it's not up to pair with the other ones.
*/
if ((typeof CanvasChartPainterFactory != 'undefined') && (window.CanvasRenderingContext2D)) {
this.setPainterFactory(CanvasChartPainterFactory);
}
else if (typeof JsGraphicsChartPainterFactory != 'undefined') {
this.setPainterFactory(JsGraphicsChartPainterFactory);
}
else { this._painterFactory = null; }
}
Chart.prototype.setPainterFactory = function(f) {
this._painterFactory = f;
/* Create painter object */
this._painter = this._painterFactory();
this._painter.create(this._cont);
};
Chart.prototype.getPainter = function() {
return this._painter;
};
Chart.prototype.setVerticalRange = function(min, max) {
this._yMin = min;
this._yMax = max;
};
Chart.prototype.setLabelPrecision = function(precision) {
this._labelPrecision = precision;
};
Chart.prototype.setShowLegend = function(b) {
this._showLegend = b;
};
Chart.prototype.setGridDensity = function(horizontal, vertical) {
this._xGridDensity = horizontal;
this._yGridDensity = vertical;
};
Chart.prototype.setHorizontalLabels = function(labels) {
this._horizontalLabels = labels;
};
Chart.prototype.add = function(series) {
this._series.push(series);
};
Chart.prototype.draw = function() {
var i, o, o2, len, xlen, ymin, ymax, type, self, bLabels;
if (!this._painter) { return; }
/* Initialize */
this.xlen = 0;
this.ymin = this._yMin;
this.ymax = this._yMax;
/* Determine maximum number of values, ymin and ymax */
for (i = 0; i < this._series.length; i++) {
this._series[i].setRange(this);
}
/*
* For bar only charts the number of charts is the same as the length of the
* longest series, for others combinations it's one less. Compensate for that
* for bar only charts.
*/
//if (this._series.length == this._bars) {
this.xlen++;
this._xGridDensity++;
//}
/*
* Determine whatever or not to show the legend and axis labels
* Requires density and labels to be set.
*/
//bLabels = ((this._xGridDensity) && (this._yGridDensity) && (this._horizontalLabels.length >= this._xGridDensity));
bLabels = (this._xGridDensity) && (this._yGridDensity);
/* Initialize painter object */
this.init(this.xlen, this.ymin, this.ymax, this._xGridDensity, this._yGridDensity, bLabels);
/* Draw chart background */
this.drawBackground();
/*
* If labels and grid density where specified, draw legend and labels.
* It's drawn prior to the chart as the size of the legend and labels
* affects the size of the chart area.
*/
if (this._showLegend) { this.drawLegend(); }
if (bLabels) {
this.drawVerticalAxis(this._yGridDensity, this._labelPrecision);
this.drawHorizontalAxis(this.xlen, this._horizontalLabels, this._xGridDensity, this._labelPrecision);
}
/* Draw grid */
this.drawGrid();
/* Draw series */
for (i = 0; i < this._series.length; i++) {
this._series[i].draw(this);
}
/*
* Draw axis (after the series since the anti aliasing of the lines may
* otherwise be drawn on top of the axis)
*/
this.drawAxis();
};
Chart.prototype.init = function(xlen, ymin, ymax, xgd, ygd, bLegendLabels) {
this.w=this._painter.getWidth();
this.h=this._painter.getHeight();
this.chartx = 0;
this.chartw = this.w;
this.charth = this.h;
this.charty = 0;
this.xlen = xlen;
this.ymin = ymin;
this.ymax = ymax;
this.xgd = xgd;
this.ygd = ygd;
this.calc(this.chartw, this.charth, xlen, ymin, ymax, xgd, ygd);
};
Chart.prototype.calc = function(w, h, xlen, ymin, ymax, xgd, ygd) {
this.range = ymax - ymin;
this.xstep = w / (xlen - 1);
this.xgrid = (xgd)?w / (xgd - 1):0;
this.ygrid = (ygd)?h / (ygd - 1):0;
this.ymin = ymin;
this.ymax = ymax;
};
Chart.prototype.findSeries = function(label) {
for (var i = 0; i < this._series.length; i++) {
if (this._series[i].getLabel()==label) {
return this._series[i];
}
}
return null;
};
Chart.prototype.drawLegend = function() {
var legend, list, item, label;
var series=this._series;
legend = document.createElement('div');
legend.className = 'legend';
legend.style.position = 'absolute';
list = document.createElement('ul');
for (i = 0; i < series.length; i++) {
item = document.createElement('li');
item.style.color = series[i].getColor();
label = document.createElement('span');
label.appendChild(document.createTextNode(series[i].getLabel()));
label.style.color = 'black';
item.appendChild(label);
list.appendChild(item);
}
legend.appendChild(list);
this._cont.appendChild(legend);
legend.style.right = '0px';
legend.style.top = this.charty + (this.charth / 2) - (legend.offsetHeight / 2) + 'px';
this.legend = legend;
/* Recalculate chart width and position based on labels and legend */
this.chartw = this.w - (this.legend.offsetWidth + 5);
this.calc(this.chartw, this.charth, this.xlen, this.ymin, this.ymax, this.xgd, this.ygd);
};
Chart.prototype.drawVerticalAxis = function(ygd, precision) {
var axis, item, step, y, ty, n, yoffset, value, multiplier, w, items, pos;
/* Calculate step size and rounding precision */
multiplier = Math.pow(10, precision);
step = this.range / (ygd - 1);
/* Create container */
axis = document.createElement('div');
axis.style.position = 'absolute';
axis.style.left = '0px';
axis.style.top = '0px';
axis.style.textAlign = 'right';
this._cont.appendChild(axis);
/* Draw labels and points */
w = 0;
items = new Array();
for (n = 0, i = this.ymax; (i > this.ymin) && (n < ygd - 1); i -= step, n++) {
item = document.createElement('span');
value = parseInt(i * multiplier) / multiplier;
item.appendChild(document.createTextNode(value));
axis.appendChild(item);
items.push([i, item]);
if (item.offsetWidth > w) { w = item.offsetWidth; }
}
/* Draw last label and point (lower left corner of chart) */
item = document.createElement('span');
item.appendChild(document.createTextNode(this.ymin));
axis.appendChild(item);
items.push([this.ymin, item]);
if (item.offsetWidth > w) { w = item.offsetWidth; }
/* Set width of container to width of widest label */
axis.style.width = w + 'px';
/* Recalculate chart width and position based on labels and legend */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -