我正在将 Fabric.js 与 Meteor 一起使用。
我有以下 SVG 图像,我将其用作路径组内路径上的图案。
正如您所看到的,它具有一定的透明度。
我想要做的是用这个图案填充路径,然后使用颜色选择器来操纵它的颜色。到目前为止,我已经能够通过将 SVG 添加为图案,然后复制路径并使用不透明度为 50% 的颜色填充该路径来做到这一点,但是当然,这会改变整个区域的颜色,而不仅仅是图案的颜色。基本上,由于模式已经是路径的“填充”,我将如何填充模式本身?
这是一个可以更好地解释的图表...
这是我在从下拉列表中选择特定模式时用来添加模式的代码(使用 Meteor 事件)...
'change .shapeTopPattern': function(e, template){ e.preventDefault();
var textureID = e.target.value;
if(textureID != '') { //If this shape has a texture selected.
var texture = Textures.findOne(textureID);
//Get the image
var textureIMG = new Image;
textureIMG.crossOrigin = "anonymous";
textureIMG.src = texture.image;
var patternURL = textureIMG.src;
fabric.Image.fromURL(patternURL, function(img) {
var obj = canvas.getActiveObject();
var paths = obj.paths;
paths.forEach(function(p) {
if (p.pathName == "shapeTopTexture") {
img.width = p.width;
img.height = p.height
var patternSourceCanvas = new fabric.StaticCanvas();
patternSourceCanvas.add(img);
patternSourceCanvas.setDimensions({
width: p.width,
height: p.height
});
var texture = patternSourceCanvas.getElement();
var pattern = new fabric.Pattern({
source: texture,
repeat: 'no-repeat',
offsetX: p.width/2,
offsetY: p.height/2
});
obj.setFill();
if (obj instanceof fabric.PathGroup) {
p.fill = pattern;
obj.perPixelTargetFind = false;
} else {
obj.setFill(pattern);
}
canvas.renderAll();
}
});
});
}
},
这是我在颜色选择器的更改事件上使用的函数。 “shapeTopPatternColour”是圆柱体路径组中的复制路径(圆柱体顶部)。我知道这显然就是为什么颜色覆盖整个区域而不仅仅是图案的原因,但它是我最接近我想要的。
changeTopPatternColour = function(o, color, opacity) {
/*
* o = object
* color = rgbcolor data
* opacity = .5
*/
var paths = o.paths;
paths.forEach(function(p) {
if (p.pathName == "shapeTopPatternColour") {
p.setFill(color);
p.opacity = opacity;
}
});
canvas.renderAll();
};
那我怎样才能...
- 添加图案并将其维护为 SVG(仅在需要时)
- 仅用颜色填充图案 Alpha,而不填充透明部分?
提前致谢。
最佳答案
不幸的是,我无法找到一种方法来将 svg 文件用作模式而不必对其进行光栅化,我很抱歉。在下面的示例中,您可以亲眼看到我总是完全重写表面。 我没有像图像一样加载 svg,而是正常加载 svg,然后使用路径组将其添加到 Canvas 中。对于此代码片段,我使用您的文件作为字符串,以避免烦人的 CORS 问题。
Here you can find the bitbucket repository
祝一切顺利。
$(function() {
var canvas = new fabric.Canvas('c');
canvas.setWidth(600);
canvas.setHeight(370);
var tint = function(color) {
canvas.clear();
var svgObjectString = '<?xml version="1.0" encoding="utf-8"?>' +
'<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"' +
' viewBox="0 0 596 366" style="enable-background:new 0 0 596 366;" xml:space="preserve">' +
'<style type="text/css">' +
'.st0{fill:#E0E0E0;}' +
' .st1{fill:url(#SVGID_1_);}' +
'</style>' +
'<path class="st0" d="M596,103.5c0,32-41.7,60.5-107.2,79.5c-51.7,15-118.2,24-190.8,24s-139.1-9-190.8-24C41.7,164,0,135.4,0,103.5' +
'c0-0.2,0-0.3,0-0.5C0.8,46.1,133.9,0,298,0s297.2,46.1,298,103C596,103.2,596,103.3,596,103.5z"/>' +
'<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="0" y1="133.25" x2="596" y2="133.25" gradientTransform="matrix(1 0 0 -1 0 368)">' +
'<stop offset="0" style="stop-color:#E8E8E8"/>' +
'<stop offset="0.23" style="stop-color:#878787"/>' +
'<stop offset="0.6" style="stop-color:#D6D6D6"/>' +
'<stop offset="1" style="stop-color:#ADADAD"/>' +
'</linearGradient>' +
'<path class="st1" d="M596,103.5v159c0,0.2,0,0.3,0,0.5c-0.8,56.9-133.9,103-298,103S0.8,319.9,0,263c0-0.2,0-0.3,0-0.5v-159' +
'c0,32,41.7,60.5,107.2,79.5c51.7,15,118.2,24,190.8,24s139.1-9,190.8-24C554.3,164,596,135.4,596,103.5z"/>' +
'</svg>';
fabric.loadSVGFromString(svgObjectString, function(svgobject) {
//fabric.loadSVGFromURL('../../Content/object.svg', function (svgobject) {
var objGroup = new fabric.PathGroup(svgobject, {
width: 596,
height: 500
});
canvas.add(objGroup);
var svgPatternString = '<?xml version="1.0" encoding="utf-8"?>' +
'<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' +
'<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"' +
' width="576px" height="576px" viewBox="0 0 576 576" enable-background="new 0 0 576 576" xml:space="preserve">' +
'<polygon fill="#848484" points="290.664,286.625 244.214,729.625 338.422,729.625 "/>' +
'<polygon fill="#848484" points="290.711,286.625 337.16,-156.375 242.953,-156.375 "/>' +
'<polygon fill="#848484" points="290.688,286.602 -152.312,240.152 -152.312,334.359 "/>' +
'<polygon fill="#848484" points="290.688,286.648 733.688,333.098 733.688,238.89 "/>' +
'<polygon fill="#848484" points="290.664,286.625 244.214,729.625 338.422,729.625 "/>' +
'<polygon fill="#848484" points="290.711,286.625 337.16,-156.375 242.953,-156.375 "/>' +
'<polygon fill="#848484" points="290.688,286.602 -152.312,240.152 -152.312,334.359 "/>' +
'<polygon fill="#848484" points="290.688,286.648 733.688,333.098 733.688,238.89 "/>' +
'<polygon fill="#848484" points="290.666,286.616 75.532,676.646 162.318,713.297 "/>' +
'<polygon fill="#848484" points="290.709,286.634 505.843,-103.396 419.057,-140.047 "/>' +
'<polygon fill="#848484" points="290.696,286.604 -99.334,71.469 -135.984,158.255 "/>' +
'<polygon fill="#848484" points="290.679,286.646 680.709,501.78 717.359,414.994 "/>' +
'<polygon fill="#848484" points="290.671,286.608 -59.646,561.716 5.948,629.336 "/>' +
'<polygon fill="#848484" points="290.704,286.642 641.021,11.534 575.427,-56.086 "/>' +
'<polygon fill="#848484" points="290.704,286.609 15.597,-63.709 -52.024,1.885 "/>' +
'<polygon fill="#848484" points="290.671,286.641 565.778,636.958 633.398,571.364 "/>' +
'<polygon fill="#848484" points="290.679,286.603 -137.942,407.811 -102.993,495.296 "/>' +
'<polygon fill="#848484" points="290.696,286.647 719.315,165.439 684.367,77.954 "/>' +
'<polygon fill="#848484" points="290.709,286.617 169.502,-142.004 82.016,-107.055 "/>' +
'<polygon fill="#848484" points="290.666,286.634 411.873,715.253 499.358,680.305 "/>' +
'</svg>';
fabric.loadSVGFromString(svgPatternString, function(svgpattern) {
//fabric.loadSVGFromURL('../../Content/pattern.svg',
// function (svgpattern) {
svgpattern.map(function(item) {
item.fill = color;
});
var ptnGroup = new fabric.PathGroup(svgpattern, {
top: -190,
width: 596,
height: 500
});
var paths = objGroup.paths;
var path = paths[0];
svgpattern.width = path.width;
svgpattern.height = path.height;
var patternSourceCanvas = new fabric.StaticCanvas();
patternSourceCanvas.add(ptnGroup);
patternSourceCanvas.setDimensions({
width: path.width,
height: path.height
});
var texture = patternSourceCanvas.getElement();
var pattern = new fabric.Pattern({
source: texture,
repeat: 'no-repeat',
offsetX: path.width / 2,
offsetY: path.height / 2
});
objGroup.setFill();
objGroup.globalCompositeOperation = "source-over";
path.setFill("#ff0000");
path.fill = pattern;
objGroup.perPixelTargetFind = false;
canvas.renderAll();
});
});
}
$('button')
.on('click',
function(e, args) {
tint(e.target.value);
});
});
canvas {
border: 1px solid #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.2/fabric.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="row">
<div class="col-md-7">
<canvas id="c" style="border: solid 1px #ccc;"></canvas>
</div>
<div class="col-md-5">
<button class="btn-danger" value="red">red</button>
<button class="btn-success" value="green">green</button>
<button class="btn-primary" value="blue">blue</button>
</div>
</div>
</div>
编辑:为了检索圆柱体顶部的尺寸,我使用 svgobject 的第一个路径
var paths = objGroup.paths;
var path = paths[0];
svgpattern.width = path.width;
svgpattern.height = path.height;
var patternSourceCanvas = new fabric.StaticCanvas();
patternSourceCanvas.add(ptnGroup);
patternSourceCanvas.setDimensions({
width: path.width,
height: path.height
});
关于meteor - Fabric.js : Use SVG as a pattern & adjust fill of SVG pattern,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41234864/