2015-02-10 82 views
0

我使用html5 canvas元素绘制折线图。该图表正常工作良好。但是当提供负值时,图表绘制不正确。在画布线条图中显示负值

这是我试过的。任何帮助将不胜感激。

http://jsfiddle.net/nshX6/142/

function getMinY() { 

     var min = 0; 
      for(var i = 0; i < data.values.length; i ++) { 
       if(data.values[i].Y < min) { 
        min = data.values[i].Y; 
            } 
      } 
     return Math.ceil(min); 
    } 

回答

2

enter image description here

这里有您可以用它来建立一个灵活的图形工具的一些功能。

你灵活的图形将能显示数据的任何范围内,它会始终可用的画布的大小适合

calcSourceMinMax:计算数据数组中的最小值和最大值。

mapRange:注意到任何数据值并且将其映射到被保证是曲线图显示宽度&高度的最小和最大内的比例值。这允许您的数据数组包含任何范围的值,并且始终不会超出图形显示区域。

getDisplayXY:获取指定的x,y数据值并在图上找到它的显示X,Y坐标。

这里的示例代码和演示:

var canvas=document.getElementById("canvas"); 
 
var ctx=canvas.getContext("2d"); 
 
var cw=canvas.width; 
 
var ch=canvas.height; 
 

 

 
var xPadding = 40; 
 
var yPadding = 30; 
 

 
// Notice I changed The X values 
 
var data = { values:[ 
 
    { X: 0, Y: -120 }, 
 
    { X: 2, Y: 28 }, 
 
    { X: 3, Y: 18 }, 
 
    { X: 4, Y: 34 }, 
 
    { X: 5, Y: 40 }, 
 
    { X: 6, Y: 80 }, 
 
    { X: 7, Y: 80 } 
 
]}; 
 

 

 
// calc the drawable graph boundaries 
 
var graphLeft=xPadding; 
 
var graphRight=canvas.width-xPadding; 
 
var graphTop=yPadding; 
 
var graphBottom=canvas.height-yPadding; 
 

 
// graph styling 
 
var dotRadius=3; 
 

 
// calc the min & max values of data.values (calc both X & Y ranges) 
 
var rangeX=calcSourceMinMax(data.values,'X'); 
 
var rangeY=calcSourceMinMax(data.values,'Y'); 
 

 
// draw the graph content 
 
var starting=getDisplayXY(data.values[0].X,data.values[0].Y); 
 
dot(starting,dotRadius); 
 
for(var i=1;i<data.values.length;i++){ 
 
    var ending=getDisplayXY(data.values[i].X,data.values[i].Y); 
 
    connector(starting,ending); 
 
    dot(ending,dotRadius); 
 
    starting=ending; 
 
} 
 

 
// draw the graph axes 
 
var y0=getDisplayXY(graphLeft,0).displayY; 
 
ctx.beginPath(); 
 
ctx.moveTo(graphLeft,graphTop); 
 
ctx.lineTo(graphLeft,graphBottom); 
 
ctx.moveTo(graphLeft,y0); 
 
ctx.lineTo(graphRight,y0); 
 
ctx.strokeStyle='#D3E'; 
 
ctx.stroke(); 
 

 
// draw the graph legends 
 
ctx.textAlign='right'; 
 
ctx.textBaseline='middle'; 
 
var y0=getDisplayXY(graphLeft,0).displayY; 
 
var yMin=getDisplayXY(graphLeft,rangeY.min).displayY; 
 
var yMax=getDisplayXY(graphLeft,rangeY.max).displayY; 
 
var xMax=getDisplayXY(graphRight,rangeX.max).displayX; 
 
ctx.fillText(rangeY.min,graphLeft-10,yMin); 
 
ctx.fillText(0,graphLeft-10,y0); 
 
ctx.fillText(rangeY.max,graphLeft-10,yMax); 
 
ctx.fillText(rangeX.max,graphRight+10,y0); 
 

 

 

 
/////////////////////////////////// 
 
// HELPER FUNCTIONS 
 
/////////////////////////////////// 
 

 
// 
 
function getDisplayXY(valueX,valueY){ 
 
    // calc the display X & Y from data.values[i] 
 
    x=mapRange(valueX,rangeX.min,rangeX.max,graphLeft,graphRight); 
 
    // Note: canvas y values increase going downward 
 
    // so swap graphTop & graphBottom 
 
    y=mapRange(valueY,rangeY.min,rangeY.max,graphBottom,graphTop); 
 
    return({displayX:x,displayY:y}) 
 
} 
 
// 
 
function connector(starting,ending){ 
 
    ctx.beginPath(); 
 
    ctx.moveTo(starting.displayX,starting.displayY); 
 
    ctx.lineTo(ending.displayX,ending.displayY); 
 
    ctx.stroke(); 
 
} 
 
// 
 
function dot(position,radius){ 
 
    ctx.beginPath(); 
 
    ctx.moveTo(position.displayX,position.displayY); 
 
    ctx.arc(position.displayX,position.displayY,radius,0,Math.PI*2); 
 
    ctx.closePath(); 
 
    ctx.fill(); 
 
} 
 

 

 
// map source values into a designated range 
 
function mapRange(value, sourceLow, sourceHigh, mappedLow, mappedHigh) { 
 
    return mappedLow + (mappedHigh - mappedLow) * (value - sourceLow)/(sourceHigh - sourceLow); 
 
} 
 
// mapping helper function 
 
function calcSourceMinMax(a,prop){ 
 
    var min=1000000; 
 
    var max=-1000000; 
 
    for(var i=0;i<a.length;i++){ 
 
    var value=a[i][prop]; 
 
    if(value<min){min=value;} 
 
    if(value>max){max=value;} 
 
    } 
 
    return({min:min,max:max}); 
 
}
body{ background-color: ivory; padding:10px; } 
 
#canvas{border:1px solid red;}
<canvas id="canvas" width=350 height=300></canvas>

您将要根据您的设计需要风格的图形。这个最简单的例子显示了一个包含x,y轴和最小,最大值范围的图例。

而且,x轴被置于y = 0值。您还需要检查y值范围内是否存在y = 0。如果没有,您可以将x轴移动到图表的底部。

祝您的项目顺利!

+1

这是一个完整的覆盖。但是帮助很大。非常感谢你。 – 2015-02-12 07:14:36

0

尽量modifaying此参数:

var xPadding = 30; 
var yPadding = 30; 

要:

var xPadding = 30; 
var yPadding = 100; 

之后,你需要改变Y步进要大些。

编辑

在,你有你需要的标准化值动态数据情况。

步骤1:发现用于Y

步骤2最小值:如果最小值小于零(0),则需要以标准化所有值是正的。将该值添加到数组的每个元素

第3步:将Y轴移到它的新位置。

+0

如果数据是动态的呢? – 2015-02-10 14:12:29