"Title", "subtitle" => "description", "grad_x" => 25, "grad_y" => 20, "x_label" => "<= x =>", "y_label" => "<= y =>", "antialias" => false, "data" => [] ], $graph); $size = array_merge([ "image_width" => 750, "image_height" => 500, "x" => 90, "y" => 50, "width" => 650, "height" => 300, "square" => 11, "column" => 6 ], $size); $colors = array_merge([ "bg" => new ImagickPixel("#1d2021"), "lines_bg" => new ImagickPixel("#3c3836"), "outline" => new ImagickPixel("#a89984"), "text" => new ImagickPixel("#ebdbb2"), "transparent" => new ImagickPixel("transparent") ], $colors); $colors_line = array_merge([ new ImagickPixel("#83a598"), new ImagickPixel("#fb4934"), new ImagickPixel("#b8bb26"), new ImagickPixel("#fabd2f"), new ImagickPixel("#d3869b"), new ImagickPixel("#8ec07c"), new ImagickPixel("#fe8019"), new ImagickPixel("#458588"), new ImagickPixel("#cc241d"), new ImagickPixel("#98971a"), new ImagickPixel("#d79921"), new ImagickPixel("#b16286"), new ImagickPixel("#689d6a"), new ImagickPixel("#d65d0e"), new ImagickPixel("#a89984") // other ], $colors_line); $not_enough_data = false; // compute datapoint max ranges $max_range_x = 0; $max_range_y = 0; if(count($graph["data"]) === 0){ $not_enough_data = true; }else{ foreach($graph["data"] as $datapoint => $value){ if(count($value) < 1){ $not_enough_data = true; }else{ $nv1 = []; $nv2 = []; foreach($value as $k => $v){ $nv1[] = $v[0]; $nv2[] = $v[1]; } $max1 = max($nv1); $max2 = max($nv2); if($max_range_x < $max1){ $max_range_x = $max1; } if($max_range_y < $max2){ $max_range_y = $max2; } } } } $im = new Imagick(); $im->newImage($size["image_width"], $size["image_height"], $colors["bg"]); $im->setImageFormat("png"); $draw = new ImagickDraw(); // // Draw background grid // $draw->setStrokeColor($colors["lines_bg"]); $draw->setStrokeAntialias($graph["antialias"]); $draw->setStrokeWidth(1); $draw->setFillColor($colors["transparent"]); $text = new ImagickDraw(); $text->setFontSize(11); $text->setTextAntialias($graph["antialias"]); $text->setFillColor($colors["text"]); // vertical lines $offset = $size["width"] / ($graph["grad_x"] - 1); for($i=0; $i<$graph["grad_x"]; $i++){ $x = round($size["x"] + ($offset * $i)); if( $i === 0 || $i === $graph["grad_x"] - 1 ){ $draw->setStrokeColor($colors["outline"]); }else{ $draw->setStrokeColor($colors["lines_bg"]); } $draw->line( $x, $size["y"], $x, $size["y"] + $size["height"], ); if($not_enough_data === false){ // add numbas $number = number_format(round(($graph["grad_x"] - 1 - $i) * ($max_range_x / ($graph["grad_x"] - 1)))); $number_width = $im->queryFontMetrics($text, $number)["textWidth"]; $im->annotateImage( $text, round($x - ($number_width / 2)), $size["y"] + $size["height"] + 14, 0, $number ); } } // horizontal lines $text->setTextAlignment(Imagick::ALIGN_RIGHT); $offset = $size["height"] / ($graph["grad_y"] - 1); $vertical_text_size = 0; for($i=0; $i<$graph["grad_y"]; $i++){ $y = round($size["y"] + ($offset * $i)); if( $i === 0 || $i === $graph["grad_y"] - 1 ){ $draw->setStrokeColor($colors["outline"]); }else{ $draw->setStrokeColor($colors["lines_bg"]); } $draw->line( $size["x"] + 1, $y, $size["x"] + $size["width"] - 1, $y, ); if($not_enough_data === false){ $val = number_format(round(($graph["grad_y"] - 1 - $i) * ($max_range_y / ($graph["grad_y"] - 1)))); $query = $im->queryFontMetrics($text, $val); if($query["textWidth"] > $vertical_text_size){ $vertical_text_size = $query["textWidth"]; } // add numbas $im->annotateImage( $text, $size["x"] - 4, $y + 4, 0, $val ); } } // // Draw legend // $text->setTextAlignment(Imagick::ALIGN_LEFT); $top_padding = 44; $c = count($colors_line); $padding = $size["width"] / $size["column"]; $line = new ImagickDraw(); //$line->setStrokeWidth(1); $line->setStrokeAntialias($graph["antialias"]); if($not_enough_data === false){ $i = 0; foreach($graph["data"] as $datafield => $data){ $used_color = $colors_line[$i % $c]; $draw->setStrokeColor($used_color); $row = floor($i / $size["column"]); $x = round($size["x"] + (($i % $size["column"]) * $padding)); $y = $size["y"] + $size["height"] + $top_padding + ($row * 17); // draw legend $draw->rectangle( $x, $y, $x + $size["square"], $y + $size["square"] ); $im->annotateImage( $text, $x + $size["square"] + 4, $y + 10, 0, $datafield ); // // Draw lines // $line->setStrokeColor($used_color); $old_x = null; $old_y = null; $continue = true; foreach($data as $field){ // field 0 = hour (sorted) // field 1 = datapoint $x = $size["x"] + (($max_range_x - $field[0]) * ($size["width"] / $max_range_x)); $y = $size["y"] + (($max_range_y - $field[1]) * ($size["height"] / $max_range_y)); if($continue){ $continue = false; $old_x = $x; $old_y = $y; continue; } $line->line($old_x, $old_y, $x, $y); $old_x = $x; $old_y = $y; } $i++; } } // // add background labels // $text->setFontSize(13); $text->setFillColor($colors["bg"]); $draw->setFillColor($colors["text"]); $draw->setStrokeColor($colors["transparent"]); // horizontal $label_width_x = $im->queryFontMetrics($text, $graph["x_label"]); $x_x = $size["x"] + ($size["width"] / 2) - ($label_width_x["textWidth"] / 2); $x_y = $size["y"] + $size["height"] + ($not_enough_data ? 21 : 30); $draw->rectangle( $x_x - 2, $x_y - $label_width_x["textHeight"] + 4, $x_x + $label_width_x["textWidth"] + 2, $x_y + 3, ); // vertical $label_width_y = $im->queryFontMetrics($text, $graph["y_label"]); $y_x = $size["x"] - $label_width_y["textHeight"] - 13 - $vertical_text_size; $y_y = $size["y"] + ($size["height"] / 2) - ($label_width_y["textWidth"] / 2); $draw->rectangle( $y_x + 4, $y_y - 2, $y_x + $label_width_y["textHeight"] + 3, $y_y + $label_width_y["textWidth"] + 2, ); $im->drawImage($draw); $im->drawImage($line); // horizontal text $im->annotateImage( $text, $x_x, $x_y, 0, $graph["x_label"] ); // vertical text $im->annotateImage( $text, $y_x + $label_width_y["textHeight"], $y_y + $label_width_y["textWidth"], 270, $graph["y_label"] ); // // draw title + subtext // $text->setFontSize(20); $text->setFontWeight(900); $text->setFillColor($colors["text"]); $im->annotateImage( $text, $size["x"], $size["y"] - 25, 0, $graph["title"] ); $text->setFontSize(13); $text->setFontWeight(100); $im->annotateImage( $text, $size["x"], $size["y"] - 10, 0, $graph["subtitle"] ); if($not_enough_data){ // add not enough data notice $rect = new ImagickDraw(); $rect->setFillColor($colors["bg"]); $rect->setStrokeColor($colors_line[1]); $rect_w = 200; $rect_h = 24; $rect_x = round($size["x"] + ($size["width"] / 2) - ($rect_w / 2)); $rect_y = round($size["y"] + ($size["height"] / 2) - ($rect_h / 2)); $rect->rectangle( $rect_x, $rect_y, $rect_x + $rect_w, $rect_y + $rect_h ); $im->drawImage($rect); $label = "Not enough data"; $text->setFontWeight(900); $query = $im->queryFontMetrics($text, $label); $im->annotateImage( $text, round($size["x"] + ($size["width"] / 2) - ($query["textWidth"] / 2)), round($size["y"] + ($size["height"] / 2) + ($query["textHeight"] / 2)) - 3, 0, $label ); } return $im->getImageBlob(); } }