前言:这个网站可以生成比较好看的logo,但是logo加了水印还收费(太穷了qaq),所以记了个todo,开发了个chrome扩展让他能自动提取svg保存到本地。
贴一下Chrome官方文档https://developer.chrome.com/docs/extensions/mv3/getstarted/,这里为了简单用的v2,但是v2在23年会下掉,建议用v3。
了解主要文件
manifest.json
这里指定扩展的基本信息,包括名称,描述,图标,允许访问的域名,扩展的UI界面,以及动态注入的脚本。
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
| { "manifest_version": 2, "name": "TanTan", "version": "1.0.0", "description": "Hello, Help you Download svg.", "icons": { "16": "img/icon16.png", "48": "img/icon48.png", "128": "img/icon128.png" }, "browser_action": { "default_icon": "img/icon128.png", "default_popup": "popup.html" }, "permissions": [ "<all_urls>" ], "content_scripts": [ { "matches": [ "<all_urls>" ], "js": [ "content.js" ], "run_at": "document_start" } ] }
|
在manifest.json中引入 popup.html ,这里确定了下图这块区域,但由于浏览器的内容安全策略 ( CSP ),不允许使用内联脚本,因此js的操作要放在单独的文件中。也就是下面的popup.js。

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
| <!DOCTYPE html> <html>
<head> <title>Covid-19 Stats- UK</title> <meta charset="utf-8"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"> <style> .container { width: 450px; height: 500px; display: flex; flex-flow: column; align-items: center; overflow: hidden; }
.imgs { width: 400px; height: 400px; overflow: auto; margin-top: 40px; } li{ margin-top: 10px; padding: 10px; border: 1px solid rgb(179, 179, 179); } .button { position: fixed; left: 50%; transform: translate(-50%); }
ul { list-style: none; } </style> </head>
<body> <div class="container mt-3"> <button type="button" class="btn btn-outline-primary button">TanTan</button> <ul class="imgs"></ul> </div> </body> <script src="popup.js" type="module"></script>
</html>
|
这里会选中当前的页面,然后给你注入的脚本(content.js)发送数据并接受数据执行callback。
1 2 3 4 5
| chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { chrome.tabs.sendMessage(tabs[0].id, index, function (response) { if (callback) callback(response); }); });
|
整体代码:接受content.js返回给的svg使用canvas做中转,将svg+xml在canvas上绘制,调用canvas方法转成base64的png格式,添加click函数用于保存svg / png。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function drawInlineSVG(svgStr) { const svg = document.createElement('div') svg.innerHTML = svgStr var svgData = new XMLSerializer().serializeToString(svg.children[0]); var canvas = document.createElement("canvas"); var ctx = canvas.getContext("2d"); var img = document.createElement("img"); img.setAttribute("src", "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(svgData)))); img.onload = function () { canvas.width = img.width canvas.height = img.height ctx.drawImage(img, 0, 0); const dataURL = canvas.toDataURL("image/png"); console.log(dataURL); }; return img; }
|
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
| function download(filename, text) { var element = document.createElement('a'); element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)); element.setAttribute('download', filename);
element.style.display = 'none'; document.body.appendChild(element);
element.click();
document.body.removeChild(element); }
function drawInlineSVG(svgStr) { const svg = document.createElement('div') svg.innerHTML = svgStr var svgData = new XMLSerializer().serializeToString(svg.children[0]); var canvas = document.createElement("canvas"); var ctx = canvas.getContext("2d"); var img = document.createElement("img"); img.setAttribute("src", "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(svgData)))); img.onload = function () { canvas.width = img.width canvas.height = img.height ctx.drawImage(img, 0, 0); const dataURL = canvas.toDataURL("image/png"); console.log(dataURL); }; return img; } let sum = 10; function sendMessageToContentScript() { const callback = (response) => { const img = drawInlineSVG(response) const li = document.createElement('li') li.appendChild(img) li.addEventListener('click', (e) => { download('download.svg', response) }) document.getElementsByClassName('imgs')[0].appendChild(li) } for (let index = 0; index <= sum; index += 2) { chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { chrome.tabs.sendMessage(tabs[0].id, index, function (response) { if (callback) callback(response); }); }); } sum += 10; } window.onload = () => { const btn = document.getElementsByClassName('button')[0] const ul = document.getElementsByClassName('imgs')[0] btn.addEventListener('click', sendMessageToContentScript) }
|
content.js
因为他可以被注入到页面中,所以content.js可以获取到当前页面的dom,因此通过选择器选中svg传给popup.js。
1 2 3 4
| chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { const svgs = document.querySelectorAll('.svg-card > svg') sendResponse(svgs[request].outerHTML); });
|