css - 如何在 HTML5 Canvas 上使用外部 CSS 绘制 SVG
问题描述
我需要在画布上使用外部 CSS 文件绘制 SVG。
在以下示例代码中,它的第一个多边形(三角形)使用 SVG,第二个使用从 SVG 绘制的画布,第三个使用从画布转换的图像。SVG 标签使用来自外部 common.css 文件的<polygon>
ploygon CSS
svgtest.html:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title></title>
<link href="common.css" type="text/css" rel="stylesheet"
xmlns="http://www.w3.org/1999/xhtml"/>
</head>
<body>
<div id="svg-container">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" width="500" height="210">
<defs>
</defs>
<g>
<rect x="78" y="78" width="694" height="284" style="stroke-width: 0px; fill: #ffffff; fill-opacity: 1;"></rect>
<svg width="500" height="210" >
<polygon class="ploygon" points="200,10 250,190 160,210" />
</svg>
</g>
</svg>
</div>
<div>
</div>
<canvas id="canvas" width="500" height="210"></canvas>
<div id="png-container"></div>
<script>
var svgElement = document.querySelector('svg');
svgElement.onload = function() {
var svgString = new XMLSerializer().serializeToString(svgElement);
var svg = new Blob([svgString], { type: "image/svg+xml;charset=utf-8" });
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var DOMURL = self.URL || self.webkitURL || self;
var img = new Image();
var url = DOMURL.createObjectURL(svg);
img.src = url;
img.onload = function () {
ctx.drawImage(img, 0, 0);
var png = canvas.toDataURL("image/png");
document.querySelector('#png-container').innerHTML = '<img src="' + png + '"/>';
DOMURL.revokeObjectURL(png);
};
}
var canvas1 = document.getElementById("canvas");
</script>
</body>
</html>
common.css:
.ploygon {
fill:lime;
}
当我将 CSS<link>
放入<head>
如上图所示时,第一个 SVG 三角形可以使用 .ploygon CSS 并填充石灰色,第二个和第三个三角形填充黑色。
我读过 CSS 链接标签可以放在 SVG 中。当我执行以下操作时:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" width="850" height="440">
<defs>
<link href="common.css" type="text/css" rel="stylesheet"
xmlns="http://www.w3.org/1999/xhtml"/>
</defs>
<g>
<rect x="78" y="78" width="694" height="284" style="stroke-width: 0px; fill: #ffffff; fill-opacity: 1;"></rect>
<svg height="210" width="500">
<polygon class="ploygon" points="200,10 250,190 160,210" />
</svg>
</g>
</svg>
所有 3 个三角形都不使用 CSS 并用黑色填充:
如果我改用这样的内联<svg>
样式
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" width="500" height="210">
<defs>
<style>
.ploygon {
fill:lime;
}
</style>
</defs>
<g>
<rect x="78" y="78" width="694" height="284" style="stroke-width: 0px; fill: #ffffff; fill-opacity: 1;"></rect>
<svg width="500" height="210" >
<polygon class="ploygon" points="200,10 250,190 160,210" />
</svg>
</g>
</svg>
然后所有 3 个三角形都用石灰填充:
我曾尝试在 中使用 import the common.css <defs>
,但它不使用 css 文件。我不想将 CSS 样式内联。有什么好的解决方案吗?
解决方案
一种解决方案是读取 CSS 文件内容并将其作为样式节点插入到 SVG 中:
// Create style element and insert the rules in it
let style = document.createElementNS("http://www.w3.org/2000/svg", "style");
style.textContent = getCssStringFromFile('common.css');
svgElement.insertBefore(style, svgElement.firstChild);
这是 getCssStringFromFile 函数:
/**
* Returns css rules as string from linked css file
* @param {string} fileName - The css file name.
*/
function getCssStringFromFile(fileName){
let cssStyles = "";
for(let i=0; i < document.styleSheets.length; i++) {
let styleSheet = document.styleSheets[i];
if (!styleSheet.href || styleSheet.href.indexOf(fileName) == -1)
continue;
let style = null;
if (styleSheet) {
if (typeof styleSheet.cssRules !== "undefined")
style = styleSheet.cssRules;
else if (typeof styleSheet.rules !== "undefined")
style = styleSheet.rules;
}
for(let item in style) {
if(typeof style[item].cssText !== "undefined")
cssStyles += (style[item].cssText);
}
break;
}
return cssStyles;
}
请在此处查看演示
推荐阅读
- java - 如何让我的 Spring 库项目实现在使用该库的项目中定义接口的 bean?
- python - Python:如何仅对特定的 URL 参数进行 URL 编码?
- azure-maps - Azure maps 室内模块:如何从 Azure Maps Web SDK 访问 Indoor Map GeoJSON
- python - 使用python修改json文件的子值
- c# - 我们如何使用 C# 从字符串中获取精确值
- python - 在 pandas 数据框中重新排序公共列但不重新排序其他列
- c# - 在 TransactionScope 上下文中遇到时停止调试 WinForms 应用程序是否有任何危险
- 3d - gltf 3D 模型的位置、法线、texcoords 和其他此类属性是否总是在同一个缓冲区中找到?
- kotlin - 带 Hilt 的 SavedStateViewModelFactory
- java - Spring,具有原型范围的bean构造函数中的@Value问题