问题
I have modified some code of Fabric.text to get arc shape of text . But the problem is toSVG() is rendering the plain text instead of arc text. How can i render it properly. https://i.stack.imgur.com/A3bnx.png (Rendering Canvas)
https://i.stack.imgur.com/R4cY0.png (Exported SVG)
If there is an alternative way to print in svg then let me know.
_renderText: function(ctx) {
this._translateForTextAlign(ctx);
/* this._renderTextFill(ctx);*/
this._getCircularText(ctx)
/* this._renderTextStroke(ctx);*/
this._translateForTextAlign(ctx, true);
},
_getCircularText: function(ctx)
{
var text = this.text,
arc = this.arc/4,
inwardFacing = true,
angle = 0,
kerning = 0,
cw=0,
x,
clockwise = 1;
if(arc>0){
clockwise=1;
inwardFacing=true;
}else{
clockwise=-1;
inwardFacing=false;
}
var lineHeights = 0;
var widthOftext=0;
var maxHeight=0;
;
for (x = 0; x < text.length; x++) {
cw = ctx.measureText(text[x]).width;
angle=(arc)/((text.length*cw));
if(arc){
ctx.rotate(-angle/2);
}
}
for (x = 0; x < text.length; x++) {
cw = ctx.measureText(text[x]).width;
var heightOfLine = this._getHeightOfLine(ctx, x, text);
angle=(arc)/((text.length*cw));
ctx.rotate(angle);
lineHeights += heightOfLine;
ctx.fillText(text[x], (-this.width/2)+widthOftext , (-this.height/2)+heightOfLine);
widthOftext+= cw;
}
},
You can find the code for SVG Export below
toSVG: function(reviver) {
// console.log(20833);
var markup = this._createBaseSVGMarkup(),
offsets = this._getSVGLeftTopOffsets(this.ctx),
textAndBg = this._getSVGTextAndBg(offsets.textTop, offsets.textLeft);
console.log(textAndBg);
this._wrapSVGTextAndBg(markup, textAndBg);
return reviver ? reviver(markup.join('')) : markup.join('');
},
/**
* @private
*/
_getSVGLeftTopOffsets: function(ctx) {
var lineTop = this._getHeightOfLine(ctx, 0),
textLeft = -this.width / 2,
textTop = 0;
return {
textLeft: textLeft + (this.group && this.group.type === 'path-group' ? this.left : 0),
textTop: textTop + (this.group && this.group.type === 'path-group' ? -this.top : 0),
lineTop: lineTop
};
},
/**
* @private
*/
_wrapSVGTextAndBg: function(markup, textAndBg) {
var noShadow = true, filter = this.getSvgFilter(),
style = filter === '' ? '' : ' style="' + filter + '"';
console.log(textAndBg.textSpans);
markup.push(
'\t<g transform="', this.getSvgTransform(), this.getSvgTransformMatrix(), '"',
style, '>\n',
textAndBg.textBgRects.join(''),
'\t\t<text ',
(this.fontFamily ? 'font-family="' + this.fontFamily.replace(/"/g, '\'') + '" ': ''),
(this.fontSize ? 'font-size="' + this.fontSize + '" ': ''),
(this.fontStyle ? 'font-style="' + this.fontStyle + '" ': ''),
(this.fontWeight ? 'font-weight="' + this.fontWeight + '" ': ''),
(this.textDecoration ? 'text-decoration="' + this.textDecoration + '" ': ''),
'style="', this.getSvgStyles(noShadow), '" >\n',
textAndBg.textSpans.join(''),
'\t\t</text>\n',
'\t</g>\n'
);
},
/**
* @private
* @param {Number} textTopOffset Text top offset
* @param {Number} textLeftOffset Text left offset
* @return {Object}
*/
_getSVGTextAndBg: function(textTopOffset, textLeftOffset) {
var textSpans = [ ],
textBgRects = [ ],
height = 0;
// bounding-box background
this._setSVGBg(textBgRects);
// console.log(this._textLines);
// text and text-background
for (var i = 0, len = this._textLines.length; i < len; i++) {
if (this.textBackgroundColor) {
this._setSVGTextLineBg(textBgRects, i, textLeftOffset, textTopOffset, height);
}
this._setSVGTextLineText(i, textSpans, height, textLeftOffset, textTopOffset, textBgRects);
height += this._getHeightOfLine(this.ctx, i);
}
return {
textSpans: textSpans,
textBgRects: textBgRects
};
},
_setSVGTextLineText: function(i, textSpans, height, textLeftOffset, textTopOffset) {
var yPos = this.fontSize * (this._fontSizeMult - this._fontSizeFraction)
- textTopOffset + height - this.height / 2;
if (this.textAlign === 'justify') {
// i call from here to do not intefere with IText
this._setSVGTextLineJustifed(i, textSpans, yPos, textLeftOffset);
return;
}
// console.log(textSpans);
textSpans.push(
'\t\t\t<tspan x="',
toFixed(textLeftOffset + this._getLineLeftOffset(this._getLineWidth(this.ctx, i)), NUM_FRACTION_DIGITS), '" ',
'y="',
toFixed(yPos, NUM_FRACTION_DIGITS),
'" ',
// doing this on <tspan> elements since setting opacity
// on containing <text> one doesn't work in Illustrator
this._getFillAttributes(this.fill), '>',
fabric.util.string.escapeXml(this._textLines[i]),
'</tspan>\n'
);
// console.log(textSpans);
},
_setSVGTextLineJustifed: function(i, textSpans, yPos, textLeftOffset) {
var ctx = fabric.util.createCanvasElement().getContext('2d');
this._setTextStyles(ctx);
var line = this._textLines[i],
words = line.split(/\s+/),
wordsWidth = this._getWidthOfWords(ctx, line),
widthDiff = this.width - wordsWidth,
numSpaces = words.length - 1,
spaceWidth = numSpaces > 0 ? widthDiff / numSpaces : 0,
word, attributes = this._getFillAttributes(this.fill),
len;
textLeftOffset += this._getLineLeftOffset(this._getLineWidth(ctx, i));
for (i = 0, len = words.length; i < len; i++) {
word = words[i];
textSpans.push(
'\t\t\t<tspan x="',
toFixed(textLeftOffset, NUM_FRACTION_DIGITS), '" ',
'y="',
toFixed(yPos, NUM_FRACTION_DIGITS),
'" ',
// doing this on <tspan> elements since setting opacity
// on containing <text> one doesn't work in Illustrator
attributes, '>',
fabric.util.string.escapeXml(word),
'</tspan>\n'
);
textLeftOffset += this._getWidthOfWords(ctx, word) + spaceWidth;
}
},
_setSVGTextLineBg: function(textBgRects, i, textLeftOffset, textTopOffset, height) {
textBgRects.push(
'\t\t<rect ',
this._getFillAttributes(this.textBackgroundColor),
' x="',
toFixed(textLeftOffset + this._getLineLeftOffset(this._getLineWidth(this.ctx, i)), NUM_FRACTION_DIGITS),
'" y="',
toFixed(height - this.height / 2, NUM_FRACTION_DIGITS),
'" width="',
toFixed(this._getLineWidth(this.ctx, i), NUM_FRACTION_DIGITS),
'" height="',
toFixed(this._getHeightOfLine(this.ctx, i) / this.lineHeight, NUM_FRACTION_DIGITS),
'"></rect>\n');
},
_setSVGBg: function(textBgRects) {
if (this.backgroundColor) {
textBgRects.push(
'\t\t<rect ',
this._getFillAttributes(this.backgroundColor),
' x="',
toFixed(-this.width / 2, NUM_FRACTION_DIGITS),
'" y="',
toFixed(-this.height / 2, NUM_FRACTION_DIGITS),
'" width="',
toFixed(this.width, NUM_FRACTION_DIGITS),
'" height="',
toFixed(this.height, NUM_FRACTION_DIGITS),
'"></rect>\n');
}
},
/**
* Adobe Illustrator (at least CS5) is unable to render rgba()-based fill values
* we work around it by "moving" alpha channel into opacity attribute and setting fill's alpha to 1
*
* @private
* @param {Any} value
* @return {String}
*/
_getFillAttributes: function(value) {
var fillColor = (value && typeof value === 'string') ? new fabric.Color(value) : '';
if (!fillColor || !fillColor.getSource() || fillColor.getAlpha() === 1) {
return 'fill="' + value + '"';
}
return 'opacity="' + fillColor.getAlpha() + '" fill="' + fillColor.setAlpha(1).toRgb() + '"';
},
来源:https://stackoverflow.com/questions/59242972/svg-export-is-not-working-properly-by-modifying-the-text-rendering-function-in-f