📄 jpgraph.php
字号:
// Get a string of all image map areas function GetCSIMareas() { if( !$this->iHasStroked ) $this->Stroke(_CSIM_SPECIALFILE); $csim = $this->title->GetCSIMAreas(); $csim .= $this->subtitle->GetCSIMAreas(); $csim .= $this->subsubtitle->GetCSIMAreas(); $csim .= $this->legend->GetCSIMAreas(); if( $this->y2axis != NULL ) { $csim .= $this->y2axis->title->GetCSIMAreas(); } if( $this->texts != null ) { $n = count($this->texts); for($i=0; $i < $n; ++$i ) { $csim .= $this->texts[$i]->GetCSIMAreas(); } } if( $this->y2texts != null && $this->y2scale != null ) { $n = count($this->y2texts); for($i=0; $i < $n; ++$i ) { $csim .= $this->y2texts[$i]->GetCSIMAreas(); } } if( $this->yaxis != null && $this->xaxis != null ) { $csim .= $this->yaxis->title->GetCSIMAreas(); $csim .= $this->xaxis->title->GetCSIMAreas(); } $n = count($this->plots); for( $i=0; $i < $n; ++$i ) $csim .= $this->plots[$i]->GetCSIMareas(); $n = count($this->y2plots); for( $i=0; $i < $n; ++$i ) $csim .= $this->y2plots[$i]->GetCSIMareas(); return $csim; } // Get a complete <MAP>..</MAP> tag for the final image map function GetHTMLImageMap($aMapName) { $im = "<MAP NAME=\"$aMapName\">\n"; $im .= $this->GetCSIMareas(); $im .= "</MAP>"; return $im; } function CheckCSIMCache($aCacheName,$aTimeOut=60) { global $_SERVER; if( $aCacheName=='auto' ) $aCacheName=basename($_SERVER['PHP_SELF']); $this->csimcachename = CSIMCACHE_DIR.$aCacheName; $this->csimcachetimeout = $aTimeOut; // First determine if we need to check for a cached version // This differs from the standard cache in the sense that the // image and CSIM map HTML file is written relative to the directory // the script executes in and not the specified cache directory. // The reason for this is that the cache directory is not necessarily // accessible from the HTTP server. if( $this->csimcachename != '' ) { $dir = dirname($this->csimcachename); $base = basename($this->csimcachename); $base = strtok($base,'.'); $suffix = strtok('.'); $basecsim = $dir.'/'.$base.'_csim_.html'; $baseimg = $dir.'/'.$base.'.'.$this->img->img_format; $timedout=false; // Does it exist at all ? if( file_exists($basecsim) && file_exists($baseimg) ) { // Check that it hasn't timed out $diff=time()-filemtime($basecsim); if( $this->csimcachetimeout>0 && ($diff > $this->csimcachetimeout*60) ) { $timedout=true; @unlink($basecsim); @unlink($baseimg); } else { if ($fh = @fopen($basecsim, "r")) { fpassthru($fh); exit(); } else JpGraphError::Raise(" Can't open cached CSIM \"$basecsim\" for reading."); } } } return false; } function StrokeCSIM($aScriptName='',$aCSIMName='',$aBorder=0) { if( $aCSIMName=='' ) { // create a random map name srand ((double) microtime() * 1000000); $r = rand(0,100000); $aCSIMName='__mapname'.$r.'__'; } if( empty($_GET[_CSIM_DISPLAY]) ) { // First determine if we need to check for a cached version // This differs from the standard cache in the sense that the // image and CSIM map HTML file is written relative to the directory // the script executes in and not the specified cache directory. // The reason for this is that the cache directory is not necessarily // accessible from the HTTP server. if( $this->csimcachename != '' ) { $dir = dirname($this->csimcachename); $base = basename($this->csimcachename); $base = strtok($base,'.'); $suffix = strtok('.'); $basecsim = $dir.'/'.$base.'_csim_.html'; $baseimg = $base.'.'.$this->img->img_format; // Check that apache can write to directory specified if( file_exists($dir) && !is_writeable($dir) ) { JpgraphError::Raise('Apache/PHP does not have permission to write to the CSIM cache directory ('.$dir.'). Check permissions.'); } // Make sure directory exists $this->cache->MakeDirs($dir); // Write the image file $this->Stroke(CSIMCACHE_DIR.$baseimg); // Construct wrapper HTML and write to file and send it back to browser $htmlwrap = $this->GetHTMLImageMap($aCSIMName)."\n". '<img src="'.CSIMCACHE_HTTP_DIR.$baseimg.'" ISMAP USEMAP="#'.$aCSIMName.'" border='.$aBorder.'>'."\n"; if($fh = @fopen($basecsim,'w') ) { fwrite($fh,$htmlwrap); fclose($fh); echo $htmlwrap; } else JpGraphError::Raise(" Can't write CSIM \"$basecsim\" for writing. Check free space and permissions."); } else { if( $aScriptName=='' ) { JpGraphError::Raise('Missing script name in call to StrokeCSIM(). You must specify the name of the actual image script as the first parameter to StrokeCSIM().'); exit(); } // This is a JPGRAPH internal defined that prevents // us from recursively coming here again $urlarg='?'._CSIM_DISPLAY.'=1'; // Now reconstruct any user URL argument reset($_GET); while( list($key,$value) = each($_GET) ) { if( is_array($value) ) { $n = count($value); for( $i=0; $i < $n; ++$i ) { $urlarg .= '&'.$key.'%5B%5D='.urlencode($value[$i]); } } else { $urlarg .= '&'.$key.'='.urlencode($value); } } // It's not ideal to convert POST argument to GET arguments // but there is little else we can do. One idea for the // future might be recreate the POST header in case. reset($_POST); while( list($key,$value) = each($_POST) ) { if( is_array($value) ) { $n = count($value); for( $i=0; $i < $n; ++$i ) { $urlarg .= '&'.$key.'%5B%5D='.urlencode($value[$i]); } } else { $urlarg .= '&'.$key.'='.urlencode($value); } } echo $this->GetHTMLImageMap($aCSIMName); echo "<img src='".$aScriptName.$urlarg."' ISMAP USEMAP='#".$aCSIMName."' border=$aBorder>"; } } else { $this->Stroke(); } } function GetTextsYMinMax($aY2=false) { if( $aY2 ) $txts = $this->y2texts; else $txts = $this->texts; $n = count($txts); $min=null; $max=null; for( $i=0; $i < $n; ++$i ) { if( $txts[$i]->iScalePosY !== null && $txts[$i]->iScalePosX !== null ) { if( $min === null ) { $min = $max = $txts[$i]->iScalePosY ; } else { $min = min($min,$txts[$i]->iScalePosY); $max = max($max,$txts[$i]->iScalePosY); } } } if( $min !== null ) { return array($min,$max); } else return null; } function GetTextsXMinMax($aY2=false) { if( $aY2 ) $txts = $this->y2texts; else $txts = $this->texts; $n = count($txts); $min=null; $max=null; for( $i=0; $i < $n; ++$i ) { if( $txts[$i]->iScalePosY !== null && $txts[$i]->iScalePosX !== null ) { if( $min === null ) { $min = $max = $txts[$i]->iScalePosX ; } else { $min = min($min,$txts[$i]->iScalePosX); $max = max($max,$txts[$i]->iScalePosX); } } } if( $min !== null ) { return array($min,$max); } else return null; } function GetXMinMax() { list($min,$ymin) = $this->plots[0]->Min(); list($max,$ymax) = $this->plots[0]->Max(); foreach( $this->plots as $p ) { list($xmin,$ymin) = $p->Min(); list($xmax,$ymax) = $p->Max(); $min = Min($xmin,$min); $max = Max($xmax,$max); } if( $this->y2axis != null ) { foreach( $this->y2plots as $p ) { list($xmin,$ymin) = $p->Min(); list($xmax,$ymax) = $p->Max(); $min = Min($xmin,$min); $max = Max($xmax,$max); } } return array($min,$max); } function AdjustMarginsForTitles() { $totrequired = ($this->title->t != '' ? $this->title->GetTextHeight($this->img) + $this->title->margin + 5 : 0 ) + ($this->subtitle->t != '' ? $this->subtitle->GetTextHeight($this->img) + $this->subtitle->margin + 5 : 0 ) + ($this->subsubtitle->t != '' ? $this->subsubtitle->GetTextHeight($this->img) + $this->subsubtitle->margin + 5 : 0 ) ; $btotrequired = 0; if($this->xaxis != null && !$this->xaxis->hide && !$this->xaxis->hide_labels ) { // Minimum bottom margin if( $this->xaxis->title->t != '' ) { if( $this->img->a == 90 ) $btotrequired = $this->yaxis->title->GetTextHeight($this->img) + 5 ; else $btotrequired = $this->xaxis->title->GetTextHeight($this->img) + 5 ; } else $btotrequired = 0; if( $this->img->a == 90 ) { $this->img->SetFont($this->yaxis->font_family,$this->yaxis->font_style, $this->yaxis->font_size); $lh = $this->img->GetTextHeight('Mg',$this->yaxis->label_angle); } else { $this->img->SetFont($this->xaxis->font_family,$this->xaxis->font_style, $this->xaxis->font_size); $lh = $this->img->GetTextHeight('Mg',$this->xaxis->label_angle); } $btotrequired += $lh + 5; } if( $this->img->a == 90 ) { // DO Nothing. It gets too messy to do this properly for 90 deg... } else{ if( $this->img->top_margin < $totrequired ) { $this->SetMargin($this->img->left_margin,$this->img->right_margin, $totrequired,$this->img->bottom_margin); } if( $this->img->bottom_margin < $btotrequired ) { $this->SetMargin($this->img->left_margin,$this->img->right_margin, $this->img->top_margin,$btotrequired); } } } // Stroke the graph // $aStrokeFileName If != "" the image will be written to this file and NOT // streamed back to the browser function Stroke($aStrokeFileName="") { // Fist make a sanity check that user has specified a scale if( empty($this->yscale) ) { JpGraphError::Raise('You must specify what scale to use with a call to Graph::SetScale().'); } // Start by adjusting the margin so that potential titles will fit. $this->AdjustMarginsForTitles(); // Setup scale constants if( $this->yscale ) $this->yscale->InitConstants($this->img); if( $this->xscale ) $this->xscale->InitConstants($this->img); if( $this->y2scale ) $this->y2scale->InitConstants($this->img); // If the filename is the predefined value = '_csim_special_' // we assume that the call to stroke only needs to do enough // to correctly generate the CSIM maps. // We use this variable to skip things we don't strictly need // to do to generate the image map to improve performance // a best we can. Therefor you will see a lot of tests !$_csim in the // code below. $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE); // We need to know if we have stroked the plot in the // GetCSIMareas. Otherwise the CSIM hasn't been generated // and in the case of GetCSIM called before stroke to generate // CSIM without storing an image to disk GetCSIM must call Stroke. $this->iHasStroked = true; // Do any pre-stroke adjustment that is needed by the different plot types // (i.e bar plots want's to add an offset to the x-labels etc) for($i=0; $i < count($this->plots) ; ++$i ) { $this->plots[$i]->PreStrokeAdjust($this); $this->plots[$i]->DoLegend($this); } // Any plots on the second Y scale? if( $this->y2scale != null ) { for($i=0; $i<count($this->y2plots) ; ++$i ) { $this->y2plots[$i]->PreStrokeAdjust($this); $this->y2plots[$i]->DoLegend($this); } } // Bail out if any of the Y-axis not been specified and // has no plots. (This means it is impossible to do autoscaling and // no other scale was given so we can't possible draw anything). If you use manual // scaling you also have to supply the tick steps as well. if( (!$this->yscale->IsSpecified() && count($this->plots)==0) || ($this->y2scale!=null && !$this->y2scale->IsSpecified() && count($this->y2plots)==0) ) { //$e = "n=".count($this->y2plots)."\n"; $e = "Can't draw unspecified Y-scale.<br>\nYou have either:<br>\n"; $e .= "1. Specified an Y axis for autoscaling but have not supplied any plots<br>\n"; $e .= "2. Specified a scale manually but have forgot to specify the tick steps"; JpGraphError::Raise($e); } // Bail out if no plots and no specified X-scale if( (!$this->xscale->IsSpecified() && count($this->plots)==0 && count($this->y2plots)==0) ) JpGraphError::Raise("<strong>JpGraph: Can't draw unspecified X-scale.</strong><br>No plots.<br>"); //Check if we should autoscale y-axis if( !$this->yscale->IsSpecified() && count($this->plots)>0 ) { list($min,$max) = $this->GetPlotsYMinMax($this->plots); $lres = $this->GetLinesYMinMax($this->lines); if( is_array($lres) ) { list($linmin,$linmax) = $lres ; $min = min($min,$linmin); $max = max($max,$linmax); } $tres = $this->GetTextsYMinMax(); if( is_array($tres) ) { list($tmin,$tmax) = $tres ; $min = min($min,$tmin); $max = max($max,$tmax); } $this->yscale->AutoScale($this->img,$min,$max, $this->img->plotheight/$this->ytick_factor); } elseif( $this->yscale->IsSpecified() && ( $this->yscale->auto_ticks || !$this->yscale->ticks->IsSpecified()) ) { // The tick calculation will use the user suplied min/max values to determine // the ticks. If auto_ticks is false the exact user specifed min and max // values will be used for the scale. // If auto_ticks is true then the scale might be slightly adjusted // so that the min and max values falls on an even major step. $min = $this->yscale->scale[0]; $max = $this->yscale->scale[1]; $this->yscale->AutoScale($this->img,$min,$max, $this->img->plotheight/$this->ytick_factor, $this->yscale->auto_ticks); } if( $this->y2scale != null) { if( !$this->y2scale->IsSpecified() && count($this->y2plots)>0 ) { list($min,$max) = $this->GetPlotsYMinMax($this->y2plots);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -