一行代碼解決svg保存成png文件

先說(shuō)下我的功能需求充蓝,大家看看和大家的是否相同,能否借鑒。
下面是我的整個(gè)的思路過(guò)程谓苟,如果想直接找解決方案官脓,直接看方案三。

功能需求:

添加一個(gè)按鈕涝焙,點(diǎn)擊按鈕時(shí)卑笨,將拓?fù)鋱D保存為圖片文件并導(dǎo)出。

就是將在svg畫(huà)布上畫(huà)的圖仑撞,保存成圖片并導(dǎo)出赤兴。

問(wèn)題描述:

在svg畫(huà)布上畫(huà)的拓?fù)鋱D,每個(gè)節(jié)點(diǎn)使用的是圖片隧哮,將整個(gè)svg導(dǎo)出時(shí)桶良,導(dǎo)出的圖片文件上面不顯示節(jié)點(diǎn)圖片。如圖1-1近迁、1-2:

圖1-1 svg畫(huà)布畫(huà)好的拓?fù)鋱D

圖1-2 導(dǎo)出的圖片

我svg中繪制過(guò)程中艺普,引入圖片的代碼如圖1-3:


圖1-3 svg節(jié)點(diǎn)引入圖片

圖片放在static下面,如圖1-4:

圖1-4 引入的圖片存放位置

方案思路:

方案一:無(wú)須引入插件

首先是制造一個(gè)button鉴竭,用的element的框架歧譬。
<el-button size = 'mini' type="primary" @click="saveSvgToPng" v-loading.fullscreen.lock="fullscreenLoading">導(dǎo)出圖片</el-button>

然后寫(xiě)這個(gè)點(diǎn)擊事件響應(yīng)函數(shù):

saveSvgToPng: function () {
        //采用直接轉(zhuǎn)成canvas的方式
        let width = 1000;
        let height = 666;
        var serializer = new XMLSerializer();
        var source = '<?xml version="1.0" standalone="no"?>\r\n'+serializer.serializeToString(svg.node());
        var image = new Image();
        image.src = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(source);
        var canvas = document.createElement("canvas");
        canvas.width = width;
        canvas.height = height;
        var context = canvas.getContext("2d")
        image.onload = function(){
          context.drawImage(image, 0, 0);

          var a = document.createElement("a");
          a.download = "aaaa.png";
          a.href = canvas.toDataURL('image/png');
          a.click();
        }
      },

導(dǎo)出內(nèi)容如圖1-2,未顯示網(wǎng)元節(jié)點(diǎn)圖片搏存。未搞清楚原因瑰步,查了一些資料,好像是因?yàn)閏anvas畫(huà)布被污染了璧眠,所以無(wú)法使用toDataURL這種方法了缩焦。而canvas畫(huà)布被污染的原因好像是因?yàn)閟vg中網(wǎng)元節(jié)點(diǎn)圖片跨域了,我現(xiàn)在有這個(gè)疑問(wèn):在static下面的圖片责静,存在跨域問(wèn)題嗎袁滥,因?yàn)槲覍?dǎo)出的時(shí)候,并沒(méi)有報(bào)出跨域的錯(cuò)誤灾螃。

然后我又嘗試了方案二:

方案二:使用插件html2canvas

按照官網(wǎng)步驟题翻,引入html2canvas插件,修改html結(jié)構(gòu)腰鬼,將svg放入一個(gè)div內(nèi)嵌赠,并給div一個(gè)ref標(biāo)簽,便于引用熄赡,如圖1-5.

圖1-5 html結(jié)構(gòu)

然后修改點(diǎn)擊響應(yīng)函數(shù)姜挺,代碼如下:

函數(shù)1:

dataURLToBlob: function (dataurl) {
  var arr = dataurl.split(',');
  var mime = arr[0].match(/:(.*?);/)[1];
  var bstr = atob(arr[1]);
  var n = bstr.length;
  var u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new Blob([u8arr], {type: mime})
},

單擊響應(yīng)函數(shù)2:

catchSvgToPng: function () {
        const _this = this
        let a = document.createElement('a');
        setTimeout(() => {
          // 此處用于解決截圖不清晰問(wèn)題,將生成的canvas放大彼硫,然后再填充到原有的容器中就會(huì)清晰
          const width = 1000;
          const height = 400;
          const canvas2 = document.createElement('canvas');
          const scale = 2;
          canvas2.width = width * scale;
          canvas2.height = height * scale;
          const context1 = canvas2.getContext('2d')
          if(context1) {
            context1.scale(scale, scale);
          }
          const opts = {
            scale,
            canvas: canvas2,
            // logging: true, //日志開(kāi)關(guān)炊豪,便于查看html2canvas的內(nèi)部執(zhí)行流程
            width,
            height,
            // 【重要】開(kāi)啟跨域配置
            useCORS: true
          };
          html2canvas(_this.$refs.imageWrapper,opts).then((canvas) => {
            const context = canvas2.getContext('2d');
            if(context) {
              context.scale(2,2);
              context.mozImageSmoothingEnabled = false;
              context.webkitImageSmoothingEnabled = false;
              context.imageSmoothingEnabled = false;
            }
            // canvas轉(zhuǎn)換成url凌箕,然后利用a標(biāo)簽的download屬性,直接下載词渤,繞過(guò)上傳服務(wù)器再下載
//            _this.screenUrl = canvas.toDataURL()

//            var imgBlob = canvas.toDataURL('image/jpeg', 1.0); //將圖片轉(zhuǎn)為base64
//            imgBlob = imgBlob.toString().substring(imgBlob.indexOf(",") + 1);//截取base64以便上傳
            let blob = _this.dataURLToBlob(canvas.toDataURL('image/jpeg', 1.0));
            a.setAttribute("href", URL.createObjectURL(blob));
            a.setAttribute("download", "xxxxxx.png");
            document.body.appendChild(a);
            a.click();
            URL.revokeObjectURL(blob);
            document.body.removeChild(a);
          });
        },1000)
      },

導(dǎo)出的圖片如圖1-6所示:


圖1-6 html2canvas導(dǎo)出的圖片

導(dǎo)出的圖片依然無(wú)網(wǎng)元節(jié)點(diǎn)圖片陌知,已經(jīng)按照網(wǎng)上查到的資料,對(duì)污染的canvas進(jìn)行處理掖肋,不讓canvas被污染,依然沒(méi)有效果∩筒危現(xiàn)在不清楚是什么原因?qū)е碌膶?dǎo)出的圖片無(wú)節(jié)點(diǎn)圖片志笼,因此也不知如何解決。
這個(gè)問(wèn)題到這里已經(jīng)困擾了我將近一周之久把篓,查了好多資料纫溃,試了又試,像一支無(wú)頭蒼蠅一樣撞來(lái)撞去韧掩,毫無(wú)頭緒紊浩。因?yàn)橹翱茖W(xué)上網(wǎng)的軟件到期了,一直沒(méi)有續(xù)費(fèi)疗锐,所以之前的查資料都是在百度上進(jìn)行坊谁。
在這里!;口芍!強(qiáng)烈建議大家科學(xué)上網(wǎng)!9途怼鬓椭!當(dāng)我把軟件續(xù)費(fèi)以后,用谷歌重新試著查詢(xún)之前的資料关划,發(fā)現(xiàn)之前嘗試的一種插件小染,但苦于沒(méi)有找到例子而不知道怎么使用,就一直未動(dòng)贮折。當(dāng)我谷歌出使用流程以后裤翩,我抱著試一試的心態(tài)重新試了一下,這就是我的方案三脱货。

方案二:使用插件saveSvgAsPng
廢話不多說(shuō)岛都,上個(gè)官網(wǎng)網(wǎng)址,寫(xiě)的很清楚振峻。
github:https://github.com/exupero/saveSvgAsPng
翻譯版本:https://www.helplib.com/GitHub/article_110596
按照這上面的提示臼疫,一步步操作。
1.用npm把插件裝上
npm install save-svg-as-png
2.在需要使用的vue文件中把js文件import進(jìn)來(lái)
import saveSvg from 'save-svg-as-png';
3.對(duì)之前的按鈕點(diǎn)擊響應(yīng)函數(shù)進(jìn)行編寫(xiě)

saveSvgToPng: function () {
        //調(diào)研使用saveSvgAsPng 的方式
        saveSvg.saveSvgAsPng(document.getElementById("topologySvg"), "diagram.png",{height:800});
      },

官網(wǎng)上面給的例子直接使用的
saveSvgAsPng(document.getElementById("topologySvg"), "diagram.png")
但是這樣的話扣孟,在我的vue框架下烫堤,是顯示這個(gè)方法無(wú)效,所以需要使用前面import的文件名來(lái)進(jìn)行調(diào)用。
我們調(diào)轉(zhuǎn)這個(gè)函數(shù)鸽斟,看下怎么回事桅狠。

out$.saveSvgAsPng = (el, name, options) => {
    requireDomNode(el);
    out$.svgAsPngUri(el, options || {}, uri => out$.download(name, uri));
  };

這個(gè)是引入插件中該方法的位置,很顯然該方法需要三個(gè)參數(shù)翁脆,操作的元素尚镰、保存的文件名稱(chēng)以及一些參數(shù)。至于具體可以設(shè)置哪些參數(shù)來(lái)控制導(dǎo)出的png圖片立倍,官網(wǎng)給了一個(gè)清單灭红,寫(xiě)的很清楚。比如我們想設(shè)置導(dǎo)出圖片的寬度和高度為我們想要的值口注,就可以這么寫(xiě):

saveSvg.saveSvgAsPng(document.getElementById("topologySvg"), "diagram.png",{height:800,width:1400});

至此变擒,該功能就實(shí)現(xiàn)了,一行代碼可以搞定的功能琢磨了一周多寝志,以后一定要科學(xué)上網(wǎng)=堪摺!材部!百度真得往后稍稍毫缆。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市败富,隨后出現(xiàn)的幾起案子悔醋,更是在濱河造成了極大的恐慌,老刑警劉巖兽叮,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件芬骄,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡鹦聪,警方通過(guò)查閱死者的電腦和手機(jī)账阻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)泽本,“玉大人淘太,你說(shuō)我怎么就攤上這事」胬觯” “怎么了蒲牧?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)赌莺。 經(jīng)常有香客問(wèn)我冰抢,道長(zhǎng),這世上最難降的妖魔是什么艘狭? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任挎扰,我火速辦了婚禮翠订,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘遵倦。我一直安慰自己尽超,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布梧躺。 她就那樣靜靜地躺著似谁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪掠哥。 梳的紋絲不亂的頭發(fā)上棘脐,一...
    開(kāi)封第一講書(shū)人閱讀 49,784評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音龙致,去河邊找鬼。 笑死顷链,一個(gè)胖子當(dāng)著我的面吹牛目代,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播嗤练,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼榛了,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了煞抬?” 一聲冷哼從身側(cè)響起霜大,我...
    開(kāi)封第一講書(shū)人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎革答,沒(méi)想到半個(gè)月后战坤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡残拐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年途茫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溪食。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡囊卜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出错沃,到底是詐尸還是另有隱情栅组,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布枢析,位于F島的核電站玉掸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏登疗。R本人自食惡果不足惜排截,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一嫌蚤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧断傲,春花似錦脱吱、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至垦垂,卻和暖如春宦搬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背劫拗。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工间校, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人页慷。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓憔足,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親酒繁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子滓彰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容