1

PHP と GD ライブラリを使用して、独自のカスタム スパイダー チャート ジェネレーターを作成しました。基本的に、ユーザーは一連の質問に回答し、質問への回答に基づいてスパイダー チャートが生成されます。

全体として、すべてがうまく機能します。生成されたグラフは数学的に正確で (ただし、クイズは完全に言い換える必要があります)、十分に迅速に機能するようです。ただし、Firefox (Snowleopard ではバージョン 15.0.1) から画像を保存しようとすると、画像自体を開くことができないことに気付きました。他のブラウザーから画像を保存すると、任意の画像エディターで開くことができる作業画像が生成されます。

私が特に興味深いと思うのは、いつ壊れるかです。これを正確に説明できるかどうかを確認します。

完全に機能するバージョンは [もうここにはありません ] です。チャート自体の処理と生成に関連するすべてのコードは次のとおりです。

chart.php (POST データの処理)

$r = 300; //Radius
//Processing of information passed from the previous form yields an array $cargs
//$cargs contains key value pairs. Values are of type float with a range 0-$r

$chart = new Chart($r); //Generates Canvas and Circle
$chart->generate($cargs); //Generates Polygon based on $cargs

header("Content-type: image/png");
imagesavealpha($chart->image, true);
imagepng($chart->image);
imagedestroy($chart->image);
?>

SS_Chart.php (チャート オブジェクト)

class Chart
{
    public $radius;
    public $diameter;
    public $image;

    private $_labels;
    private $_values;
    private $_n;

    public function Chart($r=300)
    {
        $this->radius = $r;
        $this->diameter = 2*$r;
        $this->image = $this->_get_transparent_canvas($this->diameter, $this->diameter);
        $this->_draw_circle();
    }
    public function generate($arr)
    {
        if(count($arr)>2)
        {
            $red = imagecolorallocate($this->image, 255, 0, 0);
            $this->_n = count($arr);
            $this->_labels = array_keys($arr);
            $this->_values = array_values($arr);

            $coors = array();
            for($i=0;$i<$this->_n;$i++)
            {
                //Generate coordinates....
            }
            imagefilledpolygon($this->image, $coors, $this->_n, $red);
        }
        else
            trigger_error('Number of $key=>$value pairs in arguments must be 3 or greater', E_USER_ERROR);
    }
    private function _get_transparent_canvas($w, $h)
    {
        $canvas = imagecreatetruecolor($w, $h);
        imagealphablending($canvas, true);
        $transparent = imagecolorallocatealpha($canvas, 0, 0, 0, 127);
        imagefill($canvas, 0, 0, $transparent);

        return $canvas;
    }
    private function _draw_circle()
    {
        $white = imagecolorallocate($this->image, 255, 255, 255);
        imagearc($this->image, $this->radius, $this->radius, $this->diameter, $this->diameter,  0, 360, $white);
    }
}

ここが興味深いところ$chart->generate($cargs);です。chart.php でコメントアウトすると、Firefox は寸法に応じて機能し、編集可能な透明な png と白い円を生成します。

ただし、public function generateSS_Chart.php 内のすべてをコメントアウトし、コメントを外したままにしておくと$chart->generate($cargs);(基本的に実行されるメソッドになりますが、実際には何もしません)、結果の png を開くことができなくなります。

そんなことがあるものか??

この問題については、Firefox を GD ライブラリと連携させる際のいくつかの問題について説明している奇妙なフォーラムを除けば、あまり見つけていませんが、このような問題に遭遇したのはこれが初めてです。

  • それが私のコードの問題である場合、その問題はすべてのブラウザーで蔓延しているのではないでしょうか?
  • これはスコーピングや、主な GD 機能がオブジェクト内で利用されているという事実と関係がありますか?
  • また、この問題は他の人にも起こりますか?
  • 以前にこのような問題に遭遇した人はいますか?
  • これは既知の問題ですか?

これは実際には、実際の「問題」というよりは好奇心ですが、この問題についての洞察をいただければ幸いです。

4

2 に答える 2

2

その保存された画像のソースを調べます

<br />
<b>Fatal error</b>:  Number of $key=>$value pairs in arguments must be 3 or greater in <b>/home/mattmaio/public_html/dev/assets/classes/SS_Chart.php</b> on line <b>38</b><br />

Firefoxで保存すると、fireoxは表示されたものを保存しません。それが行うことは、保存時に別のGET要求を行うことです。

GET http://dev.mattmaiorano.com/chart.php HTTP/1.1
Host: dev.mattmaiorano.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20100101 Firefox/15.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-gb,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: http://dev.mattmaiorano.com/chart.php

明らかに、すべてのPOSTデータが失われるため、エラーが発生します。あなたのコメントアウトについてはよくわかりませんが、それがそれだと思います。

于 2012-10-03T15:01:39.437 に答える
1

ここに 2 つの問題があります

  • 保存
  • 壊れた円

保存

あなたがすべきことは、画像を保存してreadfileから、この方法で出力するために使用することです。ファイルを再生成する必要はなく、Firefox でも動作します。

常にイメージを生成する必要がないことも、帯域幅を節約するのに役立ちます

サンプルコード

$r = 300; // $cargs
$tempDir = "xxx";
session_start();

__flush($tempDir);

if (isset($_POST) || ! isset($_SESSION['file'])) {
    $_SESSION['file'] = $tempDir . DIRECTORY_SEPARATOR . sha1(serialize($_POST)) . ".png";
}

header("Content-type: image/png");
$file = $_SESSION['file'];

if (file_exists($file)) {
    readfile($file);
} else {
    $chart = new Chart($r); // Generates Canvas and Circle
    $chart->generate(array("A" => array(40,50),"B" => array(20,240),"C" => array(60,60),"D" => array(240,20),"E" => array(50,40),"F" => array(10,10))); // Generates

    imagesavealpha($chart->image, true);
    imagepng($chart->image, $file);
    imagedestroy($chart->image);
}

壊れた円

壊れた円has nothing to do with Firefox..最初の調査で、独自の変数を使用してコードを実行すると、次の画像が生成されました..

ここに画像の説明を入力

問題

上の画像から、greenメーカーは壊れた円を示しています。以下が当てはまる場合、このエラーが発生することがわかりました。

キャンバスの幅 = 円の直径

次のように呼び出しているコードの形式は次のとおりです。

imagearc($this->image, $this->radius, $this->radius, $this->diameter, $this->diameter, 0, 360, $white);

解決

あなたがすべきことは、このようなもので円の直径を少し小さくすることです

  imagearc($this->image, $this->radius, $this->radius, ceil(0.9 * $this->diameter), ceil(0.9 * $this->diameter), 0, 360, $white);

そして、あなたは完全な円を得るでしょう

ここに画像の説明を入力

使用コード

$r = 300; // $cargs
$tempDir = "xxx";
session_start();

__flush($tempDir);

if (isset($_POST) || ! isset($_SESSION['file'])) {
    $_SESSION['file'] = $tempDir . DIRECTORY_SEPARATOR . sha1(serialize($_POST)) . ".png";
}

header("Content-type: image/png");
$file = $_SESSION['file'];

if (file_exists($file)) {
    readfile($file);
} else {
    $chart = new Chart($r); // Generates Canvas and Circle
    $chart->generate(array("A" => array(40,50),"B" => array(20,240),"C" => array(60,60),"D" => array(240,20),"E" => array(50,40),"F" => array(10,10))); // Generates

    imagesavealpha($chart->image, true);
    imagepng($chart->image, $file);
    imagedestroy($chart->image);
}

function __flush($tempDir) {
    $expire = 300; // 5mins
    $iterator = new DirectoryIterator($tempDir);
    foreach ( $iterator as $fileinfo ) {

        if ($fileinfo->isDot())
            continue;

        if ((time() - $fileinfo->getMTime()) > $expire) {
            @unlink($iterator->getPath());
        }
    }
}


class Chart {
    public $radius;
    public $diameter;
    public $image;
    private $_labels;
    private $_values;
    private $_n;

    public function Chart($r = 300) {
        $this->radius = $r;
        $this->diameter = 2 * $r;
        $this->image = $this->_get_transparent_canvas($this->diameter, $this->diameter);
        $this->_draw_circle();
    }

    public function generate($arr) {
        if (count($arr) > 2) {
            $red = imagecolorallocate($this->image, 255, 0, 0);
            $this->_n = count($arr);
            $this->_labels = array_keys($arr);
            $this->_values = array_values($arr);

            $coors = array();
            foreach ( $this->_values as $key => $value ) {
                $coors = array_merge($coors, $value);
            }
            imagefilledpolygon($this->image, $coors, $this->_n, $red);
        } else
            trigger_error('Number of $key=>$value pairs in arguments must be 3 or greater', E_USER_ERROR);
    }

    private function _get_transparent_canvas($w, $h) {
        $canvas = imagecreatetruecolor($w, $h);
        imagealphablending($canvas, true);
        $transparent = imagecolorallocatealpha($canvas, 0, 0, 0, 127);
        imagefill($canvas, 0, 0, $transparent);

        return $canvas;
    }

    private function _draw_circle() {
        $white = imagecolorallocate($this->image, 255, 255, 255);
        imagearc($this->image, $this->radius, $this->radius, ceil(0.9 * $this->diameter), ceil(0.9 * $this->diameter), 0, 360, $white);
        // imagearc($this->image, $this->radius, $this->radius,
    // $this->diameterCycle, $this->diameterCycle, 0, 360, $white);
    }
}
于 2012-10-05T11:33:00.703 に答える