Я работаю над веб-проектом, который включает в себя динамически создаваемую карту США, окрашивающую различные штаты на основе набора данных.
Этот SVG-файл дает мне хорошую пустую карту США, и в ней очень легко изменить цвет каждого штата. Сложность в том, что браузер IE не поддерживает SVG, поэтому для того, чтобы использовать удобный синтаксис, который предлагает SVG, мне нужно преобразовать его в JPG. В идеале я хотел бы сделать это с помощью библиотеки GD2, но можно использовать и ImageMagick. Я совершенно не знаю, как это сделать. Любое решение, которое позволит мне динамически изменять цвета штатов на карте США, будет рассмотрено. Главное, чтобы было легко менять цвета на лету и чтобы это было кроссбраузерно. Только PHP/Apache решения, пожалуйста.
Ответ 1
Интересно, что вы спросили об этом, я недавно сделал это для сайта моей работы и подумал, что должен написать учебник... Вот как это сделать с помощью PHP/Imagick, который использует ImageMagick:
$usmap = '/path/to/blank/us-map.svg';
$im = new Imagick();
$svg = file_get_contents($usmap);
/*зацикливание для окрашивания каждого состояния по мере необходимости*/
$idColorArray = array(
"AL" => "339966"
,"AK" => "0099FF"
...
,"WI" => "FF4B00"
,"WY" => "A3609B"
);
foreach($idColorArray as $state => $color){
//где $color является шестнадцатеричным значением RRGGBB
$svg = preg_replace(
'/id="'.$state.'" style="fill:#([0-9a-f]{6})/'
, 'id="'.$state.'" style="fill:#'.$color
, $svg
);
}
$im->readImageBlob($svg);
/*параметры png*/
$im->setImageFormat("png24");
$im->resizeImage(720, 445, imagick::FILTER_LANCZOS, 1); /*Опционально, если вам нужно изменить размер*/
/*jpeg*/
$im->setImageFormat("jpeg");
$im->adaptiveResizeImage(720, 445); /*Опционально, если вам нужно изменить размер*/
$im->writeImage('/path/to/colored/us-map.png');/*(or .jpg)*/
$im->clear();
$im->destroy();
Шаги regex по замене цвета могут отличаться в зависимости от пути svg xml и того, как хранятся значения id и цвета. Если вы не хотите хранить файл на сервере, вы можете вывести изображение в формате base64, например, так:
<?php echo '<img src="data:image/jpg;base64,' . base64_encode($im) . '" />';?>
Прежде чем использовать clear/destroy, необходимо знать, что у ie есть проблемы с PNG в формате base64, поэтому вам, вероятно, придется выводить base64 в формате jpeg.
Дополнение:
1) Вместо цикла regex для изменения состояния заливки используйте CSS для создания правил стиля, таких как:
<style type="text/css">
#CA,#FL,HI{
fill:blue;
}
#Al, #NY, #NM{
fill:#cc6699;
}
/*etc..*/
</style>
и затем вы можете сделать единственную замену текста, чтобы внедрить правила css в svg, прежде чем приступить к созданию imagick jpeg/png. Если цвета не меняются, проверьте, нет ли у вас в тегах path каких-либо встроенных стилей заливки, переопределяющих 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>
Ответ 2
Вы упомянули, что делаете это потому, что IE не поддерживает SVG. Хорошая новость заключается в том, что IE поддерживает векторную графику. Правда, в виде языка VML, который поддерживает только IE, а не SVG, но он есть, и вы можете его использовать.
Карты Google среди прочих определяют возможности браузера, чтобы определить, обслуживать ли SVG или VML. Есть еще библиотека Raphael, которая представляет собой графическую библиотеку на основе Javascript, поддерживающую SVG или VML, опять же, в зависимости от браузера. Еще одна библиотека, которая может помочь, — SVGWeb.
Все это означает, что вы можете поддерживать пользователей IE, не прибегая к растровой графике.
Ответ 3
Вот метод преобразования svg-изображения в gif с помощью стандартных средств php GD.
Вы помещаете изображение в элемент canvas в браузере:
<canvas id=myCanvas></canvas>
<script>
var Key='picturename'
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
base_image = new Image();
base_image.src = myimage.svg;
base_image.onload = function(){
//получение информации об изображении в виде текстовой строки base64
var dataURL = canvas.toDataURL();
//Поместите изображение (dataURL) на сервер, используя метод jQuery post
$.post('ProcessPicture.php',{'TheKey':Key,'image': dataURL ,'h': canvas.height,'w':canvas.width,"stemme":stemme } ,function(data,status){ alert(data+' '+status) });
}
</script>
А затем конвертируйте его на сервере (ProcessPicture.php) из (по умолчанию) png в gif и сохраните его (вы могли бы сохранить его так же, как png, а затем использовать imagepng вместо imagegif):
//получаем опубликованные данные в php
$pic=$_POST['image'];
$Key=$_POST['TheKey'];
$height=$_POST['h'];
$width=$_POST['w'];
$dir='../gif/'
$gifName=$dir.$Key.'.gif';
$pngName=$dir.$Key.'.png';
//разделяем сгенерированную строку base64 перед запятой, чтобы удалить созданный заголовок 'data:image/png;base64, и получаем данные изображения
$data = explode(',', $pic);
$base64img = base64_decode($data[1]);
$dimg=imagecreatefromstring($base64img);
//чтобы избежать копирования черной фигуры на черный фон (по умолчанию), необходимо создать белый фон
$im_out = ImageCreateTrueColor($width,$height);
$bgfill = imagecolorallocate( $im_out, 255, 255, 255 );
imagefill( $im_out, 0,0, $bgfill );
//Копируем загруженное изображение на белый фон
ImageCopyResampled($im_out, $dimg ,0, 0, 0, 0, $width, $height,$width, $height);
//формируем файл gif и png
imagegif($im_out, $gifName);
imagepng($im_out, $pngName);
Ответ 4
Это очень просто, я работал над этим в течение последних нескольких недель.
Вам понадобится Batik SVG Toolkit. Скачайте и поместите файлы в ту же директорию, что и 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')
Web