Я даю вам 2 ответа для двух тонко разных случаев.
Случай 1 - заполнение вокруг ограничивающего прямоугольника одного многострочного текста .Код соответствует подходу CSS, где поле за пределами поля, как показано красной линией, а отступы внутри, как показано золотым фоном.На левом изображении черный текстовый фон - это то, что вы получаете от встроенного textBackgroundColor.Желтая область показывает применяемый в данный момент отступ.Правое изображение показывает дополнительное преимущество при согласовании цвета отступа, а также то, что вы можете уменьшить непрозрачность фона, сохраняя текст полностью непрозрачным.
КСТАТИ встроенный атрибут padding для текстовых площадок относительно управляющей границы, но заливка цветом фона не покрывает созданное пустое пространство.Другими словами, он работает как CSS-поле, а не как заполнение CSS.
Поэтому необходимо игнорировать этот атрибут заполнения и вместо этого ввести цветной прямоугольник, чтобы задать требуемый цвет фона, сгруппировав его с элементом text ипозиционирование соответственно.
Пример фрагмента ниже.
var canvas = window._canvas = new fabric.Canvas('c');
// function to do the drawing. Could easily be accomodated into a class (excluding the canvas reset!)
function reset(pos)
{
canvas.clear();
// Create the text node - note the position is (0, 0)
var text = new fabric.Text(pos.text, {
fontFamily: 'Arial',
left: 0,
top: 0,
fill: "#ffffff",
stroke: "",
textBackgroundColor: '#000000'
});
// create the outer 'margin' rect, note the position is negatively offset for padding & margin
// and the width is sized from the dimensions of the text node plus 2 x (padding + margin).
var rectMargin = new fabric.Rect({
left: -1 * (pos.padding.left + pos.margin.left),
top: -1 * (pos.padding.top + pos.margin.top),
width: text.width + ((pos.padding.left + pos.padding.right) + (pos.margin.left + pos.margin.right)),
height: text.height + ((pos.padding.top + pos.padding.bottom) + (pos.margin.top + pos.margin.bottom)),
strokeWidth: pos.border,
stroke: 'red',
fill: 'transparent'
})
// create the inner 'padding' rect, note the position is offset for padding only
// and the width is sized from the dimensions of the text node plus 2 x padding.
var rectPadding = new fabric.Rect({
width: text.width + (pos.padding.left + pos.padding.right),
height: text.height + (pos.padding.top + pos.padding.bottom),
left: -1 * pos.padding.left, top: -1 * pos.padding.top,
fill: 'gold'
})
// create group and add shapes to group, rect first so it is below text.
// note that as the group is oversized, we position it at pos - padding.
var group = new fabric.Group([ rectMargin, rectPadding, text ], {
left: pos.x - (pos.padding.left - pos.margin.left),
top: pos.y - (pos.padding.top - pos.margin.top),
angle: pos.angle,
});
canvas.add(group);
}
// function to grab values from user inputs
function go()
{
var m = $('#margin').val().split(',');
var p = $('#padding').val().split(',');
for (var i = 0 ; i < 4; i = i + 1)
{
p[i] = parseInt(p[i], 10); // ensure we have numbers and not strings !
m[i] = parseInt(m[i], 10);
}
// Object holding position and content info
var pos = {x: 50, y : 10, text: 'Text with padding\nand another line',
padding: {top:p[0], right:p[1], bottom: p[2], left: p[3]}, margin: {top:m[0], right:m[1], bottom: m[2], left: m[3]}, border: 1, angle: 10};
reset(pos);
}
// click handler for go button
$('#go').on('click', function(e){
go();
})
// call go once to show on load
go();
div
{
background-color: silver;
width: 600px;
height: 300px;
}
.ipt
{
margin-right: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.1/fabric.min.js"></script>
<p>
<span class='ipt'> Margin: <input id='margin' value = '12,10,12,10' /></span>
<span class='ipt'> Padding: <input id='padding' value = '0,5,0,5' /></span>
<span class='ipt'><button id='go' />Go</button></span>
<div>
<canvas id="c" width="600" height="300"></canvas>
</div>
Случай 2: заполнение рамками отдельных строк текста, а не полного ограничивающего прямоугольника .
InВ этом случае вы можете увидеть разницу в том, как мягкий фон отслеживает каждую строку текста, а не применяется к внешней ограничительной рамке текста.Решение более сложное, включающее создание фиктивного текстового узла, который затем предоставляет информацию о разбиении строки и размере.Затем мы циклически перебрасываем данные строки, выводя отдельные строки текста и отступы в группу, что означает, что мы можем позиционировать и обрабатывать текст как один объект, как показано с применением угла.
var textIn = 'Text goat\nMillenium jam\nplumb\nBlack & White'
var canvas = window._canvas = new fabric.Canvas('c');
// function to do the drawing. Could easily be accomodated into a class (excluding the canvas reset!)
function reset(pos)
{
canvas.clear();
// Create the text measuring node - not added to the canvas !
var textMeasure = new fabric.IText(pos.text, {
fontFamily: 'Arial',
left: 0,
top: 0,
fill: "#ffffff",
stroke: "",
textBackgroundColor: '#000000'
});
// loop round the lines in the text creating a margin/pad scenario for each line
var theText, text, textHeight, rectPadding, rectMargin, top = 0, shapes = [];
for (var i = 0; i < textMeasure._textLines.length; i = i + 1){
theText = textMeasure._textLines[i].join('');
textHeight = Math.floor(textMeasure.lineHeight * textMeasure.fontSize) //textMeasure.getHeightOfLine(i)
// Make the text node for line i
text = new fabric.IText(theText, {
fontFamily: 'Arial',
left: 0,
top: top,
fill: "#ffffff",
stroke: ""
});
// create the outer 'margin' rect, note the position is negatively offset for padding & margin
// and the width is sized from the dimensions of the text node plus 2 x (padding + margin).
rectMargin = new fabric.Rect({
left: -1 * (pos.padding.left + pos.margin.left),
top: top - (pos.padding.top + pos.margin.top),
width: text.width + ((pos.padding.left + pos.padding.right) + (pos.margin.left + pos.margin.right)),
height: textHeight + ((pos.padding.top + pos.padding.bottom) + (pos.margin.top + pos.margin.bottom)),
fill: 'transparent'
})
shapes.push(rectMargin);
// create the inner 'padding' rect, note the position is offset for padding only
// and the width is sized from the dimensions of the text node plus 2 x padding.
rectPadding = new fabric.Rect({
width: text.width + (pos.padding.left + pos.padding.right),
height: textHeight + (pos.padding.top + pos.padding.bottom),
left: -1 * pos.padding.left,
top: top - pos.padding.top,
fill: '#000000ff'
})
shapes.push(rectPadding);
shapes.push(text);
// move the insert point down by the height of the line
var gap = 0; // text.lineHeight - textHeight;
top = top - 1 + textHeight + pos.padding.top + pos.margin.top + pos.padding.bottom + pos.margin.bottom;
}
// At this point we have a list of shapes to output in the shapes[] array.
// Create group and add the shapes to group.
// note that group is positioned so that the topleft of the first text line is where
// it would fall if it were a standard text node.
var group = new fabric.Group(shapes, {
left: pos.x - (pos.padding.left - pos.margin.left),
top: pos.y - (pos.padding.top - pos.margin.top),
angle: pos.angle,
});
canvas.add(group);
}
// function to grab values from user inputs
function go()
{
var m = $('#margin').val().split(',');
var p = $('#padding').val().split(',');
for (var i = 0 ; i < 4; i = i + 1)
{
p[i] = parseInt(p[i], 10); // ensure we have numbers and not strings !
m[i] = parseInt(m[i], 10);
}
// Object holding position and content info
var pos = {x: 70, y : 10, text: textIn,
padding: {top:p[0], right:p[1], bottom: p[2], left: p[3]}, margin: {top:m[0], right:m[1], bottom: m[2], left: m[3]}, border: 1, angle: 10};
reset(pos);
}
// click handler for go button
$('#go').on('click', function(e){
go();
})
// call go once to show on load
go();
div
{
background-color: silver;
width: 600px;
height: 100px;
}
.ipt
{
margin-right: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.1/fabric.min.js"></script>
<p>
<span class='ipt'> Margin: <input id='margin' value = '0,0,0,0' /></span>
<span class='ipt'> Padding: <input id='padding' value = '5,15,5,15' /></span>
<span class='ipt'><button id='go' />Go</button></span>
<div>
<canvas id="c" width="600" height="300"></canvas>
</div>