我想要做的是加载一个svg,将其填充颜色更改为随机值,然后在画布上绘制它。事实证明这比我想象的要困难得多。这是我目前的代码。
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
//images
var bottomLeftTop = new Image();
var bottomRightTop = new Image();
var fullTop= new Image();
var leftMidSide = new Image();
var leftSide = new Image();
var rightMidSide = new Image();
var rightSide = new Image();
var topLeftTop = new Image();
var topRightTop = new Image();
bottomLeftTop.src = "img/bottomLeftTop.svg";
bottomRightTop.src = "img/bottomRightTop.svg";
fullTop.src = "img/fullTop.svg";
leftMidSide.src = "img/leftMidSide.svg";
leftSide.src = "img/leftSide.svg";
rightMidSide.src = "img/rightMidSide.svg";
rightSide.src = "img/rightSide.svg";
topLeftTop.src = "img/topLeftTop.svg";
topRightTop.src = "img/topRightTop.svg";
//draw
context.drawImage(fullTop,50,50);
我正在加载我的svg作为Image对象,它只适用于绘图,但不允许我更改填充颜色。
我确实尝试将我的svg转换为canvas命令,这允许我更改填充但需要大量工作才能正确缩放和定位,并且对于我正在使用的图像数量而言是不可行的。
在使用画布时,还有其他方法可以做到这一点吗?
答案 0 :(得分:10)
诀窍是通过XHR将svg加载为XML并以任何方式对其进行操作,然后使用data:image
格式从中创建图像。
E.g。
$.get('img/bottomLeftTop.svg', function(svgXml) {
var img = new Image();
var coloredSvgXml = svgXml.replace(/#3080d0/g,'#e05030');
img.src = "data:image/svg+xml;charset=utf-8,"+coloredSvgXml;
context.drawImage(img,0,0);
});
这是我创建的一个片段,用于演示操作原理。它使用in-html隐藏的svg节点在2d画布上绘制,然后通过regexp更改颜色并再次在同一画布上绘制:
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var svg = document.getElementById('tmpSvg')
var blueCircle = (new XMLSerializer).serializeToString(svg);
var img = new Image();
img.src = "data:image/svg+xml;charset=utf-8," + blueCircle;
context.drawImage(img, 0, 0);
redCircle = blueCircle.replace(/#3080d0/g, '#e05030');
img = new Image();
img.src = "data:image/svg+xml;charset=utf-8," + redCircle;
context.drawImage(img, 10, 10);
.wrapper {
display: none;
}
#canvas {
width: 400px;
height: 300px;
}
<canvas id="canvas"></canvas>
<div class="wrapper">
<svg id="tmpSvg" version="1.1" xmlns="http://www.w3.org/2000/svg" width="200" height="200">
<style>
circle {
fill-opacity: 0.5;
stroke-width: 4;
fill: #3080d0;
stroke: #3080d0;
}
</style>
<circle id="my-circle" cx="50" cy="50" r="30" />
</svg>
</div>
当然,没有什么能阻止您使用JavaScript内置的XML解析器和基于XPath的节点操作。但在这种特殊情况下,对于特定颜色,regexp可能更有效。
答案 1 :(得分:0)
一种方法是为每个图像创建一个临时画布,获取图像数据并循环遍历它。在循环中,如果像素具有颜色数据,请将其更改为所需的值。
var canvas = document.getElementById("c");
var ctx = canvas.getContext("2d");
canvas.width = 600;
canvas.height = 400;
var svg = new Image();
svg.onload = function () {
canvas.width = svg.width;
canvas.height = svg.height;
// create temporary canvas
var svgCanvas = document.createElement("canvas");
var svgCtx = svgCanvas.getContext("2d");
svgCanvas.width = svg.width;
svgCanvas.height = svg.height;
// draw the actual svg image to temporary canvas
svgCtx.drawImage(svg, 0, 0);
// get ImageData object
var svgData = svgCtx.getImageData(0, 0, svgCanvas.width, svgCanvas.height);
// get pixel data
var data = svgData.data;
// loop through data
for (var i = 0; i < data.length; i += 4) {
// check if pixel alpha value is not 0, then change the data
if (data[i + 3] !== 0) {
data[i] = 255; // pixel red value
data[i + 1] = 0; // pixel green value
data[i + 2] = 0; // pixel blue value
}
}
// put the data back to the temporary svg canvas
svgCtx.putImageData(svgData, 0, 0);
// draw temporary canvas to the real canvas
ctx.drawImage(svgCanvas, 0, 0);
}
// look out for CORS, the svg needs to be on the same origin.
svg.src = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/38/Maki-alcohol-shop-15.svg/1024px-Maki-alcohol-shop-15.svg.png";