用JAVASCRIPT生成统计图

demo.html文件

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
 <head>
  <title>统计报表</title>
  <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
  <script type="text/javascript" src="chart.js"></script>
  <script type="text/javascript" src="wz_jsgraphics.js"></script>
  <script type="text/javascript" src="jgchartpainter.js"></script>
  <link rel="stylesheet" type="text/css" media="screen" href="canvaschart.css" />
  <style type="text/css">
   .chart { margin-left: 20px; }
  </style>

 </head>
 <body>
  <h3>宁波市重大危险源统计报表</h3>
  <p>
   <div id="chart"  class="chart" style="width: 900px; height: 400px;"></div>
  </p>
 </body>
</html>


<script>
function check(obj){
 for(i=0;i<obj.length;i++){ 
  if(obj[i]==''){
   obj[i]=0;
  }
 }
}

function demo() {
 
 var wxyb=new Array('10', '20', '30', '299', '79', '68', '250', '50', '40');
 var wxyc=new Array('10', '20', '30', '299', '79', '68', '250', '50', '67');
 var wxyd=new Array('10', '20', '30', '40', '50', '60', '70', '80', '90');
  var HorizontalLabels=new Array('1', '2', '3', '4', '5', '6', '7', '8', '9', '');
 
 var c = new Chart(document.getElementById('chart'));
 c.setDefaultType(CHART_STACKED);
 c.setGridDensity(HorizontalLabels.length, 31);//
 c.setVerticalRange(0, 300);
 c.setHorizontalLabels(HorizontalLabels);
 c.setBarWidth(10);
 c.add('','#FFFFFF', [0,0,0,0,0,0,0,0,0,0]);
 c.add('同意', '#B70606', wxyb, CHART_BAR);
 c.add('不同意', '#B7B106', wxyc, CHART_BAR);
 c.add('弃权', '#6206B7', wxyd, CHART_BAR);
 c.draw();
}

demo();
</script>
chart.js

var CHART_LINE    =  1;
var CHART_AREA    =  2;
var CHART_BAR     =  3;
var CHART_STACKED =  4;

/*----------------------------------------------------------------------------/
|                                    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._painterFactory   = function() {
  var canvas_enabled = false;
  var opera = navigator.userAgent.match(/opera[ //]/d+./d+/i);
  if (opera) {
   var opera_version = parseFloat(opera[0].match(//d+./d+/)[0]);
   if (opera_version >= 9) {
    canvas_enabled = true;
   }
  }
  var firefox = navigator.userAgent.match(/firefox///d+./d+/i);
  if (firefox) {
   var firefox_version = parseFloat(firefox[0].match(//d+./d+/)[0]);
   if (firefox_version >= 1.5) {
    canvas_enabled = true;
   }
  }
  if (canvas_enabled) {
   return new CanvasChartPainter();
  }
  else {
   return new JsGraphicsChartPainter();
  }
 }
}


Chart.prototype.setPainterFactory = function(f) {
 this._painterFactory = f;
};


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.setDefaultType = function(flags) {
 this._flags = flags;
};


Chart.prototype.setBarWidth = function(width) {
 this._barWidth = width;
};


Chart.prototype.setBarDistance = function(distance) {
 this._barDistance = distance;
};


Chart.prototype.add = function(label, color, values, flags) {
 var o, offset;

 if (!flags) { flags = this._flags; }
 if ((flags & CHART_BAR) == CHART_BAR) { offset = this._barDistance + this._bars * (this._barWidth + this._barDistance); this._bars++; }
 else { offset = 0; }
 o = new ChartSeries(label, color, values, flags, offset);

 this._series[this._series.length] = o;
};


Chart.prototype.draw = function() {
 var painter, i, o, o2, len, xlen, ymin, ymax, series, type, self, bLabels;

 /* Initialize */
 series = new Array();
 stackedSeries = new Array();
 xlen = 0;
 ymin = this._yMin;
 ymax = this._yMax;

 /* Separate stacked series (as they need processing). */
 for (i = 0; i < this._series.length; i++) {
  o = this._series[i]
  if ((o.flags & CHART_STACKED) == CHART_STACKED) { series[series.length] = o; }
 }

 /* Calculate values for stacked series */
 for (i = series.length - 2; i >= 0; i--) {
  o  = series[i].values;
  o2 = series[i+1].values;
  len = (o2.length > o.length)?o2.length:o.length;
  for (j = 0; j < len; j++) {
   if ((o[j]) && (!o2[j])) { continue; }
   if ((!o[j]) && (o2[j])) { o[j] = o2[j]; }
   else { o[j] = parseInt(o[j]) + parseFloat(o2[j]); }
 } }

 /* Append non-stacked series to list */
 for (i = 0; i < this._series.length; i++) {
  o = this._series[i]
  if ((o.flags & CHART_STACKED) != CHART_STACKED) { series[series.length] = o; }
 }

 /* Determine maximum number of values, ymin and ymax */
 for (i = 0; i < series.length; i++) {
  o = series[i]
  if (o.values.length > xlen) { xlen = o.values.length; }
  for (j = 0; j < o.values.length; j++) {
   if ((o.values[j] < ymin) || (ymin == null))  { ymin = o.values[j]; }
   if (o.values[j] > ymax) { ymax = o.values[j]; }
 } }

 /*
  * 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) {
  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));

 /* Create painter object */
 painter = this._painterFactory();
 painter.create(this._cont);

 /*
  * Delay initialization to give IE time to bind the
  * behavior to the canvas tag if IECanvas is used
  */
 self = this;
// window.setTimeout(function() {
  painter.init(xlen, ymin, ymax, self._xGridDensity, self._yGridDensity, bLabels);

  /* Draw chart */
  painter.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 (self._showLegend) { painter.drawLegend(series); }
  if (bLabels) {
   painter.drawVerticalAxis(self._yGridDensity, self._labelPrecision);
   painter.drawHorizontalAxis(xlen, self._horizontalLabels, self._xGridDensity, self._labelPrecision);
  }

  /* Draw chart */
  painter.drawChart();

  /* Draw series */
  for (i = 0; i < series.length; i++) {
   type = series[i].flags & ~CHART_STACKED;
   switch (type) {
    case CHART_LINE: painter.drawLine(series[i].color, series[i].values); break;
    case CHART_AREA: painter.drawArea(series[i].color, series[i].values); break;
    case CHART_BAR:  painter.drawBars(series[i].color, series[i].values, xlen-1, series[i].offset, self._barWidth); break;
    default: ;
   };
  }

  /*
   * Draw axis (after the series since the anti aliasing of the lines may
   * otherwise be drawn on top of the axis)
   */
  painter.drawAxis();
// }, (document.all)?500:0);

};


/*----------------------------------------------------------------------------/
|                                 ChartSeries                                 |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| Internal class for representing a series.                                   |
/----------------------------------------------------------------------------*/

function ChartSeries(label, color, values, flags, offset) {
 this.label  = label;
 this.color  = color;
 this.values = values;
 this.flags  = flags;
 this.offset = offset;
}


/*----------------------------------------------------------------------------/
|                            AbstractChartPainter                             |
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
| Abstract base class defining the painter API. Can not be used directly.     |
/----------------------------------------------------------------------------*/

function AbstractChartPainter() {

};


AbstractChartPainter.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;
};


AbstractChartPainter.prototype.create = function(el) {};
AbstractChartPainter.prototype.init = function(xlen, ymin, ymax, xgd, ygd, bLabels) {};
AbstractChartPainter.prototype.drawLegend = function(series) {};
AbstractChartPainter.prototype.drawVerticalAxis = function(ygd, precision) {};
AbstractChartPainter.prototype.drawHorizontalAxis = function(xlen, labels, xgd, precision) {};
AbstractChartPainter.prototype.drawAxis = function() {};
AbstractChartPainter.prototype.drawBackground = function() {};
AbstractChartPainter.prototype.drawChart = function() {};
AbstractChartPainter.prototype.drawArea = function(color, values) {};
AbstractChartPainter.prototype.drawLine = function(color, values) {};
AbstractChartPainter.prototype.drawBars = function(color, values, xlen, xoffset, width) {};

jgchartpainter.js
function JsGraphicsChartPainterFactory() {
 return new JsGraphicsChartPainter();
}


function JsGraphicsChartPainter() {
 this.base = AbstractChartPainter;
};


JsGraphicsChartPainter.prototype = new AbstractChartPainter;


JsGraphicsChartPainter.prototype.create = function(el) {
 while (el.firstChild) { el.removeChild(el.lastChild); }

 this.el = el;
 this.w = el.clientWidth;
 this.h = el.clientHeight;

 this.canvas = document.createElement('div');
 this.canvas.width  = this.w;
 this.canvas.height = this.h;
 this.canvas.style.width  = this.w + 'px';
 this.canvas.style.height = this.h + 'px';
 this.canvas.style.position = "relative";
 this.canvas.id = "canvas_" + el.id;

 el.appendChild(this.canvas);
};


JsGraphicsChartPainter.prototype.init = function(xlen, ymin, ymax, xgd, ygd, bLegendLabels) {
 this.ctx = new jsGraphics(this.canvas.id);

 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);
};


JsGraphicsChartPainter.prototype.drawLegend = function(series) {
 var legend, list, item, label;

 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].color;
  label = document.createElement('span');
  label.appendChild(document.createTextNode(series[i].label));
  label.style.color = 'black';
  item.appendChild(label);
  list.appendChild(item);
 }
 legend.appendChild(list);
 this.el.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);
};


JsGraphicsChartPainter.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.el.appendChild(axis);

 /* Draw labels and points */
 this.ctx.setColor('black');
 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[items.length] = new Array(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[items.length] = new Array(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 */
 this.chartx = w + 5;
 this.charty = item.offsetHeight / 2;
 this.charth = this.h - ((item.offsetHeight * 1.5) + 5);
 this.chartw = this.w - (((this.legend)?this.legend.offsetWidth:0) + w + 10);
 this.calc(this.chartw, this.charth, this.xlen, this.ymin, this.ymax, this.xgd, this.ygd);
 
 /* Position labels on the axis */
 n          = this.range / this.charth;
 yoffset    = (this.ymin / n);
 for (i = 0; i < items.length; i++) {
  item = items[i][1];
  pos = items[i][0];
  if (pos == this.ymin) { y = this.charty + this.charth - 1; }
  else { y = this.charty + (this.charth - (pos / n) + yoffset); }
  this.ctx.drawLine(this.chartx - 5, y, this.chartx, y);
  ty = y - (item.offsetHeight/2);
  item.style.position = 'absolute';
  item.style.right = '0px';
  item.style.top   = ty + 'px';
} };

JsGraphicsChartPainter.prototype.drawHorizontalAxis = function(xlen, labels, xgd, precision) {
 var axis, item, step, x, tx, y1, y2, n, multiplier;

 /* Calculate offset, step size and rounding precision */
 multiplier = Math.pow(10, precision);
 n          = this.chartw / (xgd - 1);

 /* Create container */
 axis = document.createElement('div');
 axis.style.position = 'absolute';
 axis.style.left   = '0px';
 axis.style.top    = (this.charty + this.charth + 5) + 'px';
 axis.style.width  = this.w + 'px';
 this.el.appendChild(axis);

 /* Draw labels and points */
 this.ctx.setColor('black');
 y1 = this.charty + this.charth;
 y2 = this.charty + this.charth + 5;
 for (i = 0; i < xgd; i++) {
  item = document.createElement('span');
  item.appendChild(document.createTextNode(labels[i]));
  axis.appendChild(item);
  x = this.chartx + (n * i);
  tx = x - (item.offsetWidth/2)
  item.style.position = 'absolute';
  item.style.left = tx + 'px';
  item.style.top  = '0px';
  this.ctx.drawLine(x, y1, x, y2);
} };


JsGraphicsChartPainter.prototype.drawAxis = function() {
    var x1, x2, y1, y2;
 this.ctx.setColor('black');
 x1 = this.chartx;
 x2 = this.chartx + this.chartw + 1;
 y1 = this.charty;
 y2 = this.charty + this.charth - 1;
 this.ctx.drawLine(x1, y1, x1, y2);
 this.ctx.drawLine(x1, y2, x2, y2);
 this.ctx.paint();
};


JsGraphicsChartPainter.prototype.drawBackground = function() {
 this.ctx.setColor('white');
 this.ctx.fillRect(0, 0, this.w, this.h);
};


JsGraphicsChartPainter.prototype.drawChart = function() {
 this.ctx.setColor('silver');
 if (this.xgrid) {
  for (i = this.xgrid; i < this.chartw; i += this.xgrid) {
   this.ctx.drawLine(this.chartx + i, this.charty, this.chartx + i, this.charty + this.charth - 1);
 } }
 if (this.ygrid) {
  for (i = this.charth - this.ygrid; i > 0; i -= this.ygrid) {
   this.ctx.drawLine(this.chartx + 1, this.charty + i, this.chartx + this.chartw + 1, this.charty + i);
} } };


JsGraphicsChartPainter.prototype.drawArea = function(color, values) {
 var i, len, x, y, n, yoffset;
 var XPoints = new Array();
 var YPoints = new Array();

 /* Determine distance between points and offset */
 n = this.range / this.charth;
 yoffset = (this.ymin / n);

 len = values.length;
 if (len) {
  this.ctx.setColor(color);

  x = this.chartx + 1;
  y = this.charty + this.charth - 1;
  XPoints[XPoints.length] = x;
  YPoints[YPoints.length] = y;

  y = this.charty + this.charth - (values[0] / n) + yoffset;
  XPoints[XPoints.length] = x;
  YPoints[YPoints.length] = y;

  for (i = 1; i < len; i++) {
   y = this.charty + this.charth - (values[i] / n) + yoffset;
   x += this.xstep;
   XPoints[XPoints.length] = x;
   YPoints[YPoints.length] = y;
  }

  XPoints[XPoints.length] = x;
  YPoints[YPoints.length] = this.charty + this.charth - 1;
  
  this.ctx.fillPolygon(XPoints, YPoints);
} };


JsGraphicsChartPainter.prototype.drawLine = function(color, values) {
 var i, len, x1, y1, x2, y2, n, yoffset;

 n = this.range / this.charth;
 yoffset = (this.ymin / n);

 len = values.length;
 if (len) {
  this.ctx.setStroke(1);
  this.ctx.setColor(color);
  x1 = this.chartx + 1;
  y1 = this.charty + this.charth - (values[0] / n) + yoffset;

  for (i = 1; i < len; i++) {
   y2 = this.charty + this.charth - (values[i] / n) + yoffset;
   x2 = x1 + this.xstep;
   this.ctx.drawLine(x1, y1, x2, y2);
   x1 = x2;
   y1 = y2;
  }

} };


JsGraphicsChartPainter.prototype.drawBars = function(color, values, xlen, xoffset, width) {
 var i, len, x, y, n, yoffset;

 n = this.range / this.charth;
 yoffset = (this.ymin / n);

 len = values.length;
 if (len > xlen) { len = xlen; }
 if (len) {
  this.ctx.setColor(color);
  x = this.chartx + xoffset + 1;
  for (i = 0; i < len; i++) {
   y = this.charty + this.charth - (values[i] / n) + yoffset;
   this.ctx.fillRect(x, y, width, this.charty + this.charth - y);
   x += this.xstep;
} } };

wz_jsgraphics.js
var jg_ihtm, jg_ie, jg_fast, jg_dom, jg_moz,
jg_n4 = (document.layers && typeof document.classes != "undefined");


function chkDHTM(x, i)
{
 x = document.body || null;
 jg_ie = x && typeof x.insertAdjacentHTML != "undefined";
 jg_dom = (x && !jg_ie &&
  typeof x.appendChild != "undefined" &&
  typeof document.createRange != "undefined" &&
  typeof (i = document.createRange()).setStartBefore != "undefined" &&
  typeof i.createContextualFragment != "undefined");
 jg_ihtm = !jg_ie && !jg_dom && x && typeof x.innerHTML != "undefined";
 jg_fast = jg_ie && document.all && !window.opera;
 jg_moz = jg_dom && typeof x.style.MozOpacity != "undefined";
}


function pntDoc()
{
 this.wnd.document.write(jg_fast? this.htmRpc() : this.htm);
 this.htm = '';
}


function pntCnvDom()
{
 var x = document.createRange();
 x.setStartBefore(this.cnv);
 x = x.createContextualFragment(jg_fast? this.htmRpc() : this.htm);
 this.cnv.appendChild(x);
 this.htm = '';
}


function pntCnvIe()
{
 this.cnv.insertAdjacentHTML("BeforeEnd", jg_fast? this.htmRpc() : this.htm);
 this.htm = '';
}


function pntCnvIhtm()
{
 this.cnv.innerHTML += this.htm;
 this.htm = '';
}


function pntCnv()
{
 this.htm = '';
}


function mkDiv(x, y, w, h)
{
 this.htm += '<div style="position:absolute;'+
  'left:' + x + 'px;'+
  'top:' + y + 'px;'+
  'width:' + w + 'px;'+
  'height:' + h + 'px;'+
  'clip:rect(0,'+w+'px,'+h+'px,0);'+
  'background-color:' + this.color +
  (!jg_moz? ';overflow:hidden' : '')+
  ';"><//div>';
}


function mkDivIe(x, y, w, h)
{
 this.htm += '%%'+this.color+';'+x+';'+y+';'+w+';'+h+';';
}


function mkDivPrt(x, y, w, h)
{
 this.htm += '<div style="position:absolute;'+
  'border-left:' + w + 'px solid ' + this.color + ';'+
  'left:' + x + 'px;'+
  'top:' + y + 'px;'+
  'width:0px;'+
  'height:' + h + 'px;'+
  'clip:rect(0,'+w+'px,'+h+'px,0);'+
  'background-color:' + this.color +
  (!jg_moz? ';overflow:hidden' : '')+
  ';"><//div>';
}


function mkLyr(x, y, w, h)
{
 this.htm += '<layer '+
  'left="' + x + '" '+
  'top="' + y + '" '+
  'width="' + w + '" '+
  'height="' + h + '" '+
  'bgcolor="' + this.color + '"><//layer>/n';
}


var regex =  /%%([^;]+);([^;]+);([^;]+);([^;]+);([^;]+);/g;
function htmRpc()
{
 return this.htm.replace(
  regex,
  '<div style="overflow:hidden;position:absolute;background-color:'+
  '$1;left:$2;top:$3;width:$4;height:$5"></div>/n');
}


function htmPrtRpc()
{
 return this.htm.replace(
  regex,
  '<div style="overflow:hidden;position:absolute;background-color:'+
  '$1;left:$2;top:$3;width:$4;height:$5;border-left:$4px solid $1"></div>/n');
}


function mkLin(x1, y1, x2, y2)
{
 if (x1 > x2)
 {
  var _x2 = x2;
  var _y2 = y2;
  x2 = x1;
  y2 = y1;
  x1 = _x2;
  y1 = _y2;
 }
 var dx = x2-x1, dy = Math.abs(y2-y1),
 x = x1, y = y1,
 yIncr = (y1 > y2)? -1 : 1;

 if (dx >= dy)
 {
  var pr = dy<<1,
  pru = pr - (dx<<1),
  p = pr-dx,
  ox = x;
  while ((dx--) > 0)
  {
   ++x;
   if (p > 0)
   {
    this.mkDiv(ox, y, x-ox, 1);
    y += yIncr;
    p += pru;
    ox = x;
   }
   else p += pr;
  }
  this.mkDiv(ox, y, x2-ox+1, 1);
 }

 else
 {
  var pr = dx<<1,
  pru = pr - (dy<<1),
  p = pr-dy,
  oy = y;
  if (y2 <= y1)
  {
   while ((dy--) > 0)
   {
    if (p > 0)
    {
     this.mkDiv(x++, y, 1, oy-y+1);
     y += yIncr;
     p += pru;
     oy = y;
    }
    else
    {
     y += yIncr;
     p += pr;
    }
   }
   this.mkDiv(x2, y2, 1, oy-y2+1);
  }
  else
  {
   while ((dy--) > 0)
   {
    y += yIncr;
    if (p > 0)
    {
     this.mkDiv(x++, oy, 1, y-oy);
     p += pru;
     oy = y;
    }
    else p += pr;
   }
   this.mkDiv(x2, oy, 1, y2-oy+1);
  }
 }
}


function mkLin2D(x1, y1, x2, y2)
{
 if (x1 > x2)
 {
  var _x2 = x2;
  var _y2 = y2;
  x2 = x1;
  y2 = y1;
  x1 = _x2;
  y1 = _y2;
 }
 var dx = x2-x1, dy = Math.abs(y2-y1),
 x = x1, y = y1,
 yIncr = (y1 > y2)? -1 : 1;

 var s = this.stroke;
 if (dx >= dy)
 {
  if (dx > 0 && s-3 > 0)
  {
   var _s = (s*dx*Math.sqrt(1+dy*dy/(dx*dx))-dx-(s>>1)*dy) / dx;
   _s = (!(s-4)? Math.ceil(_s) : Math.round(_s)) + 1;
  }
  else var _s = s;
  var ad = Math.ceil(s/2);

  var pr = dy<<1,
  pru = pr - (dx<<1),
  p = pr-dx,
  ox = x;
  while ((dx--) > 0)
  {
   ++x;
   if (p > 0)
   {
    this.mkDiv(ox, y, x-ox+ad, _s);
    y += yIncr;
    p += pru;
    ox = x;
   }
   else p += pr;
  }
  this.mkDiv(ox, y, x2-ox+ad+1, _s);
 }

 else
 {
  if (s-3 > 0)
  {
   var _s = (s*dy*Math.sqrt(1+dx*dx/(dy*dy))-(s>>1)*dx-dy) / dy;
   _s = (!(s-4)? Math.ceil(_s) : Math.round(_s)) + 1;
  }
  else var _s = s;
  var ad = Math.round(s/2);

  var pr = dx<<1,
  pru = pr - (dy<<1),
  p = pr-dy,
  oy = y;
  if (y2 <= y1)
  {
   ++ad;
   while ((dy--) > 0)
   {
    if (p > 0)
    {
     this.mkDiv(x++, y, _s, oy-y+ad);
     y += yIncr;
     p += pru;
     oy = y;
    }
    else
    {
     y += yIncr;
     p += pr;
    }
   }
   this.mkDiv(x2, y2, _s, oy-y2+ad);
  }
  else
  {
   while ((dy--) > 0)
   {
    y += yIncr;
    if (p > 0)
    {
     this.mkDiv(x++, oy, _s, y-oy+ad);
     p += pru;
     oy = y;
    }
    else p += pr;
   }
   this.mkDiv(x2, oy, _s, y2-oy+ad+1);
  }
 }
}


function mkLinDott(x1, y1, x2, y2)
{
 if (x1 > x2)
 {
  var _x2 = x2;
  var _y2 = y2;
  x2 = x1;
  y2 = y1;
  x1 = _x2;
  y1 = _y2;
 }
 var dx = x2-x1, dy = Math.abs(y2-y1),
 x = x1, y = y1,
 yIncr = (y1 > y2)? -1 : 1,
 drw = true;
 if (dx >= dy)
 {
  var pr = dy<<1,
  pru = pr - (dx<<1),
  p = pr-dx;
  while ((dx--) > 0)
  {
   if (drw) this.mkDiv(x, y, 1, 1);
   drw = !drw;
   if (p > 0)
   {
    y += yIncr;
    p += pru;
   }
   else p += pr;
   ++x;
  }
  if (drw) this.mkDiv(x, y, 1, 1);
 }

 else
 {
  var pr = dx<<1,
  pru = pr - (dy<<1),
  p = pr-dy;
  while ((dy--) > 0)
  {
   if (drw) this.mkDiv(x, y, 1, 1);
   drw = !drw;
   y += yIncr;
   if (p > 0)
   {
    ++x;
    p += pru;
   }
   else p += pr;
  }
  if (drw) this.mkDiv(x, y, 1, 1);
 }
}


function mkOv(left, top, width, height)
{
 var a = width>>1, b = height>>1,
 wod = width&1, hod = (height&1)+1,
 cx = left+a, cy = top+b,
 x = 0, y = b,
 ox = 0, oy = b,
 aa = (a*a)<<1, bb = (b*b)<<1,
 st = (aa>>1)*(1-(b<<1)) + bb,
 tt = (bb>>1) - aa*((b<<1)-1),
 w, h;
 while (y > 0)
 {
  if (st < 0)
  {
   st += bb*((x<<1)+3);
   tt += (bb<<1)*(++x);
  }
  else if (tt < 0)
  {
   st += bb*((x<<1)+3) - (aa<<1)*(y-1);
   tt += (bb<<1)*(++x) - aa*(((y--)<<1)-3);
   w = x-ox;
   h = oy-y;
   if (w&2 && h&2)
   {
    this.mkOvQds(cx, cy, -x+2, ox+wod, -oy, oy-1+hod, 1, 1);
    this.mkOvQds(cx, cy, -x+1, x-1+wod, -y-1, y+hod, 1, 1);
   }
   else this.mkOvQds(cx, cy, -x+1, ox+wod, -oy, oy-h+hod, w, h);
   ox = x;
   oy = y;
  }
  else
  {
   tt -= aa*((y<<1)-3);
   st -= (aa<<1)*(--y);
  }
 }
 this.mkDiv(cx-a, cy-oy, a-ox+1, (oy<<1)+hod);
 this.mkDiv(cx+ox+wod, cy-oy, a-ox+1, (oy<<1)+hod);
}


function mkOv2D(left, top, width, height)
{
 var s = this.stroke;
 width += s-1;
 height += s-1;
 var a = width>>1, b = height>>1,
 wod = width&1, hod = (height&1)+1,
 cx = left+a, cy = top+b,
 x = 0, y = b,
 aa = (a*a)<<1, bb = (b*b)<<1,
 st = (aa>>1)*(1-(b<<1)) + bb,
 tt = (bb>>1) - aa*((b<<1)-1);

 if (s-4 < 0 && (!(s-2) || width-51 > 0 && height-51 > 0))
 {
  var ox = 0, oy = b,
  w, h,
  pxl, pxr, pxt, pxb, pxw;
  while (y > 0)
  {
   if (st < 0)
   {
    st += bb*((x<<1)+3);
    tt += (bb<<1)*(++x);
   }
   else if (tt < 0)
   {
    st += bb*((x<<1)+3) - (aa<<1)*(y-1);
    tt += (bb<<1)*(++x) - aa*(((y--)<<1)-3);
    w = x-ox;
    h = oy-y;

    if (w-1)
    {
     pxw = w+1+(s&1);
     h = s;
    }
    else if (h-1)
    {
     pxw = s;
     h += 1+(s&1);
    }
    else pxw = h = s;
    this.mkOvQds(cx, cy, -x+1, ox-pxw+w+wod, -oy, -h+oy+hod, pxw, h);
    ox = x;
    oy = y;
   }
   else
   {
    tt -= aa*((y<<1)-3);
    st -= (aa<<1)*(--y);
   }
  }
  this.mkDiv(cx-a, cy-oy, s, (oy<<1)+hod);
  this.mkDiv(cx+a+wod-s+1, cy-oy, s, (oy<<1)+hod);
 }

 else
 {
  var _a = (width-((s-1)<<1))>>1,
  _b = (height-((s-1)<<1))>>1,
  _x = 0, _y = _b,
  _aa = (_a*_a)<<1, _bb = (_b*_b)<<1,
  _st = (_aa>>1)*(1-(_b<<1)) + _bb,
  _tt = (_bb>>1) - _aa*((_b<<1)-1),

  pxl = new Array(),
  pxt = new Array(),
  _pxb = new Array();
  pxl[0] = 0;
  pxt[0] = b;
  _pxb[0] = _b-1;
  while (y > 0)
  {
   if (st < 0)
   {
    st += bb*((x<<1)+3);
    tt += (bb<<1)*(++x);
    pxl[pxl.length] = x;
    pxt[pxt.length] = y;
   }
   else if (tt < 0)
   {
    st += bb*((x<<1)+3) - (aa<<1)*(y-1);
    tt += (bb<<1)*(++x) - aa*(((y--)<<1)-3);
    pxl[pxl.length] = x;
    pxt[pxt.length] = y;
   }
   else
   {
    tt -= aa*((y<<1)-3);
    st -= (aa<<1)*(--y);
   }

   if (_y > 0)
   {
    if (_st < 0)
    {
     _st += _bb*((_x<<1)+3);
     _tt += (_bb<<1)*(++_x);
     _pxb[_pxb.length] = _y-1;
    }
    else if (_tt < 0)
    {
     _st += _bb*((_x<<1)+3) - (_aa<<1)*(_y-1);
     _tt += (_bb<<1)*(++_x) - _aa*(((_y--)<<1)-3);
     _pxb[_pxb.length] = _y-1;
    }
    else
    {
     _tt -= _aa*((_y<<1)-3);
     _st -= (_aa<<1)*(--_y);
     _pxb[_pxb.length-1]--;
    }
   }
  }

  var ox = 0, oy = b,
  _oy = _pxb[0],
  l = pxl.length,
  w, h;
  for (var i = 0; i < l; i++)
  {
   if (typeof _pxb[i] != "undefined")
   {
    if (_pxb[i] < _oy || pxt[i] < oy)
    {
     x = pxl[i];
     this.mkOvQds(cx, cy, -x+1, ox+wod, -oy, _oy+hod, x-ox, oy-_oy);
     ox = x;
     oy = pxt[i];
     _oy = _pxb[i];
    }
   }
   else
   {
    x = pxl[i];
    this.mkDiv(cx-x+1, cy-oy, 1, (oy<<1)+hod);
    this.mkDiv(cx+ox+wod, cy-oy, 1, (oy<<1)+hod);
    ox = x;
    oy = pxt[i];
   }
  }
  this.mkDiv(cx-a, cy-oy, 1, (oy<<1)+hod);
  this.mkDiv(cx+ox+wod, cy-oy, 1, (oy<<1)+hod);
 }
}


function mkOvDott(left, top, width, height)
{
 var a = width>>1, b = height>>1,
 wod = width&1, hod = height&1,
 cx = left+a, cy = top+b,
 x = 0, y = b,
 aa2 = (a*a)<<1, aa4 = aa2<<1, bb = (b*b)<<1,
 st = (aa2>>1)*(1-(b<<1)) + bb,
 tt = (bb>>1) - aa2*((b<<1)-1),
 drw = true;
 while (y > 0)
 {
  if (st < 0)
  {
   st += bb*((x<<1)+3);
   tt += (bb<<1)*(++x);
  }
  else if (tt < 0)
  {
   st += bb*((x<<1)+3) - aa4*(y-1);
   tt += (bb<<1)*(++x) - aa2*(((y--)<<1)-3);
  }
  else
  {
   tt -= aa2*((y<<1)-3);
   st -= aa4*(--y);
  }
  if (drw) this.mkOvQds(cx, cy, -x, x+wod, -y, y+hod, 1, 1);
  drw = !drw;
 }
}


function mkRect(x, y, w, h)
{
 var s = this.stroke;
 this.mkDiv(x, y, w, s);
 this.mkDiv(x+w, y, s, h);
 this.mkDiv(x, y+h, w+s, s);
 this.mkDiv(x, y+s, s, h-s);
}


function mkRectDott(x, y, w, h)
{
 this.drawLine(x, y, x+w, y);
 this.drawLine(x+w, y, x+w, y+h);
 this.drawLine(x, y+h, x+w, y+h);
 this.drawLine(x, y, x, y+h);
}


function jsgFont()
{
 this.PLAIN = 'font-weight:normal;';
 this.BOLD = 'font-weight:bold;';
 this.ITALIC = 'font-style:italic;';
 this.ITALIC_BOLD = this.ITALIC + this.BOLD;
 this.BOLD_ITALIC = this.ITALIC_BOLD;
}
var Font = new jsgFont();


function jsgStroke()
{
 this.DOTTED = -1;
}
var Stroke = new jsgStroke();


function jsGraphics(id, wnd)
{
 this.setColor = new Function('arg', 'this.color = arg.toLowerCase();');

 this.setStroke = function(x)
 {
  this.stroke = x;
  if (!(x+1))
  {
   this.drawLine = mkLinDott;
   this.mkOv = mkOvDott;
   this.drawRect = mkRectDott;
  }
  else if (x-1 > 0)
  {
   this.drawLine = mkLin2D;
   this.mkOv = mkOv2D;
   this.drawRect = mkRect;
  }
  else
  {
   this.drawLine = mkLin;
   this.mkOv = mkOv;
   this.drawRect = mkRect;
  }
 };


 this.setPrintable = function(arg)
 {
  this.printable = arg;
  if (jg_fast)
  {
   this.mkDiv = mkDivIe;
   this.htmRpc = arg? htmPrtRpc : htmRpc;
  }
  else this.mkDiv = jg_n4? mkLyr : arg? mkDivPrt : mkDiv;
 };


 this.setFont = function(fam, sz, sty)
 {
  this.ftFam = fam;
  this.ftSz = sz;
  this.ftSty = sty || Font.PLAIN;
 };


 this.drawPolyline = this.drawPolyLine = function(x, y, s)
 {
  for (var i=0 ; i<x.length-1 ; i++ )
   this.drawLine(x[i], y[i], x[i+1], y[i+1]);
 };


 this.fillRect = function(x, y, w, h)
 {
  this.mkDiv(x, y, w, h);
 };


 this.drawPolygon = function(x, y)
 {
  this.drawPolyline(x, y);
  this.drawLine(x[x.length-1], y[x.length-1], x[0], y[0]);
 };


 this.drawEllipse = this.drawOval = function(x, y, w, h)
 {
  this.mkOv(x, y, w, h);
 };


 this.fillEllipse = this.fillOval = function(left, top, w, h)
 {
  var a = (w -= 1)>>1, b = (h -= 1)>>1,
  wod = (w&1)+1, hod = (h&1)+1,
  cx = left+a, cy = top+b,
  x = 0, y = b,
  ox = 0, oy = b,
  aa2 = (a*a)<<1, aa4 = aa2<<1, bb = (b*b)<<1,
  st = (aa2>>1)*(1-(b<<1)) + bb,
  tt = (bb>>1) - aa2*((b<<1)-1),
  pxl, dw, dh;
  if (w+1) while (y > 0)
  {
   if (st < 0)
   {
    st += bb*((x<<1)+3);
    tt += (bb<<1)*(++x);
   }
   else if (tt < 0)
   {
    st += bb*((x<<1)+3) - aa4*(y-1);
    pxl = cx-x;
    dw = (x<<1)+wod;
    tt += (bb<<1)*(++x) - aa2*(((y--)<<1)-3);
    dh = oy-y;
    this.mkDiv(pxl, cy-oy, dw, dh);
    this.mkDiv(pxl, cy+y+hod, dw, dh);
    ox = x;
    oy = y;
   }
   else
   {
    tt -= aa2*((y<<1)-3);
    st -= aa4*(--y);
   }
  }
  this.mkDiv(cx-a, cy-oy, w+1, (oy<<1)+hod);
 };


/* fillPolygon method, implemented by Matthieu Haller.
This javascript function is an adaptation of the gdImageFilledPolygon for Walter Zorn lib.
C source of GD 1.8.4 found at http://www.boutell.com/gd/

THANKS to Kirsten Schulz for the polygon fixes!

The intersection finding technique of this code could be improved
by remembering the previous intertersection, and by using the slope.
That could help to adjust intersections to produce a nice
interior_extrema. */
 this.fillPolygon = function(array_x, array_y)
 {
  var i;
  var y;
  var miny, maxy;
  var x1, y1;
  var x2, y2;
  var ind1, ind2;
  var ints;

  var n = array_x.length;

  if (!n) return;


  miny = array_y[0];
  maxy = array_y[0];
  for (i = 1; i < n; i++)
  {
   if (array_y[i] < miny)
    miny = array_y[i];

   if (array_y[i] > maxy)
    maxy = array_y[i];
  }
  for (y = miny; y <= maxy; y++)
  {
   var polyInts = new Array();
   ints = 0;
   for (i = 0; i < n; i++)
   {
    if (!i)
    {
     ind1 = n-1;
     ind2 = 0;
    }
    else
    {
     ind1 = i-1;
     ind2 = i;
    }
    y1 = array_y[ind1];
    y2 = array_y[ind2];
    if (y1 < y2)
    {
     x1 = array_x[ind1];
     x2 = array_x[ind2];
    }
    else if (y1 > y2)
    {
     y2 = array_y[ind1];
     y1 = array_y[ind2];
     x2 = array_x[ind1];
     x1 = array_x[ind2];
    }
    else continue;

     // modified 11. 2. 2004 Walter Zorn
    if ((y >= y1) && (y < y2))
     polyInts[ints++] = Math.round((y-y1) * (x2-x1) / (y2-y1) + x1);

    else if ((y == maxy) && (y > y1) && (y <= y2))
     polyInts[ints++] = Math.round((y-y1) * (x2-x1) / (y2-y1) + x1);
   }
   polyInts.sort(integer_compare);
   for (i = 0; i < ints; i+=2)
    this.mkDiv(polyInts[i], y, polyInts[i+1]-polyInts[i]+1, 1);
  }
 };


 this.drawString = function(txt, x, y)
 {
  this.htm += '<div style="position:absolute;white-space:nowrap;'+
   'left:' + x + 'px;'+
   'top:' + y + 'px;'+
   'font-family:' +  this.ftFam + ';'+
   'font-size:' + this.ftSz + ';'+
   'color:' + this.color + ';' + this.ftSty + '">'+
   txt +
   '<//div>';
 };


/* drawStringRect() added by Rick Blommers.
Allows to specify the size of the text rectangle and to align the
text both horizontally (e.g. right) and vertically within that rectangle */
 this.drawStringRect = function(txt, x, y, width, halign)
 {
  this.htm += '<div style="position:absolute;overflow:hidden;'+
   'left:' + x + 'px;'+
   'top:' + y + 'px;'+
   'width:'+width +'px;'+
   'text-align:'+halign+';'+
   'font-family:' +  this.ftFam + ';'+
   'font-size:' + this.ftSz + ';'+
   'color:' + this.color + ';' + this.ftSty + '">'+
   txt +
   '<//div>';
 };


 this.drawImage = function(imgSrc, x, y, w, h, a)
 {
  this.htm += '<div style="position:absolute;'+
   'left:' + x + 'px;'+
   'top:' + y + 'px;'+
   'width:' +  w + ';'+
   'height:' + h + ';">'+
   '<img src="' + imgSrc + '" width="' + w + '" height="' + h + '"' + (a? (' '+a) : '') + '>'+
   '<//div>';
 };


 this.clear = function()
 {
  this.htm = "";
  if (this.cnv) this.cnv.innerHTML = this.defhtm;
 };


 this.mkOvQds = function(cx, cy, xl, xr, yt, yb, w, h)
 {
  this.mkDiv(xr+cx, yt+cy, w, h);
  this.mkDiv(xr+cx, yb+cy, w, h);
  this.mkDiv(xl+cx, yb+cy, w, h);
  this.mkDiv(xl+cx, yt+cy, w, h);
 };

 this.setStroke(1);
 this.setFont('verdana,geneva,helvetica,sans-serif', String.fromCharCode(0x31, 0x32, 0x70, 0x78), Font.PLAIN);
 this.color = '#000000';
 this.htm = '';
 this.wnd = wnd || window;

 if (!(jg_ie || jg_dom || jg_ihtm)) chkDHTM();
 if (typeof id != 'string' || !id) this.paint = pntDoc;
 else
 {
  this.cnv = document.all? (this.wnd.document.all[id] || null)
   : document.getElementById? (this.wnd.document.getElementById(id) || null)
   : null;
  this.defhtm = (this.cnv && this.cnv.innerHTML)? this.cnv.innerHTML : '';
  this.paint = jg_dom? pntCnvDom : jg_ie? pntCnvIe : jg_ihtm? pntCnvIhtm : pntCnv;
 }

 this.setPrintable(false);
}

 

function integer_compare(x,y)
{
 return (x < y) ? -1 : ((x > y)*1);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值