Я работаю над веб-проектом, который включает в себя динамически сгенерированную карту США, окрашивающих разные состояния на основе набора данных.
Этот файл SVG дает мне хорошую пустую карту США и очень легко изменить цвет каждого состояния. Трудность заключается в том, что браузеры IE не поддерживают SVG, поэтому для того, чтобы я мог использовать удобный синтаксис, предлагаемый svg, мне нужно будет преобразовать его в JPG.
В идеале я бы хотел сделать это только с библиотекой GD2, но также мог бы использовать ImageMagick. Я не знаю, как это сделать.
Будет рассмотрено любое решение, которое позволит мне динамически изменять цвета состояний на карте США. Ключ в том, что легко менять цвета на лету и что это кросс-браузер. Только PHP / Apache, пожалуйста.
Это смешно, что вы спросили об этом, я просто сделал это недавно на сайте моей работы, и я думал, что должен написать учебник … Вот как это сделать с 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();
замена цвета регулярных выражений шагов может варьироваться в зависимости от пути xvg path и как вы сохраняете значения идентификатора и цвета. Если вы не хотите хранить файл на сервере, вы можете выводить изображение в качестве базы 64, например
<?php echo '<img src="data:image/jpg;base64,' . base64_encode($im) . '" />';?>
(прежде чем вы будете использовать clear / destroy), но имеет проблемы с PNG как base64, поэтому вам, вероятно, придется выводить base64 как jpeg
вы можете увидеть пример здесь, который я сделал для карты продаж на бывшем работодателе:
Начало: https://upload.wikimedia.org/wikipedia/commons/1/1a/Blank_US_Map_(states_only).svg
Конец:
редактировать
Начиная с написания выше, я придумал 2 улучшенных метода:
1) вместо цикла регулярного выражения, чтобы изменить состояние заполнения, используйте CSS для создания правил стиля, таких как
<style type="text/css"> #CA,#FL,HI{ fill:blue; } #Al, #NY, #NM{ fill:#cc6699; } /*etc..*/ </style>
и затем вы можете сделать один текст, чтобы вставлять ваши правила css в svg, прежде чем приступать к созданию jpeg / png imagick. Если цвета не меняются, убедитесь, что у вас нет встроенных стилей заливки в тегах пути, переопределяющих css.
2) Если вам не нужно создавать файл jpeg / png (и не нужно поддерживать устаревшие браузеры), вы можете напрямую управлять svg с помощью jQuery. Вы не можете получить доступ к SVG-тропам при встраивании svg с использованием тегов img или object, поэтому вам нужно будет напрямую включить 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>
Еще одним очень быстрым и точным вариантом является безголовый браузер PhantomJS (webkit)
Вы упоминаете, что вы это делаете, потому что IE не поддерживает SVG.
Хорошей новостью является то, что IE поддерживает векторную графику. Хорошо, так что это в виде языка VML, который поддерживает только IE, а не SVG, но он есть, и вы можете его использовать.
Карты Google, среди прочего, обнаружат возможности браузера, чтобы определить, следует ли обслуживать SVG или VML.
Тогда есть библиотека Raphael , которая является графической библиотекой, основанной на Javascript browswer, которая поддерживает SVG или VML, опять же в зависимости от браузера.
Другая, которая может помочь: SVGWeb .
Все это означает, что вы можете поддерживать своих пользователей IE, не прибегая к растровой графике.
См. Также главный ответ на этот вопрос, например: XSL Transform SVG to VML
Когда вы конвертируете SVG в прозрачный PNG, не забудьте поставить это перед $ imagick-> readImageBlob ():
$imagick->setBackgroundColor(new ImagickPixel('transparent'));
Это легко, делали работу над этим в течение последних нескольких недель.
Вам нужен набор инструментов Batik SVG . Загрузите и поместите файлы в тот же каталог, что и SVG, который хотите преобразовать в JPEG , также убедитесь, что вы разархивируете его в первую очередь.
Откройте терминал и запустите эту команду:
java -jar batik-rasterizer.jar -m image/jpeg -q 0.8 NAME_OF_SVG_FILE.svg
Это должно выводить JPEG файла SVG. Действительно легко. Вы даже можете просто поместить его в цикл и преобразовать нагрузки SVG,
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')
вы можете использовать библиотеку canvg js для преобразования SVG в PNG, более подробную информацию здесь http://paksula.users.cs.helsinki.fi/svg_open_2010/demo.xhtml совместим со всеми основными браузерами!
Я использую его в своем проекте и фактически конвертирую SVG в PNG (с помощью PHP, чтобы сохранить файл, конечно)
Я не знаю отдельного решения PHP / Apache, поскольку для этого потребуется библиотека PHP, которая может читать и отображать SVG-изображения. Я не уверен, что такая библиотека существует – я не знаю.
ImageMagick способен растеризовать SVG-файлы либо через командную строку, либо через привязку PHP, IMagick , но, похоже, имеет ряд причуд и внешних зависимостей, как показано, например, в этом разделе . Я думаю, что это все же самый многообещающий путь, это первое, на что я бы посмотрел, если бы я был вами.
$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 demo: Tool4dev.com
Вы можете использовать библиотеку Raphaël-JavaScript и легко ее достичь. Он будет работать и в IE.