我正在开发一个网络项目,该项目涉及根据一组数据为不同州着色的美国动态生成地图。
这个 SVG 文件给了我一张很好的美国空白地图,并且很容易改变每个州的颜色。困难在于 IE 浏览器不支持 SVG,所以为了让我使用 svg 提供的便捷语法,我需要将其转换为 JPG。
理想情况下,我只想使用 GD2 库来执行此操作,但也可以使用 ImageMagick。我完全不知道如何做到这一点。
将考虑任何允许我动态更改美国地图上各州颜色的解决方案。关键是它很容易动态更改颜色并且它是跨浏览器的。请仅使用 PHP/Apache 解决方案。
你问这个很有趣,我最近刚刚为我的工作网站做了这个,我想我应该写一个教程......这是使用 ImageMagick 的 PHP/Imagick 的方法:
$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 和颜色值的存储方式。如果您不想在服务器上存储文件,则可以将图像输出为 base 64,如
<?php echo '<img src="data:image/jpg;base64,' . base64_encode($im) . '" />';?>
(在你使用 clear/destroy 之前)但是 ie 有问题将 PNG 作为 base64,所以你可能不得不将 base64 输出为 jpeg
你可以在这里看到我为前雇主的销售区域地图做的一个例子:
开始:https://upload.wikimedia.org/wikipedia/commons/1/1a/Blank_US_Map_(states_only).svg
https://upload.wikimedia.org/wikipedia/commons/1/1a/Blank_US_Map_(states_only).svg
https://i.stack.imgur.com/pRHSD.png
编辑
自从写了上面的内容以来,我提出了 2 个改进的技术:
1)而不是正则表达式循环来更改状态的填充,使用 CSS 来制作样式规则,如
<style type="text/css">
#CA,#FL,HI{
fill:blue;
}
#Al, #NY, #NM{
fill:#cc6699;
}
/*etc..*/
</style>
然后您可以进行单个文本替换以将您的 css 规则注入到 svg 中,然后再继续进行 imagick jpeg/png 创建。如果颜色没有改变,请检查以确保您的路径标签中没有任何内联填充样式覆盖 css。
2) 如果您不必实际创建 jpeg/png 图像文件(并且不需要支持过时的浏览器),您可以直接使用 jQuery 操作 svg。使用 img 或 object 标签嵌入 svg 时,您无法访问 svg 路径,因此您必须直接在网页 html 中包含 svg xml,例如:
<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>
将 SVG 转换为透明 PNG 时,不要忘记将其放在 $imagick->readImageBlob()
之前:
$imagick->setBackgroundColor(new ImagickPixel('transparent'));
你提到你这样做是因为 IE 不支持 SVG。
好消息是 IE 确实支持矢量图形。好的,它的形式是一种称为 VML 的语言,只有 IE 支持,而不是 SVG,但它就在那里,你可以使用它。
谷歌地图等将检测浏览器功能以确定是否提供 SVG 或 VML。
然后是 Raphael library,它是一个基于 Javascript 浏览器的图形库,它支持 SVG 或 VML,同样取决于浏览器。
另一个可能有帮助的:SVGWeb。
所有这一切意味着您可以支持您的 IE 用户,而无需求助于位图图形。
另请参阅此问题的最佳答案,例如:XSL Transform SVG to VML
这很容易,过去几周一直在做这方面的工作。
您需要 Batik SVG Toolkit。下载并将文件放在与要转换为 JPEG 的 SVG 相同的目录中,还要确保先解压缩它。
打开终端,然后运行以下命令:
java -jar batik-rasterizer.jar -m image/jpeg -q 0.8 NAME_OF_SVG_FILE.svg
那应该输出 SVG 文件的 JPEG。真的很容易。您甚至可以将它放在一个循环中并转换大量 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')
这是一种使用标准 php GD 工具将 svg 图片转换为 gif 的方法
1)您将图像放入浏览器中的画布元素中:
<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(){
//get the image info as base64 text string
var dataURL = canvas.toDataURL();
//Post the image (dataURL) to the server using jQuery post method
$.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 而不是图像 gif):
//receive the posted data in php
$pic=$_POST['image'];
$Key=$_POST['TheKey'];
$height=$_POST['h'];
$width=$_POST['w'];
$dir='../gif/'
$gifName=$dir.$Key.'.gif';
$pngName=$dir.$Key.'.png';
//split the generated base64 string before the comma. to remove the 'data:image/png;base64, header created by and get the image data
$data = explode(',', $pic);
$base64img = base64_decode($data[1]);
$dimg=imagecreatefromstring($base64img);
//in order to avoid copying a black figure into a (default) black background you must create a white background
$im_out = ImageCreateTrueColor($width,$height);
$bgfill = imagecolorallocate( $im_out, 255, 255, 255 );
imagefill( $im_out, 0,0, $bgfill );
//Copy the uploaded picture in on the white background
ImageCopyResampled($im_out, $dimg ,0, 0, 0, 0, $width, $height,$width, $height);
//Make the gif and png file
imagegif($im_out, $gifName);
imagepng($im_out, $pngName);
我不知道独立的 PHP / Apache 解决方案,因为这需要一个可以读取和呈现 SVG 图像的 PHP 库。我不确定这样的图书馆是否存在——我不知道。
ImageMagick 能够通过命令行或 PHP 绑定 IMagick 光栅化 SVG 文件,但似乎有许多怪癖和外部依赖项,如 this forum thread 所示。我认为这仍然是最有希望的方法,如果我是你,这是我首先要研究的。
$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
不定期副业成功案例分享
$dom = new DOMDocument(); $dom->loadXML( $svg ); $dom->getElementsByTagName('image')->item(0)->setAttribute('id', $state); $svg = $dom->saveXML();