if( typeof html5jp == 'undefined' ) { html5jp = new Object(); } if( typeof html5jp.graph == 'undefined' ) { html5jp.graph = new Object(); } html5jp.graph.line = function (id) { var elm = document.getElementById(id); if(! elm) { return; } if(elm.nodeName != "CANVAS") { return; } if(elm.parentNode.nodeName != "DIV") { return; }; this.canvas = elm; if ( ! this.canvas ){ return; } if ( ! this.canvas.getContext ){ return; } this.ctx = this.canvas.getContext('2d'); this.canvas.style.margin = "0"; this.canvas.parentNode.style.position = "relative"; this.canvas.parentNode.style.padding = "0"; }; html5jp.graph.line.prototype.draw = function(items, inparams) { if( ! this.ctx ) {return;} var params = { x: [], y: [], yMax: null, yMin: 0, backgroundColor: "#ffffff", gbackgroundColor: "#ffffff",//dddddd gGradation: true, lineWidth: 1, dotRadius: 3, dotType: "disc", hLineWidth: 1, hLineType: "dotted", hLineColor: "#eeeeee", xAxisWidth: 1, xAxisColor: "#000000", yAxisWidth: 1, yAxisColor: "#000000", xScaleColor: "#000000", xScaleFontSize: "10px", xScaleFontFamily: "Arial,sans-serif", yScaleColor: "#000000", yScaleFontSize: "10px", yScaleFontFamily: "Arial,sans-serif", xCaptionColor: "#000000", xCaptionFontSize: "12px", xCaptionFontFamily: "Arial,sans-serif", yCaptionColor: "#000000", yCaptionFontSize: "12px", yCaptionFontFamily: "Arial,sans-serif", dLabel: true, dLabelColor: "#000000", dLabelFontSize: "10px", dLabelFontFamily: "Arial,sans-serif", legend: true, legendFontSize: "12px", legendFontFamily: "Arial,sans-serif", legendColor: "#000000" }; if( inparams && typeof(inparams) == 'object' ) { for( var key in inparams ) { params[key] = inparams[key]; } } this.params = params; if( params.backgroundColor ) { this.ctx.beginPath(); this.ctx.fillStyle = params.backgroundColor; this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); } if(this.canvas.width / this.canvas.height < 1.5 || this.canvas.height < 200) { params.legend == false; } var canvas_pos = this._getElementAbsPos(this.canvas); var cpos = { x0: this.canvas.width * 0.1, y0: this.canvas.height * 0.9, x1: this.canvas.width * 0.9, y1: this.canvas.height * 0.1 }; if( typeof(params.x) == "object" && params.x.length > 0) { cpos.y0 = this.canvas.height * 0.8; } if( typeof(params.y) == "object" && params.y.length > 0) { cpos.x0 = this.canvas.width * 0.15; cpos.y1 = this.canvas.height * 0.15 } if(params.legend == true) { cpos.x1 = this.canvas.width * 0.7; } cpos.w = cpos.x1 - cpos.x0; cpos.h = cpos.y0 - cpos.y1; var item_num = items.length; if(item_num > 10) { item_num = 10; } if(params.legend == true) { var legend_tmp_s = this._getTextBoxSize('あTEST', params.legendFontSize, params.legendFontFamily); var lpos = { x: Math.round( cpos.x1 + this.canvas.width * 0.03 ), y: Math.round( ( this.canvas.height - ( legend_tmp_s.h * item_num + legend_tmp_s.h * 0.2 * (item_num - 1) ) ) / 2 ), h: legend_tmp_s.h }; lpos.cx = lpos.x + Math.round( lpos.h * 2.5 ); lpos.cw = this.canvas.width - lpos.cx; } if(params.gGradation == true) { this.ctx.beginPath(); this.ctx.moveTo(cpos.x0, cpos.y0); this.ctx.lineTo(cpos.x1, cpos.y0); this.ctx.lineTo(cpos.x1, cpos.y1); this.ctx.lineTo(cpos.x0, cpos.y1); this.ctx.closePath(); var radgrad = this.ctx.createLinearGradient(cpos.x0,cpos.y1,cpos.x0,cpos.y0); var o_gbc = this._csscolor2rgb(params.gbackgroundColor); var gbc = o_gbc.r + "," + o_gbc.g + "," + o_gbc.b; radgrad.addColorStop(0, "rgb(" + gbc + ")"); radgrad.addColorStop(1, "rgb(255,255,255)"); this.ctx.fillStyle = radgrad; this.ctx.fill(); } else { this.ctx.fillStyle = params.gbackgroundColor; this.ctx.fillRect(cpos.x0, cpos.y1, cpos.w, cpos.h); } var max_v = null; var min_v = null; var max_n = 0; if(params.y.length > 1) { max = params.y[ params.y.length - 1 ]; } for(var i=0; i= max_v) { max_v = v; } if(min_v == null) { min_v = v; } else if(v <= min_v) { min_v = v; } } if(n - 1 >= max_n) { max_n = n - 1; } } if( typeof(params.yMin) != "number" ) { params.yMin = 0; } if( typeof(params.yMax) != "number" ) { params.yMax = max_v + Math.abs(max_v - min_v) * 0.1; } var v_range = Math.abs( params.yMax - params.yMin ); if( typeof(params.hLineWidth) == "number" && params.hLineWidth > 0 ) { var h_line_type = "dashed"; if( params.hLineType.match(/^(solid|dashed|dotted)$/i) ) { h_line_type = params.hLineType; } for(var i=1; i 0 ) { dot_rad = params.dotRadius[i]; } else if( typeof(params.dotRadius) == "number" && ! isNaN(params.dotRadius) && params.dotRadius > 0 ) { dot_rad = params.dotRadius; } var dot_type = null; if( typeof(params.dotType) == "object" && typeof(params.dotType[i]) == "string" ) { dot_type = params.dotType[i]; } else if( typeof(params.dotType) == "string" ) { dot_type = params.dotType; } else { dot_type = "disc"; } if(dot_rad > 0) { for(var k=0; k cpos.x1 || plots[i][k].y > cpos.y0 || plots[i][k].y < cpos.y1) { continue; } var dlabel = plots[i][k].v.toString(); var margin = 1; if(dot_rad != null && dot_rad > 0) { margin += dot_rad; } var s = this._getTextBoxSize(dlabel, params.dLabelFontSize, params.dLabelFontFamily); var dlabel_x = plots[i][k].x - Math.round( s.w / 2 ); var dlabel_y = plots[i][k].y - Math.round( s.h ) - margin; this._drawText(dlabel_x, dlabel_y, dlabel, params.dLabelFontSize, params.dLabelFontFamily, params.dLabelColor); } } if(params.legend == true) { this._drawText(lpos.cx, lpos.y, items[i][0], params.legendFontSize, params.legendFontFamily, params.legendColor); this._draw_h_aline(lpos.x, Math.round(lpos.y+lpos.h/2), lpos.x + lpos.h*2, line_width, "solid", line_color); if(dot_rad > 0) { this._draw_dot(Math.round(lpos.x+lpos.h), Math.round(lpos.y+lpos.h/2), dot_rad, dot_type, colors[i]); } lpos.y = lpos.y + lpos.h * 1.2; } } this.ctx.fillStyle = params.backgroundColor; this.ctx.fillRect(cpos.x0, 0, cpos.w, cpos.y1); this.ctx.fillRect(cpos.x0, cpos.y0, cpos.w, this.canvas.height - cpos.y0); if( typeof(params.xAxisWidth) == "number" && params.xAxisWidth > 0 ) { this._draw_h_aline(cpos.x0, cpos.y0, cpos.x1, params.xAxisWidth, "solid", params.xAxisColor); } if( typeof(params.yAxisWidth) == "number" && params.yAxisWidth > 0 ) { this._draw_v_aline(cpos.x0, cpos.y0, cpos.y1, params.yAxisWidth, "solid", params.yAxisColor); } var xscale_y_under = 0; for(var i=1; i<=max_n; i++) { if( typeof(params.x[i] ) != "string" ) { continue; } if(params.x[i] == "") { continue; } var s = this._getTextBoxSize(params.x[i], params.xScaleFontSize, params.xScaleFontFamily); var xscale_x = Math.round( cpos.x0 + cpos.w * ( i - 0.5 ) / max_n ) - Math.round( s.w / 2 ); var xscale_y = cpos.y0 + 5; this._drawText(xscale_x, xscale_y, params.x[i], params.xScaleFontSize, params.xScaleFontFamily, params.xScaleColor); if(xscale_y + s.h >= xscale_y_under) { xscale_y_under = xscale_y + s.h; } } var yscale_y_top = this.canvas.height; for(var i=1; i params.yMax) { continue; } var s = this._getTextBoxSize(v, params.yScaleFontSize, params.yScaleFontFamily); var yscale_y = Math.round( cpos.y0 - cpos.h * ( params.y[i] - params.yMin ) / v_range ) - Math.round( s.h / 2 ); var yscale_x = Math.round( cpos.x0 - s.w ) - 5; this._drawText(yscale_x, yscale_y, v, params.yScaleFontSize, params.yScaleFontFamily, params.yScaleColor); if(yscale_y <= yscale_y_top) { yscale_y_top = yscale_y; } } if( typeof(params.x[0]) == "string" && params.x[0] != "" ) { var s = this._getTextBoxSize(params.x[0], params.xCaptionFontSize, params.xCaptionFontFamily); var xcaption_y = cpos.y0 + 5; if(xscale_y_under > 0) { xcaption_y = xscale_y_under + 5; } var xcaption_x = Math.round( cpos.x0 + ( cpos.w / 2 ) - ( s.w / 2 ) ); this._drawText(xcaption_x, xcaption_y, params.x[0], params.xCaptionFontSize, params.xCaptionFontFamily, params.xCaptionColor); } if( typeof(params.y[0]) == "string" && params.y[0] != "" ) { var s = this._getTextBoxSize(params.y[0], params.yCaptionFontSize, params.yCaptionFontFamily); var ycaption_y = yscale_y_top - s.h - 5; if(yscale_y_top > cpos.y1) { ycaption_y = cpos.y1 - s.h - 5; } var ycaption_x = Math.round( cpos.x0 - ( s.w / 2 ) ); if(ycaption_x < 5) { ycaption_x = 5; } this._drawText(ycaption_x, ycaption_y, params.y[0], params.yCaptionFontSize, params.yCaptionFontFamily, params.yCaptionColor); } }; html5jp.graph.line.prototype._draw_v_aline = function(x0, y0, y1, width, type, color) { color = this._csscolor2rgb(color); this.ctx.beginPath(); color = "rgb(" + color.r + "," + color.g + "," + color.b + ")" this.ctx.strokeStyle = color; this.ctx.lineWidth = width; if(type == "solid") { this.ctx.moveTo(x0, y0); this.ctx.lineTo(x0, y1); this.ctx.stroke(); } else if( type == "dashed" || (type == "dotted" && width < 2) ) { var y = y0; while(1) { if(y - width*4 < y1) { break; } this.ctx.moveTo(x0, y); y = y - width * 4; this.ctx.lineTo(x0, y); this.ctx.stroke(); if(y - width*2 < y1) { break; } y = y - width*2; } } else if(type == "dotted") { this.ctx.fillStyle = color; var y = y0; while(1) { if(y - width*2 < y1) { break; } this.ctx.arc(x0, y, width/2, 0, Math.PI*2, false); this.ctx.fill(); if(y - width*2 < y1) { break; } y = y - width*2; } } }; html5jp.graph.line.prototype._draw_h_aline = function(x0, y0, x1, width, type, color) { color = this._csscolor2rgb(color); this.ctx.beginPath(); color = "rgb(" + color.r + "," + color.g + "," + color.b + ")" this.ctx.strokeStyle = color; this.ctx.lineWidth = width; if(type == "solid") { this.ctx.moveTo(x0, y0); this.ctx.lineTo(x1, y0); this.ctx.stroke(); } else if( type == "dashed" || (type == "dotted" && width < 2) ) { var x = x0; while(1) { if(x + width*4 > x1) { break; } this.ctx.moveTo(x, y0); x = x + width * 4; this.ctx.lineTo(x, y0); this.ctx.stroke(); if(x + width*2 > x1) { break; } x = x + width*2; } } else if(type == "dotted") { this.ctx.fillStyle = color; var x = x0; while(1) { if(x + width*2 > x1) { break; } this.ctx.arc(x, y0, width/2, 0, Math.PI*2, false); this.ctx.fill(); if(x + width*2 > x1) { break; } x = x + width*2; } } }; html5jp.graph.line.prototype._draw_dot = function(x, y, rad, type, color) { this.ctx.beginPath(); this.ctx.fillStyle = "rgb(" + color + ")"; if( type == "disc" ) { this.ctx.arc(x, y, rad, 0, Math.PI*2, false); } else if( type == "square" ) { this.ctx.moveTo(x-rad, y-rad); this.ctx.lineTo(x+rad, y-rad); this.ctx.lineTo(x+rad, y+rad); this.ctx.lineTo(x-rad, y+rad); } else if( type == "triangle" ) { this.ctx.moveTo(x, y-rad); this.ctx.lineTo(x+rad, y+rad); this.ctx.lineTo(x-rad, y+rad); } else if( type == "i-triangle" ) { this.ctx.moveTo(x, y+rad); this.ctx.lineTo(x+rad, y-rad); this.ctx.lineTo(x-rad, y-rad); } else if( type == "diamond" ) { this.ctx.moveTo(x, y-rad); this.ctx.lineTo(x+rad, y); this.ctx.lineTo(x, y+rad); this.ctx.lineTo(x-rad, y); } else { this.ctx.arc(x, y, rad, 0, Math.PI*2, false); } this.ctx.closePath(); this.ctx.fill(); }; html5jp.graph.line.prototype._drawText = function(x, y, text, font_size, font_family, color) { var div = document.createElement('DIV'); div.appendChild( document.createTextNode(text) ); div.style.fontSize = font_size; div.style.fontFamily = font_family; div.style.color = color; div.style.margin = "0"; div.style.padding = "0"; div.style.position = "absolute"; div.style.left = x.toString() + "px"; div.style.top = y.toString() + "px"; this.canvas.parentNode.appendChild(div); } html5jp.graph.line.prototype._getTextBoxSize = function(text, font_size, font_family) { var tmpdiv = document.createElement('DIV'); tmpdiv.appendChild( document.createTextNode(text) ); tmpdiv.style.fontSize = font_size; tmpdiv.style.fontFamily = font_family; tmpdiv.style.margin = "0"; tmpdiv.style.padding = "0"; tmpdiv.style.visible = "hidden"; tmpdiv.style.position = "absolute"; tmpdiv.style.left = "0px"; tmpdiv.style.top = "0px"; this.canvas.parentNode.appendChild(tmpdiv); var o = { w: tmpdiv.offsetWidth, h: tmpdiv.offsetHeight }; tmpdiv.parentNode.removeChild(tmpdiv); return o; } html5jp.graph.line.prototype._getElementAbsPos = function(elm) { var obj = new Object(); obj.x = elm.offsetLeft; obj.y = elm.offsetTop; while(elm.offsetParent) { elm = elm.offsetParent; obj.x += elm.offsetLeft; obj.y += elm.offsetTop; } return obj; }; html5jp.graph.line.prototype._csscolor2rgb = function (c) { if( ! c ) { return null; } var color_map = { black: "#000000", gray: "#808080", silver: "#c0c0c0", white: "#ffffff", maroon: "#800000", red: "#ff0000", purple: "#800080", fuchsia: "#ff00ff", green: "#008000", lime: "#00FF00", olive: "#808000", yellow: "#FFFF00", navy: "#000080", blue: "#0000FF", teal: "#008080", aqua: "#00FFFF" }; c = c.toLowerCase(); var o = new Object(); if( c.match(/^[a-zA-Z]+$/) && color_map[c] ) { c = color_map[c]; } var m = null; if( m = c.match(/^\#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i) ) { o.r = parseInt(m[1], 16); o.g = parseInt(m[2], 16); o.b = parseInt(m[3], 16); } else if( m = c.match(/^\#([a-f\d]{1})([a-f\d]{1})([a-f\d]{1})$/i) ) { o.r = parseInt(m[1]+"0", 16); o.g = parseInt(m[2]+"0", 16); o.b = parseInt(m[3]+"0", 16); } else if( m = c.match(/^rgba*\(\s*(\d+),\s*(\d+),\s*(\d+)/i) ) { o.r = m[1]; o.g = m[2]; o.b = m[3]; } else if( m = c.match(/^rgba*\(\s*(\d+)\%,\s*(\d+)\%,\s*(\d+)\%/i) ) { o.r = Math.round(m[1] * 255 / 100); o.g = Math.round(m[2] * 255 / 100); o.b = Math.round(m[3] * 255 / 100); } else { return null; } return o; };