封裝了一下gd庫,用起來方便一些,通過寫這個庫,基本熟悉了php的語法
下面是庫shape.ini文件
<?php
final class Range {
public $location;
public $length;
public function __construct($location, $length) {
$this->location = $location;
$this->length = $length;
}
}
final class Point {
public $x, $y;
public function __construct($x, $y) {
$this->x = $x;
$this->y = $y;
}
}
final class Size {
public $width, $height;
public function __construct($w, $h) {
$this->width = $w;
$this->height = $h;
}
}
final class Rect {
public $x, $y, $width, $height;
public function __construct($x, $y, $w, $h) {
$this->x = $x;
$this->y = $y;
$this->width = $w;
$this->height = $h;
}
}
final class Color {
public $red, $green, $blue;
public function __construct($r, $g, $b) {
$this->red = $r;
$this->green = $g;
$this->blue = $b;
}
}
class Context {
public $image;
public function __construct($size, $color) {
$this->image = imagecreatetruecolor($size->width, $size->height);
imageantialias($this->image, true);
$bgColor = imagecolorallocate($this->image, $color->red, $color->green, $color->blue);
imagefilledrectangle($this->image, 0, 0, $size->width, $size->height, $bgColor);
}
public function echoPNG() {
imagepng($this->image);
}
public function echoJPEG() {
imagejpeg($this->image);
}
public function __destruct() {
imagedestroy($this->image);
}
}
class Shape {
protected $context;
protected $points;
public $strokeColor;
public $fillColor;
private $lineWidth;
function __set($name, $value) {
if ($name == 'lineWidth') {
$this->lineWidth = $value;
imagesetthickness($this->context->image, $this->lineWidth);
}
}
public function __construct($context) {
$this->context = $context;
$this->points = Array();
$this->strokeColor = new Color(0, 0, 0);
$this->lineWidth = 1;
imagesetthickness($this->context->image, $this->lineWidth);
}
public function move($dx, $dy) {
for ($i = 0; $i < count($this->points); ++$i) {
$this->points[$i]->x += $dx;
$this->points[$i]->y += $dy;
}
}
public function draw() {
$this->drawLines();
}
protected function drawLines() {
if (isset($this->strokeColor)) {
for ($i = 1; $i < count($this->points); ++$i) {
$p1 = $this->points[$i-1];
$p2 = $this->points[$i];
$color = imagecolorallocate($this->context->image, $this->strokeColor->red, $this->strokeColor->green, $this->strokeColor->blue);
imageline($this->context->image, $p1->x, $p1->y, $p2->x, $p2->y, $color);
}
}
}
protected function addPoint($point) {
array_push($this->points, $point);
}
}
class Line extends Shape {
public function __construct($context, $point1, $point2) {
parent::__construct($context);
parent::addPoint($point1);
parent::addPoint($point2);
}
}
class Lines extends Shape {
public function add($point1, $point2) {
parent::addPoint($point1);
parent::addPoint($point2);
}
protected function drawLines() {
if (isset($this->strokeColor)) {
for ($i = 1; $i < count($this->points); $i+=2) {
$p1 = $this->points[$i-1];
$p2 = $this->points[$i];
$color = imagecolorallocate($this->context->image, $this->strokeColor->red, $this->strokeColor->green, $this->strokeColor->blue);
imageline($this->context->image, $p1->x, $p1->y, $p2->x, $p2->y, $color);
}
}
}
}
class Rectangle extends Shape {
public function __construct($context, $rect) {
parent::__construct($context);
parent::addPoint(new Point($rect->x, $rect->y));
parent::addPoint(new Point($rect->x+$rect->width, $rect->y));
parent::addPoint(new Point($rect->x+$rect->width, $rect->y+$rect->height));
parent::addPoint(new Point($rect->x, $rect->y+$rect->height));
}
protected function drawLines() {
$p0 = $this->points[0];
$p2 = $this->points[2];
if (isset($this->fillColor) && isset($this->strokeColor)) {
$color = imagecolorallocate($this->context->image, $this->fillColor->red, $this->fillColor->green, $this->fillColor->blue);
imagefilledrectangle($this->context->image, $p0->x, $p0->y, $p2->x, $p2->y, $color);
$color = imagecolorallocate($this->context->image, $this->strokeColor->red, $this->strokeColor->green, $this->strokeColor->blue);
imagerectangle($this->context->image, $p0->x, $p0->y, $p2->x, $p2->y, $color);
} else if (isset($this->strokeColor)) {
$color = imagecolorallocate($this->context->image, $this->strokeColor->red, $this->strokeColor->green, $this->strokeColor->blue);
imagerectangle($this->context->image, $p0->x, $p0->y, $p2->x, $p2->y, $color);
} else if (isset($this->fillColor)) {
$color = imagecolorallocate($this->context->image, $this->fillColor->red, $this->fillColor->green, $this->fillColor->blue);
imagefilledrectangle($this->context->image, $p0->x, $p0->y, $p2->x, $p2->y, $color);
}
}
}
class Arc extends Shape {
const Pie = IMG_ARC_PIE;
const Chord = IMG_ARC_CHORD;
const NoFill = IMG_ARC_NOFILL;
const Edged = IMG_ARC_EDGED;
public $style;
public $width;
public $height;
public $start;
public $end;
public function __construct($context, $center, $width, $height, $start, $end) {
parent::__construct($context);
parent::addPoint($center);
$this->width = $width;
$this->height = $height;
$this->start = $start;
$this->end = $end;
$this->style = Arc::Pie;
}
protected function drawLines() {
$center = $this->points[0];
if (isset($this->fillColor) && isset($this->strokeColor)) {
$color = imagecolorallocate($this->context->image, $this->fillColor->red, $this->fillColor->green, $this->fillColor->blue);
imagefilledarc($this->context->image, $center->x, $center->y, $this->width, $this->height, $this->start, $this->end, $color, $this->style);
$color = imagecolorallocate($this->context->image, $this->strokeColor->red, $this->strokeColor->green, $this->strokeColor->blue);
imagearc($this->context->image, $center->x, $center->y, $this->width, $this->height, $this->start, $this->end, $color);
} else if (isset($this->strokeColor)) {
$color = imagecolorallocate($this->context->image, $this->strokeColor->red, $this->strokeColor->green, $this->strokeColor->blue);
imagearc($this->context->image, $center->x, $center->y, $this->width, $this->height, $this->start, $this->end, $color);
} else if (isset($this->fillColor)) {
$color = imagecolorallocate($this->context->image, $this->fillColor->red, $this->fillColor->green, $this->fillColor->blue);
imagefilledarc($this->context->image, $center->x, $center->y, $this->width, $this->height, $this->start, $this->end, $color, $this->style);
}
}
}
class Ellipse extends Arc {
public function __construct($context, $center, $width, $height) {
parent::__construct($context, $center, $width, $height, 0, 360);
}
}
class Circle extends Ellipse {
public function __construct($context, $center, $radius) {
parent::__construct($context, $center, $radius, $radius);
}
}
class Text extends Shape {
const Horizontal = 0;
const Vertical = 1;
public $orientaion;
public $text;
public $font;
public function __construct($context, $point, $text) {
parent::__construct($context);
parent::addPoint($point);
$this->text = $text;
$this->font = 5;
$this->orientaion = Text::Horizontal;
}
protected function drawLines() {
$point = $this->points[0];
$color = imagecolorallocate($this->context->image, $this->strokeColor->red, $this->strokeColor->green, $this->strokeColor->blue);
if ($this->orientaion == Text::Horizontal)
imagestring($this->context->image, $this->font, $point->x, $point->y, $this->text, $color);
else
imagestringup($this->context->image, $this->font, $point->x, $point->y, $this->text, $color);
}
}
class OpenPolyline extends Shape {
public function addPoint($point) {
parent::addPoint($point);
}
}
class ClosedPolyline extends OpenPolyline {
protected function drawLines() {
if (isset($this->strokeColor)) {
parent::drawLines();
$lastPoint = end($this->points);
$point0 = $this->points[0];
$color = imagecolorallocate($this->context->image, $this->strokeColor->red, $this->strokeColor->green, $this->strokeColor->blue);
imageline($this->context->image, $lastPoint->x, $lastPoint->y, $point0->x, $point0->y, $color);
}
}
}
class Polygon extends ClosedPolyline {
public function __construct($context) {
parent::__construct($context);
$this->fillColor = new Color(0, 0, 0);
}
protected function drawLines() {
if (isset($this->fillColor)) {
$color = imagecolorallocate($this->context->image, $this->fillColor->red, $this->fillColor->green, $this->fillColor->blue);
$points = Array();
foreach ($this->points as $point) {
array_push($points, $point->x);
array_push($points, $point->y);
}
imagefilledpolygon($this->context->image, $points, count($this->points), $color);
}
parent::drawLines();
}
}
class Axis extends Shape {
const X = 0;
const Y = 1;
const Z = 2;
private $notchLines;
public function __construct($context, $orientation, $origin, $length, $n) {
parent::__construct($context);
$this->addPoint($origin);
switch ($orientation) {
case Axis::X:
$this->addPoint(new Point($origin->x+$length, $origin->y));
if ($n > 1) {
$this->notchLines = new Lines($this->context);
$dist = $length / $n;
$x = $origin->x + $dist;
for ($i = 0; $i < $n; ++$i) {
$this->notchLines->add(new Point($x, $origin->y), new Point($x, $origin->y-5));
$x += $dist;
}
}
break;
case Axis::Y:
$this->addPoint(new Point($origin->x, $origin->y-$length));
if ($n > 1) {
$this->notchLines = new Lines($this->context);
$dist = $length / $n;
$y = $origin->y - $dist;
for ($i = 0; $i < $n; ++$i) {
$this->notchLines->add(new Point($origin->x, $y), new Point($origin->x+5, $y));
$y -= $dist;
}
}
break;
case Axis::Z:
break;
default:
break;
}
}
protected function drawLines() {
parent::drawLines();
$this->notchLines->draw();
}
}
class Func extends Shape {
public function __construct($context, $func, $range, $point, $count, $xScale, $yScale) {
parent::__construct($context);
if (is_callable($func)) {
$dist = ($range->length - $range->location) / $count;
$r = $range->location;
for ($i = 0; $i < $count; ++$i) {
$result = call_user_func($func, $r);
$this->addPoint(new Point($point->x+$r*$xScale, $point->y-$result*$yScale));
$r += $dist;
}
}
}
}
?>
下面是測試文件test.php
<?php
header("Content-Type:text/json; charset=utf-8");
header("Content-Type: image/png");
require_once 'shape.inc';
$context = new Context(new Size(800, 600), new Color(0xcc, 0xcc, 0xcc));
$line = new Line($context, new Point(300, 100), new Point(600, 50));
$line->lineWidth = 2;
$line->strokeColor = new Color(0xff, 0, 0);
$line->draw();
$rect = new Rectangle($context, new Rect(50, 50, 200, 100));
$rect->draw();
$rect->move(50, 50);
$rect->draw();
$arc = new Arc($context, new Point(500, 400), 200, 200, 0, 300);
$arc->lineWidth = 2;
$arc->draw();
$ellipse = new Ellipse($context, new Point(200, 300), 300, 200);
$ellipse->draw();
$circle = new Circle($context, new Point(400, 200), 100);
$circle->draw();
$opl = new ClosedPolyline($context);
$opl->addPoint(new Point(345, 232));
$opl->addPoint(new Point(545, 232));
$opl->addPoint(new Point(345, 332));
$opl->addPoint(new Point(245, 432));
$opl->addPoint(new Point(345, 532));
$opl->draw();
$polygon = new Polygon($context);
$polygon->addPoint(new Point(170, 70));
$polygon->addPoint(new Point(320, 140));
$polygon->addPoint(new Point(270, 320));
$polygon->addPoint(new Point(50, 330));
$polygon->addPoint(new Point(65, 160));
$polygon->lineWidth = 3;
$polygon->strokeColor = new Color(0xff, 0, 0);
$polygon->fillColor = new Color(0, 0, 0xff);
$polygon->draw();
$rect = new Rectangle($context, new Rect(350, 300, 300, 200));
$rect->lineWidth = 3;
$rect->strokeColor = new Color(0xff, 0, 0);
$rect->draw();
$arc = new Arc($context, new Point(500, 400), 300, 200, 0, 270);
$arc->lineWidth = 2;
$arc->fillColor = new Color(0, 0xcc, 0);
$arc->draw();
$circle = new Circle($context, new Point(400, 200), 100);
$circle->fillColor = new Color(0xcc, 0xcc, 0);
$circle->draw();
$lines = new Lines($context);
for ($i = 1; $i < 5; ++$i) {
$lines->add(new Point(500, 50*$i), new Point(700, 50*$i));
}
$lines->draw();
$xAxis = new Axis($context, Axis::X, new Point(100, 300), 600, 10);
$xAxis->draw();
$text = new Text($context, new Point(700, 300), 'x');
$text->draw();
$yAxis = new Axis($context, Axis::Y, new Point(400, 600), 600, 10);
$yAxis->draw();
$text = new Text($context, new Point(390, 0), 'y');
$text->draw();
$sineFunc = new Func($context, sin, new Range(0, 50), new Point(100, 350), 100, 30, 30);
$sineFunc->draw();
$cosineFunc = new Func($context, cos, new Range(0, 50), new Point(100, 300), 500, 30, 30);
$cosineFunc->strokeColor = new Color(0, 0xff, 0xff);
$cosineFunc->draw();
$tanFunc = new Func($context, tan, new Range(0, 50), new Point(100, 300), 500, 30, 30);
$tanFunc->draw();
/*
* y = x;
*/
function line($x) {
return $x;
}
/*
* y = x^2;
*/
function powerx($x) {
return $x*$x;
}
/*
* 第一個參數是畫布
* 第二個參數是你定義的函數
* 第三個參數是x軸變化範圍[0-50)
* 第四個參數是原點在畫布的位置
* 第五個參數是精度
* 第六個參數是x軸縮放比例
* 第七哥參數是y軸縮放比例
*/
$func = new Func($context, powerx, new Range(-10, 10), new Point(400, 300), 1000, 30, 30);
$func->draw();
$context->echoPNG();
?>
效果