代码背景:公司要做一个广告banner生成的工具,提前做好很多svg模板,上传上去,然后对svg模板中图片和文字编辑,导出最终的广告图片。提升设计运营做图效率
解决方案:
方案一、上传的svg模板解析成带有图层元素的json(图片、文字、位置、大小等等参数),前后端共同维护这个json,前端将做了更改的json发给后端,后端解析加入队列去合成图片(时间短未使用)
方案二、后端负责发布svg模板,前端负责修改svg图片元素,生成新的png图片
一、对上传的svg文件解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
/** * 上传缩略图及svg到oss * @param Request $request * @return bool|string */ public function upload(Request $request) { $file = $request->file('files')[0]; if($request->hasFile('files') && $file->isValid()){ //svg文件解析 $extensionName = $file->getClientOriginalExtension(); if($extensionName=="svg"){ $this->svgAnalysis($file); } //上传缩略图或svg文件到oss $path = pathinfo($file->getClientOriginalName(), PATHINFO_EXTENSION); $filename = md5(time().$file->getClientOriginalName()).'.'.$path; try{ //将图片上传至OSS $oss_filename = 'bannermaker/'.date('Ymd', time()).$filename; Oss::uploadImg2Oss($file->getPathname(), $oss_filename); $oss_path = config('cdn.url').$oss_filename; return response()->json(['status'=>true, 'url'=>$oss_path]); }catch (FileException $e){ return response()->json(['status'=>false]); } }else{ return response()->json(['status'=>false]); } } |
二、svg解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
/** * svg文件解析 * @param $file */ public function svgAnalysis($file) { if(empty($file)){ return false; } //获取svg源文件内容 $svgXML = file_get_contents($file); //过滤掉svg、title、desc、defs标签 // $svgXML = preg_replace("/<(svg.*?)>/si","",$svgXML); // $svgXML = preg_replace("/<(!--.*?--)>/si","",$svgXML); // $svgXML = preg_replace("/<(title.*?)>(.*?)<(\/title.*?)>/si","",$svgXML); // $svgXML = preg_replace("/<(desc.*?)>(.*?)<(\/desc.*?)>/si","",$svgXML); // $svgXML = preg_replace("/<(defs.*?)>(.*?)<(\/defs.*?)>/si","",$svgXML); // $svgXML = preg_replace("/<(\/svg.*?)>$/","",$svgXML); // $xml = simplexml_load_string($svgXML); // $xml->registerXPathNamespace('svg', 'http://www.w3.org/2000/svg'); // echo $xml->xpath('/svg:svg/svg:g')[0]->asXML('php://output'); // exit; $svg = simplexml_load_string($svgXML); $svg->registerXPathNamespace('svg', 'http://www.w3.org/2000/svg'); $svg->registerXPathNamespace('xlink', 'http://www.w3.org/1999/xlink'); //解析svg里base64字符串图片 $images = $svg->xpath('//svg:image/@xlink:href'); //解析svg里g画布里内容 $result = $svg->xpath('//svg:svg/svg:g'); //解析svg总体的属性 $result = $svg->xpath('/svg:svg/attribute::*'); //处理图片 // $svgUrl = []; // foreach($images as $k=>$v){ // $imageBase64 = $this->xml_attribute($v, 'href'); // //base64字符串上传到oss,返回图片url // $url = $this->base64UploadOss($imageBase64); // dd($url); // $svgUrl[]['url'] = $url; // } // dd($svgUrl); $svg_size = []; foreach($result as $k=>$v){ if(!empty($this->xml_attribute($v, 'width'))){ $svg_size['width'] = (string)$v['width']; }; if(!empty($this->xml_attribute($v, 'height'))){ $svg_size['height'] = (string)$v['height']; }; if(!empty($this->xml_attribute($v, 'viewBox'))){ $svg_size['viewBox'] = (string)$v['viewBox']; }; } //需要返回的数据 $data = [ 'svg_size' => $svg_size, 'svg_source' => $svgXML ]; return $data; } |
三、处理svg的xml转成的数组中@attributes
1 2 3 4 5 6 7 8 9 10 |
/** * 处理svg的xml转成的数组中@attributes * @param $object * @param $attribute * @return string */ public function xml_attribute($object, $attribute) { return isset($object[$attribute]) ? (string) $object[$attribute] : ''; } |
四、base64字符串图片上传oss
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
/** * base64字符串图片上传到oss * @param $imageBase64 * @return bool * @throws \ImagickException */ public function base64UploadOss($imageBase64) { if(empty($imageBase64)){ return false; } if (preg_match('/^(data:\s*image\/(\w+);base64,)/',$imageBase64,$res)) { $imageBlob = base64_decode(str_replace($res[1],'', $imageBase64)); $imagick = new \Imagick(); $imagick->readImageBlob($imageBlob); if(!empty($imageBlob)){ //上传oss //$path = pathinfo($imageBlob->getClientOriginalName(), PATHINFO_EXTENSION); //$filename = md5(time().$imageBlob->getClientOriginalName()).'.'.$path; try{ //将图片上传至OSS //$oss_filename = 'bannermaker/'.date('Ymd', time()).$filename; $oss_filename = 'bannermaker/'.date('Ymd', time()).'abc'; Oss::uploadImg2Oss($imageBlob->getPathname(), $oss_filename); $oss_path = config('cdn.url').$oss_filename; return response()->json(['status'=>true, 'url'=>$oss_path]); }catch (FileException $e){ return response()->json(['status'=>false]); } } } } |
更多待涛哥实践总结.分享…
转载请注明:PHP笔记 » SVG文件解析通过PHP转成JSON