SVG export is not working properly by modifying the text rendering function in Fabric.js 1.4.1

最后都变了- 提交于 2019-12-24 20:11:11

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!