PHP 生成图表。 CSS 错误。刻度错误。 SVG-多边形

PHP Generated Chart. CSS error. Scale wrong. SVG-Polygons

我写了一个使用 SVG-Poligons 来显示图表的脚本。

情况。我有一个具有最高价格和最低价格的产品。我每周一(称为周期)收集该信息。

我的系统计算产品的基本价格和获胜百分比并设置自己的价格。

示例

cycle | max   | min  | own
1     | 10.99 | 9.00 | 12.90
2     | 10.50 | 9.50 | 11.90
3     |  9.00 | 8.00 |  9.50

现在我用值画多边形。 为了做到这一点,我必须将 max-min-own Price 缩放到 100%,因为 poligons。看起来像这样

                   /B
                  / |
                 /  |
                /   |
               A    |
               |    |
               |   /D
               | /
               C/

图形不一样。来自传奇...只是一个视觉效果。

这是我目前的输出

但它必须像这样缩放

<?php
$sql_table_low = "SELECT t1.run_cycle,t1.ean,t1.shop,t1.price_total,t1.timestamp_update,t2.newprice FROM Horn_UPM_Product_Price_History as t1 inner join Horn_UPM_Product_Price_Change_History as t2 on t1.ean = t2.ean WHERE t1.ean = '".$artikel."' order by run_cycle,price_total";
// $content .= $sql_table_low;
$q = $readConnection->fetchAll($sql_table_low);
foreach($q as $row)
{
    $graph_raw[$row['run_cycle']][] = $row;
}
$g['maxheight-row'] = 0;
foreach($graph_raw as $row2)
{

    // $content .= "<br />".$row2[0]['shop'].'--'.$row2[(count($row2)-1)]['shop']."<br />";
    $graph[$row2[0]['run_cycle']] = array("low" => $row2[0]['price_total'],"low_shop" => $row2[0]['shop'],"high" => $row2[(count($row2)-1)]['price_total'],"high_shop" => $row2[(count($row2)-1)]['shop'],"timestamp" => $row2[0]['timestamp_update'],"price_set" => $row2[0]['newprice']);
    if($row2[(count($row2)-1)]['price_total']>$g['row-max'])
    {
        $g['row-max'] = $row2[(count($row2)-1)]['price_total'];
    }               
    if($row2[0]['price_total']<$g['row-min'])
    {
        $g['row-min'] = $row2[(count($row2)-1)]['price_total'];
    }
}
$content .= '<br><br>';

// ------------- Settings
$g['maxwidth'] = 800;
$g['maxheight'] = 600; // = 100%
$g['scale_hight'] = 600;
$g['dotsize'] = 6;
$g['dotcolor_height'] = 'green';
$g['dotcolor_low'] = 'red';
$g['dotcolor_fix'] = 'orange';
$g['linecolor'] = 'red';
$g['scale_multi'] = 50;
// DONT CHANGE AFTER THIS LINE
$g['colwidth'] = $g['maxwidth'] / count($graph);
$g['row_pixel_ratio'] = $g['maxheight'] / ($g['row-max']-$g['row-min']+100);
    $content .= '<div style="background:white;position:relative;width:'.$g['maxwidth'].'px;height:'.$g['maxheight'].'px;display:block;">';

        $row_count = 1;
        $height_old=0;
        $low_old=0;
        $fixo_price_old_scale=floor(($standartfixprice * 100) / $g['row-max']);
        $fixo_price_old=$standartfixprice;

        foreach(array_keys($graph) as $key)
        {
            // print_r($graph);
            $height_new = $graph[$key]['high'];
            $low_new = $graph[$key]['low'];
            if($height_old==0){$height_old=$height_new;}
            if($low_old==0){$low_old=$low_new;}


            // print_r($q2);
            // $height_new = rand(0,100);

            /*
                $dot[1] = array(0,0);       // Oben Links   // x,y
                $dot[2] = array(100,0);     // Oben Rechts  // x,y
                $dot[3] = array(100,100);   // Unten Rechts // x,y
                $dot[4] = array(0,100);     // Unten Links  // x,y

                $dot1[1] = array(0, high_old)
                $dot1[2] = array(colwidth, high_new)
                $dot1[3] = array(colwidth, low_new)
                $dot1[4] = array(0, low_old)

                (($high_old * 100) / $g['row-max']);
                (($high_new * 100) / $g['row-max']);
                (($low_new * 100) / $g['row-max']);
                (($low_old * 100) / $g['row-max']);

            */
                $dot[1] = array('x' => 0, 'y' => 100 - floor(($height_old * 100) / $g['row-max']));
                $dot[2] = array('x' => floor($g['colwidth']), 'y' => 100 - floor(($height_new * 100) / $g['row-max']));
                $dot[3] = array('x' => floor($g['colwidth']), 'y' => 100 - floor(($low_new * 100) / $g['row-max'])+$g['scale_multi']);
                $dot[4] = array('x' => 0, 'y' => 100 - floor(($low_old * 100) / $g['row-max'])+$g['scale_multi']);


                $sql_table_low_2 = "SELECT newprice*1.19 as fixprice FROM Horn_UPM_Product_Price_Change_History WHERE timestamp_unix < '".$graph[$key]['timestamp']."' AND ean = '".$artikel."' order by id DESC LIMIT 1";
                // $content .= $sql_table_low_2;
                $q2 = $readConnection->fetchRow($sql_table_low_2);
                if(!isset($q2['fixprice']))
                {                   
                    $fixo_price_new = 0;
                    $fixo_price_new_scale = 0;
                }
                else
                {
                    $fixo_price_new = $q2['fixprice'];
                    $fixo_price_new_scale = 100-floor(($q2['fixprice'] * 100) / $g['row-max']);
                }


                // $content .= 100 - floor(($height_old * 100) / $g['row-max']).'-';
                // $content .= 100 - floor(($height_new * 100) / $g['row-max']).'-';
                // $content .= 100 - floor(($low_new * 100) / $g['row-max']).'-';
                // $content .= 100 - floor(($low_old * 100) / $g['row-max']).'|||';

                // $content .= $dot[1]['y'].'-';
                // $content .= $dot[2]['y'].'-';
                // $content .= $dot[3]['y'].'-';
                // $content .= $dot[4]['y'].'|||';


                $height_old=$height_new;
                $low_old=$low_new;


                $fixo_price_old=$fixo_price_new;
                $fixo_price_old_scale=$fixo_price_new_scale;
                // print_r($dot);

            $content .= '
            <div style="position:absolute;left:'.floor($g['colwidth']*($key-1)).'px;width:'.floor($g['colwidth']).'px">
                <svg id="svg-'.$row_count.'" class="clip-svg" style="height:200px;">
                    <rect class="svg-bg-'.$row_count.'" width="'.floor($g['colwidth']).'" height="200" fill="#e6e6ff" />
                </svg>
                <svg id="svg-defs" style="height:0;">
                  <defs>
                    <clipPath id="clip-'.$row_count.'">
                      <polygon points="'.$dot[1]['x'].' '.$dot[1]['y'].', '.$dot[2]['x'].' '.$dot[2]['y'].', '.$dot[3]['x'].' '.$dot[3]['y'].', '.$dot[4]['x'].' '.$dot[4]['y'].'" />
                      <!-- <polygon points="0 0, '.$dot[2]['x'].' 0, '.$dot[3]['x'].' '.$dot[3]['y'].', '.$dot[4]['x'].' '.$dot[4]['y'].'" /> -->
                    </clipPath>
                  </defs>
                </svg>
            <style>
                .svg-bg-'.$row_count.' { clip-path: url(#clip-'.$row_count.'); }
            </style>

                <div class="dot_high" style="z-index:1000;position:absolute;top:'.$dot[2]['y'].'px;left:'.($g['colwidth']-$g['dotsize']/1.5).'px;height:'.$g['dotsize'].'px;width:'.$g['dotsize'].'px;background:'.$g['dotcolor_height'].';display:block;"></div>
                <div class="dot_low" style="z-index:1000;position:absolute;top:'.($dot[3]['y']-$g['dotsize']/1.5).'px;left:'.($g['colwidth']-$g['dotsize']/1.5).'px;height:'.$g['dotsize'].'px;width:'.$g['dotsize'].'px;background:'.$g['dotcolor_low'].';display:block;"></div>
                <div class="dot_fix" style="z-index:1000;position:absolute;top:'.($fixo_price_new_scale-$g['dotsize']/1.5).'px;left:'.($g['colwidth']-$g['dotsize']/1.5).'px;height:'.$g['dotsize'].'px;width:'.$g['dotsize'].'px;background:'.$g['dotcolor_fix'].';display:block;"></div>
            </div>';                    

            $row_count++;

        }

正如解释的那样,代码有效。但它缩放错误 (100%)..

SVG

这需要大量工作和大量混乱的代码,因此我将草拟出一个建议,告诉您如何解决此问题:

Svg 图

我不会通读你所有的代码,因为我一半都看不懂。
我会告诉你我们如何解决这个问题:
找出单行中的点数 我们将在这个例子中使用 5 个高点和 5 个低点。

$highArray = array(115, 117, 116, 117, 118);
$lowArray = array(113, 114, 114, 115);

现在我假设它必须扩展,因为你有:

 $g['maxheight'] = 600
 $g['maxwidth'] = 800

为了便于使用,我们称它们为

 $maxheight = 600
 $maxwidth = 800

我看到有; Linecolor、dotsize 等。这些不言而喻,所以我会像 $linecolor$dotsize

这样使用它们

因此我们的 svg 文档将是 600 个单位高和 800 个单位宽。 然后我们可以这样创建文档:

echo '<svg viewBox="0 ,0 '.$maxwidth.','.$maxheight.'" >';

希望您能关注。这是 svg,所以我们不使用像素大小,所以将它们排除在外。 接下来是添加图形:

现在我们需要看看这些点需要去哪里: 1. 我们希望它们均匀分布在整个 svg 上,所以我们将单个数组中的点数与 svg 的大小分开:

$ColumnSize = $maxwidth / $highArray + 1 ;
Example:
800 / 5 = 160 
in our example we will use 160 as each column size.

现在让我们用路径和圆元素创建图形:
Circles:

for($i=0; $i<$heightArray.count(); $i++) {
    echo '<circle class="circle-high" cx="'.($ColumnSize*i).'" cy="'.($maxheight - $highArray[i]).'" r="'.$dotSize.'" >';
}
//Same for $lowArray
echo '<circle class="circle-low" cx="'.($ColumnSize*n).'" cy="'.($maxheight - $lowArray[n]).'" r="'.$dotSize.'" >';

Path:

$xPath = "M";
for($i=0; $i<$hightArray.count(); $i++) {
    $xPath += " ".$ColumnSize*$i.",".($maxheight - $highArray[$i]);
}
for ($j=$lowArray.count(); $j>0; $j--) {
    $xPath += " ".$ColumnSize*$j.",".($maxheight - $lowArray[$j-1]);
}
echo '<path class="dotbackground" d="'.$xPath.'z"/>';

并将颜色添加到 css:

.circle-low {
   fill: red;
}
.circle-high {
   fill: green;
}
.dotbackground {
   fill: #ccc;
}

如果你做了所有这些,输出应该是这样的:

/*FOR DISPLAY ONLY*/
svg {
  height: 300px;
  border: 5px solid black;
}
/*END DISPLAY ONLY */
.circle-high {
  fill: red;
}
.circle-low {
  fill: green;
}
.dotbackground {
  fill: #aaa;
}
<svg viewBox="-5 0 800 600">
  <path class="dotbackground" d="M0,375 160,364, 320,374 480,363, 640,352 640,442 480,453 320,464 160,503 0,465z" />
  <circle class="circle-high" cx="0" cy="375" r="6" />
  <circle class="circle-high" cx="160" cy="363" r="6" />
  <circle class="circle-high" cx="320" cy="374" r="6" />
  <circle class="circle-high" cx="480" cy="363" r="6" />
  <circle class="circle-high" cx="640" cy="352" r="6" />
  <circle class="circle-low" cx="0" cy="465" r="6" />
  <circle class="circle-low" cx="160" cy="503" r="6" />
  <circle class="circle-low" cx="320" cy="464" r="6" />
  <circle class="circle-low" cx="480" cy="453" r="6" />
  <circle class="circle-low" cx="640" cy="442" r="6" />
  
</svg>

您可以考虑的附加功能:

  • 找到两个数组中的最低值和最高值,然后缩放它们在高度上的响应显示方式。
  • 通过 class 向 svg 文档添加 max-height: 和 max-width 并在 ccs
  • 中设置样式