Navigation
 Startseite
 Fachbücher
 Anzeigenmarkt
 Forum
 Webmaster News
 Script Newsletter
 Push Meldungen
 Kontakt
 Script Installation
 Php
 Php Tutorials
 Lernpfade
 Webhoster Vergleich
 Impressum

Community-Bereich
 kostenlos Registrieren
 Anmelden
 Benutzerliste

Script Datenbank
 Script Archiv
 Script Top 20
 Screenshots
 Testberichte

Suche
 

Unsere Php Scripts
 Counter Script
 Umfrage Script
 Bilder Upload Script
 Terminverwaltung
 Simple PHP Forum
 RSS Grabber

Tools und Generatoren
 .htpasswd Generator
 md5 Generator
 base64 Generator
 Markdown to HTML
 Colorpicker
 Unix timestamp Tool
 Unit Test Generator
 TLD Liste
 Webkatalog‑Verzeichnis

Artfiles.de
Bietet Serviceorientierte...
https://www.Artfiles.de
Hosterplus.de
Bekommen Sie Speicherplatz (Webspace), Domains...
https://www.Hosterplus.de
 
 
 

PHP imagearc() Function: Bögen und Kreise mit GD zeichnen

Sie befinden sich: Home > Php Tutorial > PHP imagearc() Function: Bö...

PHP imagearc() Function: Bögen und Kreise mit GD zeichnen
Veröffentlicht am:
28.09.2026
Hits / Besucher:
9
Sprache:
  Deutsch
Tutorial Art:
eigenes
Eingetragen von:
Merkliste:
 
Beschreibung

Ein Auswertungsskript soll den Anteil erledigter Aufträge als Ring ins Wochenprotokoll schreiben, und zwar als fertiges PNG ohne eine Zeile JavaScript im Browser. Eine Diagrammbibliothek dafür einzubinden wäre viel Aufwand für einen einzigen Kreis. Die GD-Bibliothek liegt in nahezu jeder PHP-Installation bereit und bringt mit PHP imagearc die Funktion für runde Formen gleich mit. Ein Satz vorweg, der viel Sucherei spart: PHP imagearc() zeichnet eine Linie entlang eines Bogens, sonst nichts. Wer die ganze Ellipse will, nimmt imageellipse() und spart sich die Winkel. Wer eine gefüllte Fläche will, nimmt imagefilledarc(). Bildressource, Farbanlage und Ausgabe stehen im Tutorial zur GD-Bibliothek und werden hier vorausgesetzt.

Illustration zum Tutorial: PHP imagearc() Function: Bögen und Kreise mit GD zeichnen

Drei Angaben entscheiden über jeden Aufruf: der Mittelpunkt, das umschließende Rechteck und die beiden Winkelmarken. Mehr Stellschrauben gibt es nicht, und die Grafik darüber ordnet sie einander zu.

Was PHP imagearc() zeichnet: Bögen, Kreise und Ellipsen

Die Funktion legt eine ein Pixel starke Linie auf ein bestehendes Bild, und zwar entlang des Randes einer gedachten Ellipse. Welcher Teil dieses Randes sichtbar wird, entscheiden Startwinkel und Endwinkel. Alles andere bleibt unberührt. Es entsteht kein neues Bild, es wird nichts gefüllt, und der Rückgabewert ist ein reiner Wahrheitswert, den man in der Praxis nicht auswerten muss: Ein falscher Bildtyp löst seit PHP 8 einen TypeError aus, und ein unbekannter Farbindex wird stillschweigend hingenommen. Nachgemessen mit dem Index 999999 kommt trotzdem true zurück.

Das kleinste lauffähige Beispiel kommt mit fünf Zeilen Vorbereitung und einer Zeile für den Bogen aus: Truecolor-Bild anlegen, Hintergrund füllen, Farbe reservieren, zeichnen, als PNG ausliefern.

<?php

$bild = imagecreatetruecolor(300, 200);
$weiss = imagecolorallocate($bild, 255, 255, 255);
$blau = imagecolorallocate($bild, 40, 90, 200);
imagefilledrectangle($bild, 0, 0, 299, 199, $weiss);

imagearc($bild, 150, 100, 160, 160, 0, 360, $blau);

header('Content-Type: image/png');
imagepng($bild);
imagedestroy($bild);

Dieser Aufruf ergibt einen geschlossenen Kreis, weil Start- und Endwinkel den vollen Umlauf abdecken. Sobald die beiden Zahlen enger zusammenrücken, bleibt ein Ausschnitt stehen. Damit ist der Kern von PHP imagearc() beschrieben, und der Rest des Tutorials dreht sich um die Frage, welche Zahl an welche Stelle gehört.

Syntax: die Signatur im Original

Acht Parameter, davon sechs reine Zahlen. Zusammengefasst sieht die Funktion so aus:

<?php

imagearc(
GdImage $image,
int $center_x,
int $center_y,
int $width,
int $height,
int $start_angle,
int $end_angle,
int $color
): bool

/* draws a single line along an arc of an
ellipse; it does not fill and it does not
create a new image

center_x, center_y: the center of the
circle, in pixels from the top left corner
width and height: the bounding box, that is
the diameter and not the radius
start_angle, end_angle: the two points on
the arc, in degrees; the arc is drawn
clockwise, and 0 is located at the
three-o'clock position
color: an index from imagecolorallocate(),
not a hex value on palette images

returns true; a wrong image type raises a
TypeError, an unknown color index does not */

Drei Angaben aus diesem Block tragen alles Weitere. Erstens beschreiben $width und $height das umschließende Rechteck und nicht den Radius. Zweitens stehen die Winkel in Grad und nicht im Bogenmaß, ein deg2rad() im Aufruf wäre also falsch. Drittens erwartet der achte Parameter einen Farbindex aus imagecolorallocate(). Auf einem Truecolor-Bild ist dieser Index nichts anderes als der Farbwert selbst, ein 0x2858C8 malt dort also genau dieses Blau. Auf einem Palettenbild aus imagecreate() ist dieselbe Zahl dagegen eine Position in der Farbtabelle, im Beispiel die Nummer 200, und die ist gar nicht belegt.

width und height sind Durchmesser, keine Radien

Dieser Fehler ist still: Das Ergebnis ist ein sauberer Kreis, nur eben doppelt so groß wie geplant, und nichts im Code deutet darauf hin. Wer aus der Geometrie kommt, liest die vierte und fünfte Zahl als Radius. GD meint damit die Kantenlängen des Rechtecks, in das die Ellipse passt.

<?php

/* Radius 50 gewollt, also Durchmesser 100 */
imagearc($bild, 150, 100, 100, 100, 0, 360, $blau);

/* dieser Aufruf ergibt nur Radius 25 */
imagearc($bild, 150, 100, 50, 50, 0, 360, $blau);

/* ungleiche Werte ergeben eine Ellipse */
imagearc($bild, 150, 100, 220, 90, 0, 360, $blau);

Die Merkregel ist kurz: Halbe Breite ist der Radius. Sind Breite und Höhe gleich, entsteht ein Kreis, sonst eine Ellipse. Wer mit einem Radius rechnet, sollte ihn im Code auch so nennen und erst im Aufruf verdoppeln. Dann steht die Verdopplung an einer Stelle statt verstreut im ganzen Skript.

Winkel rund um cx und cy: null Grad liegt auf drei Uhr

Die zweite Stolperfalle sitzt in der Zählrichtung. In der Schulmathematik beginnt der Winkel rechts und wächst gegen den Uhrzeigersinn. GD beginnt ebenfalls rechts, zählt aber im Uhrzeigersinn, weil die y-Achse eines Bildes nach unten zeigt. 0° liegt also auf drei Uhr, 90° unten, 180° links und 270° oben. Ein Viertelbogen von 0° bis 90° landet damit unten rechts und nicht oben rechts.

In alten Handbuchkommentaren steht, für einen vollen Kreis dürfe man nicht 0 und 360 angeben. Das gilt heute nicht mehr: Der Aufruf mit 0 und 360 schließt den Kreis lückenlos. Eine echte Grenze liegt dagegen darüber, denn GD rechnet beide Winkel zunächst modulo 360. Aus 0 bis 370 wird deshalb ein Bogen von 0 bis 10 Grad, und aus 270 bis 630 der volle Umlauf.

flowchart TD
    A[Bild anlegen] --> B[Farbe reservieren]
    B --> C{Ganzer Kreis?}
    C -- ja --> D[imageellipse]
    C -- nein --> E[Winkel festlegen]
    E --> F{Fläche füllen?}
    F -- ja --> G[imagefilledarc]
    F -- nein --> H[imagearc]
    D --> I[PNG ausgeben]
    G --> I
    H --> I

Prozentwerte werden vor dem Aufruf in Grad umgerechnet, und zwar mit dem Dreisatz statt mit einer fertigen Hilfsfunktion. Für Beschriftungen oder für den Abschluss eines Segments mit imageline() braucht man zusätzlich den Punkt auf dem Bogen. Hier kommt deg2rad() doch noch zum Einsatz, aber in der eigenen Rechnung und nicht im Parameter von PHP imagearc().

<?php

$cx = 150;
$cy = 110;
$breite = 180;
$hoehe = 180;

$grad = 42 / 100 * 360;
$winkel = deg2rad($grad);

$x = $cx + cos($winkel) * $breite / 2;
$y = $cy + sin($winkel) * $hoehe / 2;
imageline($bild, $cx, $cy, (int) $x, (int) $y, $blau);

PHP imagearc(), imageellipse() und imagefilledarc() im Vergleich

Drei Funktionen, die sich in der Schreibweise ähneln und verschiedene Aufgaben haben. Die Wahl fällt nach zwei Fragen: Brauche ich einen Ausschnitt oder die ganze Form, und soll die Fläche gefüllt sein?

Funktion Was entsteht Winkel Passt bei
imagearc() eine Linie entlang des Bogens Start und Ende Umrisse, Kreislinien, Skalenbögen
imageellipse() die vollständige Umrisslinie keine ganze Kreise und Ellipsen ohne Rechnerei
imagefilledarc() gefüllte Fläche oder Kontur, je nach Stil Start, Ende und Füllstil Tortensegmente, Ringe, Fortschrittsanzeigen

Der neunte Parameter von imagefilledarc() steuert die Form der Füllung. IMG_ARC_PIE schließt das Segment zum Mittelpunkt hin, IMG_ARC_CHORD setzt stattdessen eine gerade Sehne zwischen Anfang und Ende, IMG_ARC_NOFILL zeichnet nur die Kontur und IMG_ARC_EDGED lässt sich mit den anderen kombinieren. Die Kombination IMG_ARC_NOFILL | IMG_ARC_EDGED zeichnet die Kontur eines Tortenstücks, also den Bogen und die beiden Radien zum Mittelpunkt, ohne die Fläche zu füllen. Wer dasselbe mit PHP imagearc() bauen will, braucht zwei zusätzliche imageline()-Aufrufe und die Punktrechnung aus dem Abschnitt davor. Eine Schleife über PHP imagearc() mit wachsendem Durchmesser steht in vielen Handbuchkommentaren als Rezept für gefüllte Flächen. Sie ist langsam und hinterlässt ausgefranste Kanten, weil benachbarte Bögen nicht lückenlos aneinanderliegen.

Praxis: ein Tortendiagramm aus mehreren Segmenten

Ein Tortendiagramm ist eine Schleife über ein Wertearray. Der Endwinkel eines Segments wird zum Startwinkel des nächsten, damit keine Lücke entsteht. Wichtig ist der letzte Durchlauf: Dort wird nicht neu gerechnet, sondern hart bis 360 Grad gezeichnet. Sonst bleibt durch die Rundung auf ganze Grad ein dünner Keil in Hintergrundfarbe stehen, und der fällt ausgerechnet bei runden Prozentwerten auf.

<?php

$werte = ['PHP' => 45, 'SQL' => 30, 'JS' => 25];
$farben = [$blau, $grau, $dunkel];
$summe = array_sum($werte);

$start = 0.0;
$nr = 0;
$letzte = count($werte) - 1;

foreach ($werte as $wert) {
$ende = $nr === $letzte
? 360.0
: $start + $wert / $summe * 360;

imagefilledarc(
$bild, 150, 110, 180, 180,
(int) round($start), (int) round($ende),
$farben[$nr], IMG_ARC_PIE
);
$start = $ende;
$nr++;
}

imagearc($bild, 150, 110, 180, 180, 0, 360, $rand);

Die letzte Zeile ist der Grund, warum PHP imagearc() hier trotz der gefüllten Segmente auftaucht: Sie legt einen sauberen Außenrand um die fertige Torte. Weil die Segmentränder durch das Runden minimal ungleich ausfallen, kaschiert dieser eine Aufruf das Ergebnis deutlich. Dieselbe Technik zeigt das Tutorial zu imagepolygon() für gerade Kanten.

Ein Fortschrittsring aus zwei gefüllten Segmenten

Ein Fortschrittsring sieht aus wie ein dicker Bogen, wird aber nicht als Bogen gebaut. Der saubere Weg geht über zwei gefüllte Kreissegmente und eine Ausstanzung: erst die graue Spur als voller Kreis, darüber das farbige Segment bis zum gewünschten Winkel, zum Schluss ein Kreis in Hintergrundfarbe in der Mitte. Das ergibt gleichmäßige Stärke und harte Kanten ohne jedes Nachbessern.

<?php

function ring(int $prozent): GdImage
{
$b = imagecreatetruecolor(220, 220);
$hg = imagecolorallocate($b, 255, 255, 255);
$spur = imagecolorallocate($b, 225, 225, 225);
$voll = imagecolorallocate($b, 40, 90, 200);
imagefilledrectangle($b, 0, 0, 219, 219, $hg);

$grad = (int) round($prozent / 100 * 360);

imagefilledarc(
$b, 110, 110, 180, 180,
0, 360, $spur, IMG_ARC_PIE
);

if ($grad > 0) {
imagefilledarc(
$b, 110, 110, 180, 180,
270, 270 + $grad, $voll, IMG_ARC_PIE
);
}

imagefilledellipse($b, 110, 110, 130, 130, $hg);

return $b;
}

Der Startwinkel 270 sorgt dafür, dass der Ring oben beginnt, so wie man es von Fortschrittsanzeigen kennt. Dass der Endwinkel bei 100 Prozent rechnerisch auf 630 läuft, stört GD nicht: Modulo 360 bleibt wieder 270 stehen, und zwei gleiche Winkel ergeben den vollen Umlauf. Genau daran hängt aber die Abfrage $grad > 0. Ohne sie lautete der Aufruf bei null Prozent imagefilledarc(…, 270, 270, …), und aus derselben Regel würde statt eines leeren Rings eine volle Anzeige. Wer dem Ring zusätzlich eine feine Trennlinie geben will, zieht sie mit PHP imagearc() auf demselben Durchmesser nach.

Linienstärke und Antialiasing

imagesetthickness() wirkt auf PHP imagearc() und gilt ab dem Aufruf für alle folgenden Zeichenbefehle, bis sie wieder zurückgesetzt wird. Bis etwa drei Pixel sieht das Ergebnis gut aus. Darüber franst die Linie an den Flanken aus, weil GD die Dicke aus mehreren versetzten Einzellinien zusammensetzt, statt den Bogen wirklich zu verbreitern. Wer eine dicke, saubere Ringlinie braucht, nimmt dafür besser zwei gefüllte Segmente wie im Abschnitt davor.

<?php

foreach ([1, 3, 6] as $i => $staerke) {
imagesetthickness($bild, $staerke);
$x = 60 + $i * 95;
imagearc($bild, $x, 100, 70, 70, 0, 360, $blau);
}
imagesetthickness($bild, 1);

Eine zweite Erwartung wird ebenfalls enttäuscht: imageantialias() glättet Linien und Vielecke, Bögen aber nicht. Die Funktion lässt sich aufrufen, sie meldet auch keinen Fehler, und die Treppenstufen bleiben trotzdem sichtbar. Der einzig verlässliche Ausweg ist, doppelt oder vierfach so groß zu zeichnen und das Ergebnis anschließend mit imagecopyresampled() zu verkleinern. Das Verkleinern mittelt die Kanten und kostet nur wenig Rechenzeit. Wie dieses Herunterrechnen im Detail arbeitet, zeigt das Tutorial zu imagecrop() am verwandten Fall des Zuschneidens.

Fazit

Zwei Zahlenpaare entscheiden über das Ergebnis: Breite und Höhe sind Durchmesser, und die Winkel laufen ab drei Uhr im Uhrzeigersinn. Wer diese beiden Sätze im Kopf hat, trifft mit PHP imagearc() auf Anhieb die richtige Größe und die richtige Lage. Für ganze Kreise ist imageellipse() der kürzere Weg, für gefüllte Segmente imagefilledarc(), und PHP imagearc() bleibt der Griff zur reinen Linie. Tortendiagramm und Fortschrittsring aus den beiden Praxisabschnitten lassen sich fast unverändert in ein Adminwerkzeug übernehmen. Sie brauchen keine Bibliothek, kein Paket und keinen Aufruf nach draußen.

 

Tags:

 

 

Kommentare (0)

Noch keine Kommentare. Sei der Erste!

Melde dich an, um einen Kommentar zu schreiben.
Bücherregal mit drei Büchern: 'PHP 4 - Grundlagen und Profiwissen' von Hanser Verlag, 'Webdesign in a Nutshell' von O'Reilly Verlag, und 'Webgestaltung' von Galileo Computing.