2011-01-26 172 views
92

我正在研究一個涉及美國動態生成的地圖的Web項目,它基於一組數據着色不同的狀態。使用PHP將SVG圖像轉換爲PNG

這個SVG文件給了我一個很好的美國空白地圖,很容易改變每個州的顏色。難點在於IE瀏覽器不支持SVG,所以爲了讓我使用svg提供的便捷語法,我需要將它轉換爲JPG格式。

理想情況下,我想只用GD2庫做到這一點,但也可以使用ImageMagick。我完全不知道如何做到這一點。

任何解決方案都會允許我動態更改美國地圖上的州的顏色。關鍵是,它很容易改變顏色,它是跨瀏覽器。請僅使用PHP/Apache解決方案。

+0

是有設計的端口任何SVG班到VML?這樣你仍然可以有一個'HTML5'型解決方案 – Patrick 2011-01-26 19:54:26

+0

看看我的答案。正是你所需要的 – 2011-01-26 20:48:40

回答

115

這很有趣,你問這個問題,我只是做了這個最近對我的工作的網站,我想我應該寫一個教程...這裏是如何與ImageMagick的做到這一點:

$usmap = '/path/to/blank/us-map.svg'; 
$im = new Imagick(); 
$svg = file_get_contents($usmap); 

/*loop to color each state as needed, something like*/ 
$idColorArray = array(
    "AL" => "339966" 
    ,"AK" => "0099FF" 
    ... 
    ,"WI" => "FF4B00" 
    ,"WY" => "A3609B" 
); 

foreach($idColorArray as $state => $color){ 
//Where $color is a RRGGBB hex value 
    $svg = preg_replace(
     '/id="'.$state.'" style="fill:#([0-9a-f]{6})/' 
     , 'id="'.$state.'" style="fill:#'.$color 
     , $svg 
    ); 
} 

$im->readImageBlob($svg); 

/*png settings*/ 
$im->setImageFormat("png24"); 
$im->resizeImage(720, 445, imagick::FILTER_LANCZOS, 1); /*Optional, if you need to resize*/ 

/*jpeg*/ 
$im->setImageFormat("jpeg"); 
$im->adaptiveResizeImage(720, 445); /*Optional, if you need to resize*/ 

$im->writeImage('/path/to/colored/us-map.png');/*(or .jpg)*/ 
$im->clear(); 
$im->destroy(); 

步驟正則表達式顏色替換可能因SVG路線XML以及如何存儲你的ID &顏色值會有所不同。如果您不希望文件存儲在服務器上,可以輸出基地64圖像像

<?php echo '<img src="data:image/jpg;base64,' . base64_encode($im) . '" />';?> 

(使用前清晰/毀滅),但即有問題同巴新爲base64所以你可能要輸出的base64爲JPEG

,你可以在這裏看到一個例子,我做了一個前僱主的銷售區域地圖:

開始:https://upload.wikimedia.org/wikipedia/commons/1/1a/Blank_US_Map_(states_only).svg

完成:enter image description here

編輯

自寫上面,我拿出2種改進的技術:

1),而不是一個正則表達式循環改變狀態的填充,使用CSS製作樣式規則,如

<style type="text/css"> 
#CA,#FL,HI{ 
    fill:blue; 
} 
#Al, #NY, #NM{ 
    fill:#cc6699; 
} 
/*etc..*/ 
</style> 

然後您可以將單個文本替換爲injec在繼續進行imagick jpeg/png創作之前,請將您的css規則導入到svg中。如果顏色不變,請檢查以確保您的路徑標記中沒有任何內聯填充樣式來覆蓋css。 2)如果你不必實際創建一個jpeg/png圖像文件(並且不需要支持過時的瀏覽器),你可以直接用jQuery來操縱svg。您無法訪問使用IMG或對象標籤嵌入SVG時,SVG的路徑,所以你必須直接包括SVG XML在網頁的HTML這樣的:

<div> 
<?php echo file_get_contents('/path/to/blank/us-map.svg');?> 
</div> 

然後改變顏色是一樣簡單:

<script type="text/javascript" src="/path/to/jquery.js"></script> 
<script type="text/javascript"> 
    $('#CA').css('fill', 'blue'); 
    $('#NY').css('fill', '#ff0000'); 
</script> 
+1

感謝您提供有關如何做到這一點的非常精確和有用的教程。我一定會使用您的解決方案作爲備份,但我急於嘗試在所有主流瀏覽器中獲得svg兼容性。 – 2011-01-26 20:29:51

+1

SVG在ie8或更低版本中不受支持,無需用戶安裝SVG瀏覽器插件 - 從SVG Wikipedia頁面:「所有主流的現代Web瀏覽器,都直接支持並渲染SVG標記,但Microsoft Internet Explorer(IE) [3] Internet Explorer 9測試版支持基本的SVG功能集。[4]目前,支持在Android下運行的瀏覽器也受到限制。「 – WebChemist 2011-01-26 20:32:05

+1

是的,但svgweb似乎用一點點js和flash來消除所有的不兼容性。這是我一起去的解決方案。 – 2011-01-26 20:58:53

2

我不知道獨立的PHP/Apache解決方案,因爲這需要一個可以讀取和呈現SVG圖像的PHP庫。我不確定這樣的圖書館是否存在 - 我不知道。

ImageMagick能夠通過命令行或PHP綁定IMagick柵格化SVG文件,但似乎具有許多怪癖和外部依賴性,如圖所示。在this forum thread。我認爲這仍然是最有希望的方式,如果我是你,這是我首先考慮的事情。

+0

+1這將是最簡單和最好的答案。 – 2014-09-23 08:43:21

11

你提到你這樣做是因爲IE不支持SVG。

好消息是,IE 支持矢量圖形。好的,所以它的形式是一種叫做VML的語言,它只支持IE,而不是SVG,但它在那裏,你可以使用它。

谷歌地圖等,將檢測瀏覽器的功能,以確定是否提供SVG或VML。

然後是Raphael library,這是一個基於Javascript的browswer圖形庫,它支持SVG或VML,這又取決於瀏覽器。

另一個可能有助於:SVGWeb

所有這些都意味着您可以支持您的IE用戶而不必訴諸位圖圖形。

參見上面這個問題的答案,例如:XSL Transform SVG to VML

+0

+1提拉比爾,這絕對是一個很好的解決方案,值得研究其跨瀏覽器矢量圖形的優秀實施。 – dmp 2011-01-26 20:49:26

5

這很簡單,在過去的幾周裏一直在做這方面的工作。您需要Batik SVG Toolkit。下載和將文件放在與要轉換爲JPEG的SVG相同的目錄中,也請確保先將其解壓縮。

打開端子,並運行此命令:

java -jar batik-rasterizer.jar -m image/jpeg -q 0.8 NAME_OF_SVG_FILE.svg 

應該輸出的SVG文件的JPEG。真的很容易。 你甚至可以只將它放在一個循環,並轉換SVGs的負荷,

import os 

svgs = ('test1.svg', 'test2.svg', 'etc.svg') 
for svg in svgs: 
    os.system('java -jar batik-rasterizer.jar -m image/jpeg -q 0.8 '+str(svg)+'.svg') 
6

當轉換SVG透明PNG,不要忘記把此之前$ imagick-> readImageBlob():

$imagick->setBackgroundColor(new ImagickPixel('transparent')); 
0
$command = 'convert -density 300 '; 
         if(Input::Post('height')!='' && Input::Post('width')!=''){ 
          $command.='-resize '.Input::Post('width').'x'.Input::Post('height').' '; 
         } 
         $command.=$svg.' '.$source; 
         exec($command); 
         @unlink($svg); 

或使用:potrace 演示:Tool4dev.com