我們去年就在emojiall.com這個網站中大量使用svg格式的矢量圖,包括各emoji圖片廠商和平台提供的svg矢量圖以及我們自己的排行榜、情緒分析等原創生成的svg圖,有一些svg是直接把svg代碼放置在頁面的html中,最近把一部分svg代碼從頁面html中拿出來單獨作為獨立文件,用img标簽放在原來頁面的html中,這樣方便Google的收錄,但百度等搜索引擎不能識别、解析和收錄svg圖片,于是我們也把svg圖片轉為png保存。
這個svg轉png的功能以前就了解過一些,主要有兩種方式:
- 使用PHP的Imagick插件
- 用JS将svg轉為canvas繪制png
我們使用了第一種方式,下面是代碼:
/** * 函數:svg數據轉png圖片 * @param: svg數據 * @return: png圖片 */ function svg_data_to_png($input) { $im = new Imagick(); $im->readImageBlob($input); $im->setImageFormat("png8"); header("Content-type: image/png"); echo $im->getImageBlob(); $im->clear(); $im->destroy(); }
下面是原始svg和轉為png的對比:
svg圖片:
png圖片:
有一個坑:用上面的PHP方式轉換後尺寸不合适,後來是通過修改原是svg圖數據中的width和height來解決的。如果還有其它修改,也需要在轉換png前進行修改。
另外,确實還有一些svg樣式和特殊的語法在轉換後的png中無法顯示,也需要修改svg源碼或者以後找其它辦法解決。
2022年9月26日補充:上周自己編寫了一個php程序,對apache日志進行統計,将耗時最長的一些訪問列出,以發現性能瓶頸在什麼地方,有針對性解決。該程序在www.emojiall.com網站所在的服務器上運行時,發現有一些svg轉png的頁面訪問耗時長達幾百秒,特别是生成1280x1280、1920x1920這種大尺寸png圖片時更容易卡,今天進一步研究發現耗時幾百秒的都是svg中帶有所謂徑向漸變标簽的,例如:👎🏾 這個Emoji的Google SVG矢量圖的源代碼中包含:
<radialGradient id="e" cx="51.77" cy="27.401" r="87.039" gradientTransform="matrix(-.0021809 -1 -.7873 .001717 73.454 148.32)" gradientUnits="userSpaceOnUse"> <stop stop-color="#A56C43" offset=".6"/> <stop stop-color="#8D5738" offset="1"/> </radialGradient>
這其中的radialGradient就是徑向漸變的标簽,可以讓svg的顔色變化更方便,但正是這個顔色漸變讓Imagick的轉換運算量大增,轉為大尺寸的png圖片需要幾十甚至幾百秒。使用正則表達式把cx / cy / r / gradientTransform / gradientUnits這些内容替換為空後,轉換速度馬上大幅提升,一秒内就可以轉好。顔色信息不丢失,隻是漸變效果丢失,還是可以接受的。👌
评论