PHP GD creating graph from a MYSQL table - php
I am currently creating a bar graph for PHP using GD (inb4 use Java-script, I can't. This is a requirement) As it stands I have a functioning Bar graph in GD that i can display normal numbers with but now I am trying to retrieve data from a MYSQL table and display it in the graph.
require "connect.php";
$sql = "SELECT
title, searchcount
FROM movies
ORDER BY
searchcount DESC
LIMIT 10";
$result = $conn->query($sql);
if (mysqli_num_rows($result) > 0)
{
while($row = mysqli_fetch_array($result))
{
$data = [
$row['title'] => substr_count($row['searchcount'], "1"),
];
}
}
This above code currently works in retrieving one of the required 10 results. What I can't figure out is how to retrieve the other 9, any help would be greatly appreciated.
https://imgur.com/m8sU8QG
This here is a link to the Graph at its current state
How the graph is drawn.
/*
* Chart settings and create image
*/
// Image dimensions
$imageWidth = 700;
$imageHeight = 400;
// Grid dimensions and placement within image
$gridTop = 40;
$gridLeft = 50;
$gridBottom = 340;
$gridRight = 650;
$gridHeight = $gridBottom - $gridTop;
$gridWidth = $gridRight - $gridLeft;
// Bar and line width
$lineWidth = 1;
$barWidth = 20;
// Font settings
$font = 'OpenSans-Regular.ttf';
$fontSize = 10;
// Margin between label and axis
$labelMargin = 8;
// Max value on y-axis
$yMaxValue = 25;
// Distance between grid lines on y-axis
$yLabelSpan = 5;
// Init image
$chart = imagecreate($imageWidth, $imageHeight);
// Setup colors
$backgroundColor = imagecolorallocate($chart, 255, 255, 255);
$axisColor = imagecolorallocate($chart, 85, 85, 85);
$labelColor = $axisColor;
$gridColor = imagecolorallocate($chart, 212, 212, 212);
$barColor = imagecolorallocate($chart, 47, 133, 217);
imagefill($chart, 0, 0, $backgroundColor);
imagesetthickness($chart, $lineWidth);
/*
* Print grid lines bottom up
*/
for($i = 0; $i <= $yMaxValue; $i += $yLabelSpan) {
$y = $gridBottom - $i * $gridHeight / $yMaxValue;
// draw the line
imageline($chart, $gridLeft, $y, $gridRight, $y, $gridColor);
// draw right aligned label
$labelBox = imagettfbbox($fontSize, 0, $font, strval($i));
$labelWidth = $labelBox[4] - $labelBox[0];
$labelX = $gridLeft - $labelWidth - $labelMargin;
$labelY = $y + $fontSize / 2;
imagettftext($chart, $fontSize, 0, $labelX, $labelY, $labelColor, $font, strval($i));
}
/*
* Draw x- and y-axis
*/
imageline($chart, $gridLeft, $gridTop, $gridLeft, $gridBottom, $axisColor);
imageline($chart, $gridLeft, $gridBottom, $gridRight, $gridBottom, $axisColor);
/*
* Draw the bars with labels
*/
$barSpacing = $gridWidth / count($data);
$itemX = $gridLeft + $barSpacing / 2;
foreach($data as $key => $value) {
// Draw the bar
$x1 = $itemX - $barWidth / 2;
$y1 = $gridBottom - $value / $yMaxValue * $gridHeight;
$x2 = $itemX + $barWidth / 2;
$y2 = $gridBottom - 1;
imagefilledrectangle($chart, $x1, $y1, $x2, $y2, $barColor);
// Draw the label
$labelBox = imagettfbbox($fontSize, 0, $font, $key);
$labelWidth = $labelBox[4] - $labelBox[0];
$labelX = $itemX - $labelWidth / 2;
$labelY = $gridBottom + $labelMargin + $fontSize;
imagettftext($chart, $fontSize, 0, $labelX, $labelY, $labelColor, $font, $key);
$itemX += $barSpacing;
}
/*
* Output image to browser
*/
imagepng($chart, 'chart.png');
Ok, i tested your code and it works, so my guess is that is not formatted the right way or you not getting the right output from DB.
Try to change this lines:
$data = [
$row['title'] => substr_count($row['searchcount'], "1"),
];
to this:
$data[$row['title']] = substr_count($row['searchcount'], "1");
As you expecting to get a $key => $value pair, so the $value to not be an array(). Here are the test data i used and result:
<?php
$data = array(
'test1' => 10,
'test2' => 4,
'test3' => 10,
'test4' => 4,
'test5' => 10,
'test6' => 4,
'test7' => 10,
'test8' => 4,
'test9' => 10,
'test10' => 4
);
/*
* Chart settings and create image
*/
// Image dimensions
$imageWidth = 700;
$imageHeight = 400;
// Grid dimensions and placement within image
$gridTop = 40;
$gridLeft = 50;
$gridBottom = 340;
$gridRight = 650;
$gridHeight = $gridBottom - $gridTop;
$gridWidth = $gridRight - $gridLeft;
// Bar and line width
$lineWidth = 1;
$barWidth = 20;
// Font settings
$font = getcwd() . '/arial.ttf'; // I switched to use Arial font
$fontSize = 10;
// Margin between label and axis
$labelMargin = 8;
// Max value on y-axis
$yMaxValue = 25;
// Distance between grid lines on y-axis
$yLabelSpan = 5;
// Init image
$chart = imagecreate($imageWidth, $imageHeight);
// Setup colors
$backgroundColor = imagecolorallocate($chart, 255, 255, 255);
$axisColor = imagecolorallocate($chart, 85, 85, 85);
$labelColor = $axisColor;
$gridColor = imagecolorallocate($chart, 212, 212, 212);
$barColor = imagecolorallocate($chart, 47, 133, 217);
imagefill($chart, 0, 0, $backgroundColor);
imagesetthickness($chart, $lineWidth);
/*
* Print grid lines bottom up
*/
for($i = 0; $i <= $yMaxValue; $i += $yLabelSpan) {
$y = $gridBottom - $i * $gridHeight / $yMaxValue;
// draw the line
imageline($chart, $gridLeft, $y, $gridRight, $y, $gridColor);
// draw right aligned label
$labelBox = imagettfbbox($fontSize, 0, $font, strval($i));
$labelWidth = $labelBox[4] - $labelBox[0];
$labelX = $gridLeft - $labelWidth - $labelMargin;
$labelY = $y + $fontSize / 2;
imagettftext($chart, $fontSize, 0, $labelX, $labelY, $labelColor, $font, strval($i));
}
/*
* Draw x- and y-axis
*/
imageline($chart, $gridLeft, $gridTop, $gridLeft, $gridBottom, $axisColor);
imageline($chart, $gridLeft, $gridBottom, $gridRight, $gridBottom, $axisColor);
/*
* Draw the bars with labels
*/
$barSpacing = $gridWidth / count($data);
$itemX = $gridLeft + $barSpacing / 2;
foreach($data as $key => $value) {
// Draw the bar
$x1 = $itemX - $barWidth / 2;
$y1 = $gridBottom - $value / $yMaxValue * $gridHeight;
$x2 = $itemX + $barWidth / 2;
$y2 = $gridBottom - 1;
imagefilledrectangle($chart, $x1, $y1, $x2, $y2, $barColor);
// Draw the label
$labelBox = imagettfbbox($fontSize, 0, $font, $key);
$labelWidth = $labelBox[4] - $labelBox[0];
$labelX = $itemX - $labelWidth / 2;
$labelY = $gridBottom + $labelMargin + $fontSize;
imagettftext($chart, $fontSize, 0, $labelX, $labelY, $labelColor, $font, $key);
$itemX += $barSpacing;
}
/*
* Output image to browser
*/
imagepng($chart, 'chart.png');
?>
Output
Related
create a double column graph in fpdf php
I'm creating a graph in fpdf and I saw this question and it is exactly the same as what I need but when I copied it on my report-weekly.php file it doesn't work and gave me an error message of Notice: Undefined offset: 0 in C:\xampp\htdocs\qtqt\asd\report-weekly.php on line 112 Notice: Undefined offset: 1 in C:\xampp\htdocs\qtqt\asd\report-weekly.php on line 112 Notice: Undefined offset: 2 in C:\xampp\htdocs\qtqt\asd\report-weekly.php on line 112 FPDF error: Some data has already been output, can't send PDF file this is the code I copied <?php require('diag/sector.php'); class PDF_Diag extends PDF_Sector { var $legends; var $wLegend; var $sum; var $NbVal; function ColumnChart($w, $h, $data, $format, $color=null, $maxVal=0, $nbDiv=4) { // RGB for color 0 $colors[0][0] = 155; $colors[0][1] = 75; $colors[0][2] = 155; // RGB for color 1 $colors[1][0] = 0; $colors[1][1] = 155; $colors[1][2] = 0; // RGB for color 2 $colors[2][0] = 75; $colors[2][1] = 155; $colors[2][2] = 255; // RGB for color 3 $colors[3][0] = 75; $colors[3][1] = 0; $colors[3][2] = 155; $this->SetFont('Courier', '', 10); $this->SetLegends($data,$format); // Starting corner (current page position where the chart has been inserted) $XPage = $this->GetX(); $YPage = $this->GetY(); $margin = 2; // Y position of the chart $YDiag = $YPage + $margin; // chart HEIGHT $hDiag = floor($h - $margin * 2); // X position of the chart $XDiag = $XPage + $margin; // chart LENGHT $lDiag = floor($w - $margin * 3 - $this->wLegend); if($color == null) $color=array(155,155,155); if ($maxVal == 0) { foreach($data as $val) { if(max($val) > $maxVal) { $maxVal = max($val); } } } // define the distance between the visual reference lines (the lines which cross the chart's internal area and serve as visual reference for the column's heights) $valIndRepere = ceil($maxVal / $nbDiv); // adjust the maximum value to be plotted (recalculate through the newly calculated distance between the visual reference lines) $maxVal = $valIndRepere * $nbDiv; // define the distance between the visual reference lines (in milimeters) $hRepere = floor($hDiag / $nbDiv); // adjust the chart HEIGHT $hDiag = $hRepere * $nbDiv; // determine the height unit (milimiters/data unit) $unit = $hDiag / $maxVal; // determine the bar's thickness $lBar = floor($lDiag / ($this->NbVal + 1)); $lDiag = $lBar * ($this->NbVal + 1); $eColumn = floor($lBar * 80 / 100); // draw the chart border $this->SetLineWidth(0.2); $this->Rect($XDiag, $YDiag, $lDiag, $hDiag); $this->SetFont('Courier', '', 10); $this->SetFillColor($color[0],$color[1],$color[2]); $i=0; foreach($data as $val) { //Column $yval = $YDiag + $hDiag; $xval = $XDiag + ($i + 1) * $lBar - $eColumn/2; $lval = floor($eColumn/(count($val))); $j=0; foreach($val as $v) { $hval = (int)($v * $unit); $this->SetFillColor($colors[$j][0], $colors[$j][1], $colors[$j][2]); $this->Rect($xval+($lval*$j), $yval, $lval, -$hval, 'DF'); $j++; } //Legend $this->SetXY($xval, $yval + $margin); $this->Cell($lval, 5, $this->legends[$i],0,0,'C'); $i++; } //Scales for ($i = 0; $i <= $nbDiv; $i++) { $ypos = $YDiag + $hRepere * $i; $this->Line($XDiag, $ypos, $XDiag + $lDiag, $ypos); $val = ($nbDiv - $i) * $valIndRepere; $ypos = $YDiag + $hRepere * $i; $xpos = $XDiag - $margin - $this->GetStringWidth($val); $this->Text($xpos, $ypos, $val); } } function SetLegends($data, $format) { $this->legends=array(); $this->wLegend=0; $this->NbVal=count($data); } } $pdf = new PDF_Diag(); $pdf->AddPage(); $data[0] = array(470, 490, 90); $data[1] = array(450, 530, 110); $data[2] = array(420, 580, 100); // Column chart $pdf->SetFont('Arial', 'BIU', 12); $pdf->Cell(210, 5, 'Chart Title', 0, 1, 'C'); $pdf->Ln(8); $valX = $pdf->GetX(); $valY = $pdf->GetY(); $pdf->ColumnChart(110, 100, $data, null, array(255,175,100)); //$pdf->SetXY($valX, $valY); $pdf->Output(); ?>
How to create transparent background in gd without blurring image?
I'm trying to create a pie chart, which will display browser stats. But, when I try to create a transparent background to chart, text goes blurry than normal background. define('FONT', "C:/Windows/fonts/Arial.ttf"); $data = ['edge' => 3, 'ie' => 4, 'firefox' => 12, 'chrome' => 40, 'opera' => 9, 'android' => 18]; function textWidth($text, $fontSize) { $sizes = array_map(function($x){ return $x * .75; }, imagettfbbox($fontSize, 0, FONT, $text)); return $sizes[6] - $sizes[4]; } asort($data); $total = array_sum($data); $before = -90; $w = 300; $h = 300; $graph = imagecreatetruecolor($w * 2, $h * 2); // this is the part where background blurrs: remove this part to compare imagealphablending($graph, false); $transparency = imagecolorallocatealpha($graph, 0, 0, 0, 127); imagefill($graph, 0, 0, $transparency); imagesavealpha($graph, true); //part end $text_color = imagecolorallocate($graph, 0, 0, 0); foreach ($data as $key => $value) { $ratio = 100 / $total * $value; $deg = $before + 3.6 * $ratio; $color = imagecolorallocate($graph, rand(128,255), rand(128,255), rand(128,255)); imagefilledarc($graph, $w, $h, $w * 2, $h * 2, $before, $deg, $color, IMG_ARC_PIE); $posX = $w + $w * cos(deg2rad($deg - 1.8 * $ratio)) * .75; $posY = $w + $w * sin(deg2rad($deg - 1.8 * $ratio)) * .75; $ratio = floor($ratio); imagettftext($graph, 16, 0, $posX + textWidth($key, 18) / 2, $posY, $text_color, FONT, $key); imagettftext($graph, 16, 0, $posX + textWidth($ratio . "%", 18) / 2, $posY + 30, $text_color, FONT, $ratio . "%"); $before = $deg; } header('Content-type: image/png'); imagepng($graph); imagedestroy($graph); I've tried to create transparent background after drawing each parts of graph, but it didn't worked. Any help would be appreciated. Thanks!
You can either remove the following line: imagealphablending($graph, false); Or re-enable alpha blending after setting the transparency: imagealphablending($graph, false); $transparency = imagecolorallocatealpha($graph, 0, 0, 0, 127); imagefill($graph, 0, 0, $transparency); imagealphablending($graph, true); // add this imagesavealpha($graph, true); Result:
Position array text in PHP GD on middle of specific part of image
I have an array of a string to fit on a page, i managed to center it horizontal now i need to do that vertical in a specific part of image. $imgWidth = 240; $imgHeight = 900; $IMG = imagecreatetruecolor($imgWidth,$imgHeight); $font_type_bold = '/dejavu/DejaVuSansCondensed-Bold.ttf'; $background = imagecolorallocate($IMG, 78,129,154); $text_white = imagecolorallocate($IMG, 255,255,255); $IMG = imagecreatetruecolor($imgWidth,$imgHeight); $max_lenght_of_title = 15; $special_issue_name_mod="This is some example text to be put on the page and split into array to fit he width of frame"; $text = explode("\n", wordwrap($special_issue_name_mod, $max_lenght_of_title)); $line_height=30; imageline($IMG, 0, 500, 240, 500, $text_white); imageline($IMG, 0, 100, 240, 100, $text_white); for($i=0;$i<count($text);$i++) { $font_size_si_name_horizontal = 21; //Center the text $size = imagettfbbox(20, 0, $font_type_bold, $text[$i]); $long_text = $size[2] + $size[0]; $posx = ($imgWidth - $long_text) / 2; imagettftext($IMG, $font_size_si_name_horizontal, 0, $posx - 5, 150+ $line_height + $line_height * $i , $text_white, $font_type_bold, $text[$i]); } header("Content-type: image/png"); imagepng($IMG); imagecolordeallocate($IMG, $text_color ); imagecolordeallocate($IMG, $background ); The result is this and i need it to be in specific part of page, for example selected one So how can i make this to not be the fixed middle but adjustive one depending on what part of page the text will be. Note: Text can be longer, so thats the main problem. Depending on lenght of text the title should be in the middle
<?php $imgWidth = 240; $imgHeight = 900; $IMG = imagecreatetruecolor($imgWidth,$imgHeight); $font_type_bold = 'BioRhyme/BioRhyme-Regular.ttf'; $background = imagecolorallocate($IMG, 78,129,154); $text_white = imagecolorallocate($IMG, 255,255,255); $IMG = imagecreatetruecolor($imgWidth,$imgHeight); $max_lenght_of_title = 15; $special_issue_name_mod="This is some example text to be put on the page and split into array to fit he width of frame"; $text = explode("\n", wordwrap($special_issue_name_mod, $max_lenght_of_title)); $line_height=30; $vert = ($imgHeight/5); for($i=0;$i<count($text);$i++) { $font_size_si_name_horizontal = 21; //Center the text $size = imagettfbbox(20, 0, $font_type_bold, $text[$i]); $long_text = $size[2] + $size[0]; $posx = ($imgWidth - $long_text) / 2; imagettftext($IMG, $font_size_si_name_horizontal, 0, $posx - 5, $vert+ $line_height + $line_height * $i , $text_white, $font_type_bold, $text[$i]); } header("Content-type: image/png"); imagepng($IMG); imagecolordeallocate($IMG, $text_color ); imagecolordeallocate($IMG, $background ); ?> I have added $vert = ($imgHeight/5); and put into imagettftext() for dynamically calculted vertical Y index!
I figured out a way to solve this $middle_of_page = 350; for($i=0;$i<count($text);$i++) { $middle_of_page = $middle_of_page - 21; } imagettftext($IMG, $font_size_si_name_horizontal, 0, $posx - 5, $middle_of_page+$line_height + $line_height * $i , $text_white, $font_type_bold, $text[$i]); With the $middle_of_page part i regulate the point where text with array size of one will be, and then i just remove by font size of 21 for every $i that stands for array size of string.
Drawing in a PDF file
I would like to draw in a PDF file. Example: Open the PDF file and get such drawing tools like circle, square, text etc... Using these tools will draw shapes on the PDF file. I searched on google and found such options like pdf.js. But it's not implemented in core PHP or normal MVC structure. It's implemented in JavaScript. Any alternative for pdf.js to draw the shape in a PDF file? I am looking for the same as the example shown here.
Last year when I came upon the same problem I researched and after some tweaking and adjustments I managed to make it work. So here's a detailed explanation on how to set up and use my method. I'm using a combination of two libraries: FPDF: (Free Portable Document Format) which allows to generate PDF files with PHP FPDI: (Free Portable Document Importer) which uses existing PDF and converts them to templates to used by FPDF First, you'll need to download the two libraries: FPDF is found here in the download section and FPDI is on this page. You will be given two folders. Go ahead and add them to your project. Here's my directory structure: Let's go in index.php (or any other file for that matter) and edit a PDF file that we'll name sample.pdf. I had found some code from the official documentation but actually did some modifications to simplify it. You will see I have added the method nextPage() to the PDF class to make the navigation between pages easier. <?php require_once('FPDF/fpdf.php'); require_once('FPDI/fpdi.php'); // path of PDF file $fullPathToFile = "sample.pdf"; class PDF extends FPDI { var $fileIndex; var $currentPage = 1; function Header() { global $fullPathToFile; if (is_null($this->fileIndex)) { $this->numPages = $this->setSourceFile($fullPathToFile); $this->fileIndex = $this->importPage(1); } $this->useTemplate($this->fileIndex, 0, 0,200); } function nextPage() { if($this->currentPage != 1) { $this->fileIndex = $this->importPage($this->currentPage); } $this->addPage(); return ++$this->currentPage; } } // initiate PDF $pdf = new PDF(); // go to first page $pdf->nextPage(); // add content to current page $pdf->SetFont("helvetica", "", 20); $pdf->SetTextColor(220, 20, 60); $pdf->Text(50, 20, "I should not be here!"); // move to next page and add content $pdf->nextPage(); $pdf->SetFont("arial", "", 15); $pdf->SetTextColor(65, 105, 225); $pdf->Text(50, 20, "Me neither!!!"); //show the PDF in page $pdf->Output(); The Output() method can receive different arguments: you can simply output the PDF file in a frame or you can force the download of the PDF file to the user's computer. Read here for more information on that. DEMO! FPDF's community has written several scripts one of which might interest you: it's the geometric figures FPDF plugin (id script69.php). It allows you to draw lines, rectangles, curves, ellipses, circles, polygon among others. Here's a bonus for you: Create a new file called draw.php and put the source code provided on here. I have provided the source code below (the first three lines are different than the original source code to make it work). <?php require_once('FPDF/fpdf.php'); require_once('FPDI/fpdi.php'); class PDF_Draw extends FPDI { // Sets line style // Parameters: // - style: Line style. Array with keys among the following: // . width: Width of the line in user units // . cap: Type of cap to put on the line (butt, round, square). The difference between 'square' and 'butt' is that 'square' projects a flat end past the end of the line. // . join: miter, round or bevel // . dash: Dash pattern. Is 0 (without dash) or array with series of length values, which are the lengths of the on and off dashes. // For example: (2) represents 2 on, 2 off, 2 on , 2 off ... // (2,1) is 2 on, 1 off, 2 on, 1 off.. etc // . phase: Modifier of the dash pattern which is used to shift the point at which the pattern starts // . color: Draw color. Array with components (red, green, blue) function SetLineStyle($style) { extract($style); if (isset($width)) { $width_prev = $this->LineWidth; $this->SetLineWidth($width); $this->LineWidth = $width_prev; } if (isset($cap)) { $ca = array('butt' => 0, 'round'=> 1, 'square' => 2); if (isset($ca[$cap])) $this->_out($ca[$cap] . ' J'); } if (isset($join)) { $ja = array('miter' => 0, 'round' => 1, 'bevel' => 2); if (isset($ja[$join])) $this->_out($ja[$join] . ' j'); } if (isset($dash)) { $dash_string = ''; if ($dash) { $tab = explode(',', $dash); $dash_string = ''; foreach ($tab as $i => $v) { if ($i > 0) $dash_string .= ' '; $dash_string .= sprintf('%.2F', $v); } } if (!isset($phase) || !$dash) $phase = 0; $this->_out(sprintf('[%s] %.2F d', $dash_string, $phase)); } if (isset($color)) { list($r, $g, $b) = $color; $this->SetDrawColor($r, $g, $b); } } // Draws a line // Parameters: // - x1, y1: Start point // - x2, y2: End point // - style: Line style. Array like for SetLineStyle function Line($x1, $y1, $x2, $y2, $style = null) { if ($style) $this->SetLineStyle($style); parent::Line($x1, $y1, $x2, $y2); } // Draws a rectangle // Parameters: // - x, y: Top left corner // - w, h: Width and height // - style: Style of rectangle (draw and/or fill: D, F, DF, FD) // - border_style: Border style of rectangle. Array with some of this index // . all: Line style of all borders. Array like for SetLineStyle // . L: Line style of left border. null (no border) or array like for SetLineStyle // . T: Line style of top border. null (no border) or array like for SetLineStyle // . R: Line style of right border. null (no border) or array like for SetLineStyle // . B: Line style of bottom border. null (no border) or array like for SetLineStyle // - fill_color: Fill color. Array with components (red, green, blue) function Rect($x, $y, $w, $h, $style = '', $border_style = null, $fill_color = null) { if (!(false === strpos($style, 'F')) && $fill_color) { list($r, $g, $b) = $fill_color; $this->SetFillColor($r, $g, $b); } switch ($style) { case 'F': $border_style = null; parent::Rect($x, $y, $w, $h, $style); break; case 'DF': case 'FD': if (!$border_style || isset($border_style['all'])) { if (isset($border_style['all'])) { $this->SetLineStyle($border_style['all']); $border_style = null; } } else $style = 'F'; parent::Rect($x, $y, $w, $h, $style); break; default: if (!$border_style || isset($border_style['all'])) { if (isset($border_style['all']) && $border_style['all']) { $this->SetLineStyle($border_style['all']); $border_style = null; } parent::Rect($x, $y, $w, $h, $style); } break; } if ($border_style) { if (isset($border_style['L']) && $border_style['L']) $this->Line($x, $y, $x, $y + $h, $border_style['L']); if (isset($border_style['T']) && $border_style['T']) $this->Line($x, $y, $x + $w, $y, $border_style['T']); if (isset($border_style['R']) && $border_style['R']) $this->Line($x + $w, $y, $x + $w, $y + $h, $border_style['R']); if (isset($border_style['B']) && $border_style['B']) $this->Line($x, $y + $h, $x + $w, $y + $h, $border_style['B']); } } // Draws a Bézier curve (the Bézier curve is tangent to the line between the control points at either end of the curve) // Parameters: // - x0, y0: Start point // - x1, y1: Control point 1 // - x2, y2: Control point 2 // - x3, y3: End point // - style: Style of rectangule (draw and/or fill: D, F, DF, FD) // - line_style: Line style for curve. Array like for SetLineStyle // - fill_color: Fill color. Array with components (red, green, blue) function Curve($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3, $style = '', $line_style = null, $fill_color = null) { if (!(false === strpos($style, 'F')) && $fill_color) { list($r, $g, $b) = $fill_color; $this->SetFillColor($r, $g, $b); } switch ($style) { case 'F': $op = 'f'; $line_style = null; break; case 'FD': case 'DF': $op = 'B'; break; default: $op = 'S'; break; } if ($line_style) $this->SetLineStyle($line_style); $this->_Point($x0, $y0); $this->_Curve($x1, $y1, $x2, $y2, $x3, $y3); $this->_out($op); } // Draws an ellipse // Parameters: // - x0, y0: Center point // - rx, ry: Horizontal and vertical radius (if ry = 0, draws a circle) // - angle: Orientation angle (anti-clockwise) // - astart: Start angle // - afinish: Finish angle // - style: Style of ellipse (draw and/or fill: D, F, DF, FD, C (D + close)) // - line_style: Line style for ellipse. Array like for SetLineStyle // - fill_color: Fill color. Array with components (red, green, blue) // - nSeg: Ellipse is made up of nSeg Bézier curves function Ellipse($x0, $y0, $rx, $ry = 0, $angle = 0, $astart = 0, $afinish = 360, $style = '', $line_style = null, $fill_color = null, $nSeg = 8) { if ($rx) { if (!(false === strpos($style, 'F')) && $fill_color) { list($r, $g, $b) = $fill_color; $this->SetFillColor($r, $g, $b); } switch ($style) { case 'F': $op = 'f'; $line_style = null; break; case 'FD': case 'DF': $op = 'B'; break; case 'C': $op = 's'; // small 's' means closing the path as well break; default: $op = 'S'; break; } if ($line_style) $this->SetLineStyle($line_style); if (!$ry) $ry = $rx; $rx *= $this->k; $ry *= $this->k; if ($nSeg < 2) $nSeg = 2; $astart = deg2rad((float) $astart); $afinish = deg2rad((float) $afinish); $totalAngle = $afinish - $astart; $dt = $totalAngle/$nSeg; $dtm = $dt/3; $x0 *= $this->k; $y0 = ($this->h - $y0) * $this->k; if ($angle != 0) { $a = -deg2rad((float) $angle); $this->_out(sprintf('q %.2F %.2F %.2F %.2F %.2F %.2F cm', cos($a), -1 * sin($a), sin($a), cos($a), $x0, $y0)); $x0 = 0; $y0 = 0; } $t1 = $astart; $a0 = $x0 + ($rx * cos($t1)); $b0 = $y0 + ($ry * sin($t1)); $c0 = -$rx * sin($t1); $d0 = $ry * cos($t1); $this->_Point($a0 / $this->k, $this->h - ($b0 / $this->k)); for ($i = 1; $i <= $nSeg; $i++) { // Draw this bit of the total curve $t1 = ($i * $dt) + $astart; $a1 = $x0 + ($rx * cos($t1)); $b1 = $y0 + ($ry * sin($t1)); $c1 = -$rx * sin($t1); $d1 = $ry * cos($t1); $this->_Curve(($a0 + ($c0 * $dtm)) / $this->k, $this->h - (($b0 + ($d0 * $dtm)) / $this->k), ($a1 - ($c1 * $dtm)) / $this->k, $this->h - (($b1 - ($d1 * $dtm)) / $this->k), $a1 / $this->k, $this->h - ($b1 / $this->k)); $a0 = $a1; $b0 = $b1; $c0 = $c1; $d0 = $d1; } $this->_out($op); if ($angle !=0) $this->_out('Q'); } } // Draws a circle // Parameters: // - x0, y0: Center point // - r: Radius // - astart: Start angle // - afinish: Finish angle // - style: Style of circle (draw and/or fill) (D, F, DF, FD, C (D + close)) // - line_style: Line style for circle. Array like for SetLineStyle // - fill_color: Fill color. Array with components (red, green, blue) // - nSeg: Ellipse is made up of nSeg Bézier curves function Circle($x0, $y0, $r, $astart = 0, $afinish = 360, $style = '', $line_style = null, $fill_color = null, $nSeg = 8) { $this->Ellipse($x0, $y0, $r, 0, 0, $astart, $afinish, $style, $line_style, $fill_color, $nSeg); } // Draws a polygon // Parameters: // - p: Points. Array with values x0, y0, x1, y1,..., x(np-1), y(np - 1) // - style: Style of polygon (draw and/or fill) (D, F, DF, FD) // - line_style: Line style. Array with one of this index // . all: Line style of all lines. Array like for SetLineStyle // . 0..np-1: Line style of each line. Item is 0 (not line) or like for SetLineStyle // - fill_color: Fill color. Array with components (red, green, blue) function Polygon($p, $style = '', $line_style = null, $fill_color = null) { $np = count($p) / 2; if (!(false === strpos($style, 'F')) && $fill_color) { list($r, $g, $b) = $fill_color; $this->SetFillColor($r, $g, $b); } switch ($style) { case 'F': $line_style = null; $op = 'f'; break; case 'FD': case 'DF': $op = 'B'; break; default: $op = 'S'; break; } $draw = true; if ($line_style) if (isset($line_style['all'])) $this->SetLineStyle($line_style['all']); else { // 0 .. (np - 1), op = {B, S} $draw = false; if ('B' == $op) { $op = 'f'; $this->_Point($p[0], $p[1]); for ($i = 2; $i < ($np * 2); $i = $i + 2) $this->_Line($p[$i], $p[$i + 1]); $this->_Line($p[0], $p[1]); $this->_out($op); } $p[$np * 2] = $p[0]; $p[($np * 2) + 1] = $p[1]; for ($i = 0; $i < $np; $i++) if (!empty($line_style[$i])) $this->Line($p[$i * 2], $p[($i * 2) + 1], $p[($i * 2) + 2], $p[($i * 2) + 3], $line_style[$i]); } if ($draw) { $this->_Point($p[0], $p[1]); for ($i = 2; $i < ($np * 2); $i = $i + 2) $this->_Line($p[$i], $p[$i + 1]); $this->_Line($p[0], $p[1]); $this->_out($op); } } // Draws a regular polygon // Parameters: // - x0, y0: Center point // - r: Radius of circumscribed circle // - ns: Number of sides // - angle: Orientation angle (anti-clockwise) // - circle: Draw circumscribed circle or not // - style: Style of polygon (draw and/or fill) (D, F, DF, FD) // - line_style: Line style. Array with one of this index // . all: Line style of all lines. Array like for SetLineStyle // . 0..ns-1: Line style of each line. Item is 0 (not line) or like for SetLineStyle // - fill_color: Fill color. Array with components (red, green, blue) // - circle_style: Style of circumscribed circle (draw and/or fill) (D, F, DF, FD) (if draw) // - circle_line_style: Line style for circumscribed circle. Array like for SetLineStyle (if draw) // - circle_fill_color: Fill color for circumscribed circle. Array with components (red, green, blue) (if draw fill circle) function RegularPolygon($x0, $y0, $r, $ns, $angle = 0, $circle = false, $style = '', $line_style = null, $fill_color = null, $circle_style = '', $circle_line_style = null, $circle_fill_color = null) { if ($ns < 3) $ns = 3; if ($circle) $this->Circle($x0, $y0, $r, 0, 360, $circle_style, $circle_line_style, $circle_fill_color); $p = null; for ($i = 0; $i < $ns; $i++) { $a = $angle + ($i * 360 / $ns); $a_rad = deg2rad((float) $a); $p[] = $x0 + ($r * sin($a_rad)); $p[] = $y0 + ($r * cos($a_rad)); } $this->Polygon($p, $style, $line_style, $fill_color); } // Draws a star polygon // Parameters: // - x0, y0: Center point // - r: Radius of circumscribed circle // - nv: Number of vertices // - ng: Number of gaps (ng % nv = 1 => regular polygon) // - angle: Orientation angle (anti-clockwise) // - circle: Draw circumscribed circle or not // - style: Style of polygon (draw and/or fill) (D, F, DF, FD) // - line_style: Line style. Array with one of this index // . all: Line style of all lines. Array like for SetLineStyle // . 0..n-1: Line style of each line. Item is 0 (not line) or like for SetLineStyle // - fill_color: Fill color. Array with components (red, green, blue) // - circle_style: Style of circumscribed circle (draw and/or fill) (D, F, DF, FD) (if draw) // - circle_line_style: Line style for circumscribed circle. Array like for SetLineStyle (if draw) // - circle_fill_color: Fill color for circumscribed circle. Array with components (red, green, blue) (if draw fill circle) function StarPolygon($x0, $y0, $r, $nv, $ng, $angle = 0, $circle = false, $style = '', $line_style = null, $fill_color = null, $circle_style = '', $circle_line_style = null, $circle_fill_color = null) { if ($nv < 2) $nv = 2; if ($circle) $this->Circle($x0, $y0, $r, 0, 360, $circle_style, $circle_line_style, $circle_fill_color); $p2 = null; $visited = null; for ($i = 0; $i < $nv; $i++) { $a = $angle + ($i * 360 / $nv); $a_rad = deg2rad((float) $a); $p2[] = $x0 + ($r * sin($a_rad)); $p2[] = $y0 + ($r * cos($a_rad)); $visited[] = false; } $p = null; $i = 0; do { $p[] = $p2[$i * 2]; $p[] = $p2[($i * 2) + 1]; $visited[$i] = true; $i += $ng; $i %= $nv; } while (!$visited[$i]); $this->Polygon($p, $style, $line_style, $fill_color); } // Draws a rounded rectangle // Parameters: // - x, y: Top left corner // - w, h: Width and height // - r: Radius of the rounded corners // - round_corner: Draws rounded corner or not. String with a 0 (not rounded i-corner) or 1 (rounded i-corner) in i-position. Positions are, in order and begin to 0: top left, top right, bottom right and bottom left // - style: Style of rectangle (draw and/or fill) (D, F, DF, FD) // - border_style: Border style of rectangle. Array like for SetLineStyle // - fill_color: Fill color. Array with components (red, green, blue) function RoundedRect($x, $y, $w, $h, $r, $round_corner = '1111', $style = '', $border_style = null, $fill_color = null) { if ('0000' == $round_corner) // Not rounded $this->Rect($x, $y, $w, $h, $style, $border_style, $fill_color); else { // Rounded if (!(false === strpos($style, 'F')) && $fill_color) { list($red, $g, $b) = $fill_color; $this->SetFillColor($red, $g, $b); } switch ($style) { case 'F': $border_style = null; $op = 'f'; break; case 'FD': case 'DF': $op = 'B'; break; default: $op = 'S'; break; } if ($border_style) $this->SetLineStyle($border_style); $MyArc = 4 / 3 * (sqrt(2) - 1); $this->_Point($x + $r, $y); $xc = $x + $w - $r; $yc = $y + $r; $this->_Line($xc, $y); if ($round_corner[0]) $this->_Curve($xc + ($r * $MyArc), $yc - $r, $xc + $r, $yc - ($r * $MyArc), $xc + $r, $yc); else $this->_Line($x + $w, $y); $xc = $x + $w - $r ; $yc = $y + $h - $r; $this->_Line($x + $w, $yc); if ($round_corner[1]) $this->_Curve($xc + $r, $yc + ($r * $MyArc), $xc + ($r * $MyArc), $yc + $r, $xc, $yc + $r); else $this->_Line($x + $w, $y + $h); $xc = $x + $r; $yc = $y + $h - $r; $this->_Line($xc, $y + $h); if ($round_corner[2]) $this->_Curve($xc - ($r * $MyArc), $yc + $r, $xc - $r, $yc + ($r * $MyArc), $xc - $r, $yc); else $this->_Line($x, $y + $h); $xc = $x + $r; $yc = $y + $r; $this->_Line($x, $yc); if ($round_corner[3]) $this->_Curve($xc - $r, $yc - ($r * $MyArc), $xc - ($r * $MyArc), $yc - $r, $xc, $yc - $r); else { $this->_Line($x, $y); $this->_Line($x + $r, $y); } $this->_out($op); } } /* PRIVATE METHODS */ // Sets a draw point // Parameters: // - x, y: Point function _Point($x, $y) { $this->_out(sprintf('%.2F %.2F m', $x * $this->k, ($this->h - $y) * $this->k)); } // Draws a line from last draw point // Parameters: // - x, y: End point function _Line($x, $y) { $this->_out(sprintf('%.2F %.2F l', $x * $this->k, ($this->h - $y) * $this->k)); } // Draws a Bézier curve from last draw point // Parameters: // - x1, y1: Control point 1 // - x2, y2: Control point 2 // - x3, y3: End point function _Curve($x1, $y1, $x2, $y2, $x3, $y3) { $this->_out(sprintf('%.2F %.2F %.2F %.2F %.2F %.2F c', $x1 * $this->k, ($this->h - $y1) * $this->k, $x2 * $this->k, ($this->h - $y2) * $this->k, $x3 * $this->k, ($this->h - $y3) * $this->k)); } } ?> Don't forget to add require_once('FPDF/fpdf.php'); and require_once('FPDI/fpdi.php'); at the top of the page assuming you have this directory structure: Then with code in index.php instead of extending the class FPDI we can directly extend PDF_Draw. This way the code we add earlier still work but now we can use new methods like Line(), Curve(), Rect() etc... Here is the full index.php code: <?php require_once('draw.php'); // path of PDF file $fullPathToFile = "sample.pdf"; class PDF extends PDF_Draw { . . . } // initiate PDF $pdf = new PDF(); // go to first page $pdf->nextPage(); // add content to current page $pdf->SetFont("helvetica", "", 20); $pdf->SetTextColor(220, 20, 60); $pdf->Text(50, 20, "I should not be here!"); // move to next page and add content $pdf->nextPage(); $pdf->SetFont("arial", "", 15); $style = array('width' => 0.5, 'cap' => 'butt', 'join' => 'miter', 'dash' => '10,20,5,10', 'phase' => 10, 'color' => array(255, 0, 0)); $style2 = array('width' => 0.5, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(255, 0, 0)); $style3 = array('width' => 1, 'cap' => 'round', 'join' => 'round', 'dash' => '2,10', 'color' => array(255, 0, 0)); $style4 = array('L' => 0, 'T' => array('width' => 0.25, 'cap' => 'butt', 'join' => 'miter', 'dash' => '20,10', 'phase' => 10, 'color' => array(100, 100, 255)), 'R' => array('width' => 0.50, 'cap' => 'round', 'join' => 'miter', 'dash' => 0, 'color' => array(50, 50, 127)), 'B' => array('width' => 0.75, 'cap' => 'square', 'join' => 'miter', 'dash' => '30,10,5,10')); $style5 = array('width' => 0.25, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0)); $style6 = array('width' => 0.5, 'cap' => 'butt', 'join' => 'miter', 'dash' => '10,10', 'color' => array(0, 255, 0)); $style7 = array('width' => 0.5, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(200, 200, 0)); // Line $pdf->Text(5, 7, 'Line'); $pdf->Line(5, 10, 80, 30, $style); // Rect $pdf->Text(100, 7, 'Rectangle'); $pdf->Rect(100, 10, 40, 20, 'DF', $style4, array(220, 220, 200)); // Curve $pdf->Text(5, 37, 'Curve'); $pdf->Curve(5, 40, 30, 55, 70, 45, 60, 75, null, $style6); // Circle and ellipse $pdf->Text(5, 82, 'Circle and ellipse'); $pdf->SetLineStyle($style5); $pdf->Circle(25,105,20); // Polygon $pdf->Text(5, 132, 'Polygon'); $pdf->SetLineStyle(array('width' => 0.5, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))); $pdf->Polygon(array(5,135,45,135,15,165)); // Regular polygon $pdf->Text(5, 172, 'Regular polygon'); $pdf->SetLineStyle($style5); $pdf->RegularPolygon(20, 190, 15, 6, 0, 1, 'F'); // Star polygon $pdf->Text(5, 212, 'Star polygon'); $pdf->SetLineStyle($style5); $pdf->StarPolygon(20, 230, 15, 20, 3, 0, 1, 'F'); // Rounded rectangle $pdf->Text(5, 252, 'Rounded rectangle'); $pdf->SetLineStyle(array('width' => 0.5, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))); $pdf->RoundedRect(5, 255, 40, 30, 3.50, '1111', 'DF'); $pdf->SetTextColor(65, 105, 225); $pdf->Text(50, 20, "Me neither!!!"); //show the PDF in page $pdf->Output(); DEMO!
TCPDF (tcpdf.org) seems to handle PDF graphics methods. Cf. examples/example_012.php: // create new PDF document $pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false); // Line $pdf->Text(5, 4, 'Line examples'); $pdf->Line(5, 10, 80, 30, $style); $pdf->Line(5, 10, 5, 30, $style2); $pdf->Line(5, 10, 80, 10, $style3); // Rect $pdf->Text(100, 4, 'Rectangle examples'); $pdf->Rect(100, 10, 40, 20, 'DF', $style4, array(220, 220, 200)); $pdf->Rect(145, 10, 40, 20, 'D', array('all' => $style3)); And its GitHub project tecnickcom/tcpdf indicated being 100% PHP. However, this search shows it can create and modify a new PDF document. It might not be able to open and modify an existing one.
http://www.fpdf.org If You want to draw using x, y coordinates fpdf as well as tcpdf can be useful for you. global $title; // Calculate width $w = $this->GetStringWidth($title)+6; $this->SetX((210-$w)/2); // Colors of frame, background and text $this->SetDrawColor(0,80,180); $this->SetFillColor(230,230,0); $this->SetTextColor(220,50,50); // Thickness of frame (1 mm) $this->SetLineWidth(1); // Title $this->Cell($w,9,$title,1,1,'C',true); // Line break $this->Ln(10); }
How to create Double bar diagram using fpdf php?
I'm using FPDF in my php project. I would like to have PDF version Double bar diagram like above image in my project. There's a way that FPDF can create Pie chart and Bar diagram in http://www.fpdf.org/en/script/script28.php. But it's not double bar diagram like what I want to get. Anyone have an idea how to create Double bar diagram using FPDF in PHP? Many Thanks !!!
Probably you mean "COLUMN CHARTS" It seems that there is no method to create column charts, so I tried to adapt the existing bar chart. Unfortunately I have no time to develop it further. try this (making the necessary changes): <?php require('diag/sector.php'); class PDF_Diag extends PDF_Sector { var $legends; var $wLegend; var $sum; var $NbVal; function ColumnChart($w, $h, $data, $format, $color=null, $maxVal=0, $nbDiv=4) { // RGB for color 0 $colors[0][0] = 155; $colors[0][1] = 75; $colors[0][2] = 155; // RGB for color 1 $colors[1][0] = 0; $colors[1][1] = 155; $colors[1][2] = 0; // RGB for color 2 $colors[2][0] = 75; $colors[2][1] = 155; $colors[2][2] = 255; // RGB for color 3 $colors[3][0] = 75; $colors[3][1] = 0; $colors[3][2] = 155; $this->SetFont('Courier', '', 10); $this->SetLegends($data,$format); // Starting corner (current page position where the chart has been inserted) $XPage = $this->GetX(); $YPage = $this->GetY(); $margin = 2; // Y position of the chart $YDiag = $YPage + $margin; // chart HEIGHT $hDiag = floor($h - $margin * 2); // X position of the chart $XDiag = $XPage + $margin; // chart LENGHT $lDiag = floor($w - $margin * 3 - $this->wLegend); if($color == null) $color=array(155,155,155); if ($maxVal == 0) { foreach($data as $val) { if(max($val) > $maxVal) { $maxVal = max($val); } } } // define the distance between the visual reference lines (the lines which cross the chart's internal area and serve as visual reference for the column's heights) $valIndRepere = ceil($maxVal / $nbDiv); // adjust the maximum value to be plotted (recalculate through the newly calculated distance between the visual reference lines) $maxVal = $valIndRepere * $nbDiv; // define the distance between the visual reference lines (in milimeters) $hRepere = floor($hDiag / $nbDiv); // adjust the chart HEIGHT $hDiag = $hRepere * $nbDiv; // determine the height unit (milimiters/data unit) $unit = $hDiag / $maxVal; // determine the bar's thickness $lBar = floor($lDiag / ($this->NbVal + 1)); $lDiag = $lBar * ($this->NbVal + 1); $eColumn = floor($lBar * 80 / 100); // draw the chart border $this->SetLineWidth(0.2); $this->Rect($XDiag, $YDiag, $lDiag, $hDiag); $this->SetFont('Courier', '', 10); $this->SetFillColor($color[0],$color[1],$color[2]); $i=0; foreach($data as $val) { //Column $yval = $YDiag + $hDiag; $xval = $XDiag + ($i + 1) * $lBar - $eColumn/2; $lval = floor($eColumn/(count($val))); $j=0; foreach($val as $v) { $hval = (int)($v * $unit); $this->SetFillColor($colors[$j][0], $colors[$j][1], $colors[$j][2]); $this->Rect($xval+($lval*$j), $yval, $lval, -$hval, 'DF'); $j++; } //Legend $this->SetXY($xval, $yval + $margin); $this->Cell($lval, 5, $this->legends[$i],0,0,'C'); $i++; } //Scales for ($i = 0; $i <= $nbDiv; $i++) { $ypos = $YDiag + $hRepere * $i; $this->Line($XDiag, $ypos, $XDiag + $lDiag, $ypos); $val = ($nbDiv - $i) * $valIndRepere; $ypos = $YDiag + $hRepere * $i; $xpos = $XDiag - $margin - $this->GetStringWidth($val); $this->Text($xpos, $ypos, $val); } } function SetLegends($data, $format) { $this->legends=array(); $this->wLegend=0; $this->NbVal=count($data); } } $pdf = new PDF_Diag(); $pdf->AddPage(); $data[0] = array(470, 490, 90); $data[1] = array(450, 530, 110); $data[2] = array(420, 580, 100); // Column chart $pdf->SetFont('Arial', 'BIU', 12); $pdf->Cell(210, 5, 'Chart Title', 0, 1, 'C'); $pdf->Ln(8); $valX = $pdf->GetX(); $valY = $pdf->GetY(); $pdf->ColumnChart(110, 100, $data, null, array(255,175,100)); //$pdf->SetXY($valX, $valY); $pdf->Output(); ?>