【问题标题】:Fabricjs text spacingFabricjs 文本间距
【发布时间】:2016-04-06 22:52:18
【问题描述】:

我已经覆盖了 fabricjs Text 对象来设置字母间距

fabric.util.object.extend(fabric.Text.prototype, {
    letterSpace: 0,
    _renderChars: function(method, ctx, chars, left, top) {
        if(!this.letterSpace){
            ctx[method](chars, left, top);
            return;
        }
        var charShift = 0;
        for(var i = 0; i < chars.length; i++){
            if(i > 0){
                charShift += this.letterSpace + ctx.measureText(chars.charAt(i-1)).width;
           }
           ctx[method](chars.charAt(i), left+charShift, top);
       }
    },
    _getLineWidth: function(ctx, lineIndex) {
        if (this.__lineWidths[lineIndex]) {
            return this.__lineWidths[lineIndex];
        }
        var lineLength = this._textLines[lineIndex].length;
        var additionalSpaceSum = 0
        if(lineLength > 0){
            additionalSpaceSum = this.letterSpace * (lineLength - 1);
        }
        this.__lineWidths[lineIndex] = ctx.measureText(this._textLines[lineIndex]).width + additionalSpaceSum;
        return this.__lineWidths[lineIndex];
    }
});

间距很好,但宽度不正确,如何改进宽度计算?

我在这个问题中改进了我的代码,现在它工作正常))

很抱歉没有显示以前的错误,但是这里很难弄清楚鳕鱼,而且我在这个问题中的前面是正确的。

但我已经为左文本对齐编写了它,如果您使用不同的对齐,则需要更正它。对我来说已经足够了

【问题讨论】:

    标签: fabricjs


    【解决方案1】:

    我已经改进了有问题的代码,现在可以正常工作))抱歉。

    但是我已经为左文本对齐写了它,如果你使用不同的对齐,你需要更正它。对我来说已经足够了

    fabric.util.object.extend(fabric.Text.prototype, {
        letterSpace: 0,
        _renderChars: function (method, ctx, chars, left, top) {
            if (!this.letterSpace) {
                ctx[method](chars, left, top);
                return;
            }
            var charShift = 0;
            for (var i = 0; i < chars.length; i++) {
                if (i > 0) {
                    charShift += this.letterSpace + ctx.measureText(chars.charAt(i - 1)).width;
                }
                ctx[method](chars.charAt(i), left + charShift, top);
            }
        },
        _getLineWidth: function (ctx, lineIndex) {
            var lineLength = this._textLines[lineIndex].length;
            var additionalSpaceSum = 0
            if (lineLength > 0) {
                additionalSpaceSum = this.letterSpace * (lineLength - 1);
            }
            this.__lineWidths[lineIndex] = ctx.measureText(this._textLines[lineIndex]).width + additionalSpaceSum;
            return this.__lineWidths[lineIndex];
        },
        _renderExtended: function (ctx) {
            this.clipTo && fabric.util.clipContext(this, ctx);
            this.extendedRender = true;
            this._renderTextBackground(ctx);
            this._renderText(ctx);
    
            this._renderTextDecoration(ctx);
            this.clipTo && ctx.restore();
        }
    });
    

    【讨论】:

    • 你会展示一些你是如何使用扩展属性的。
    • 正如我所写的,我已经改进了我的代码。但现在我在我的答案中复制了它。但是对我有用!!!我没有使用不同的对齐方式
    • 实际上我正在尝试在我的项目中使用您的代码。但我不明白我将如何在客户端使用它。
    • 还有什么不明白的?而且你不需要使用 _renderExtended: 函数。这是为我的情况而写的
    【解决方案2】:

    此代码适用于所有对齐方式:

    fabric.util.object.extend(fabric.Text.prototype, {
    letterSpace: 0,
    _renderChars: function (method, ctx, chars, left, top) {
        if (!this.letterSpace) {
            ctx[method](chars, left, top);
            return;
        }
        var characters = String.prototype.split.call(chars, '');
        if(this.textAlign == 'left'){
            var charShift = 0;
            for (var i = 0; i < chars.length; i++) {
                if (i > 0) {
                    charShift += this.letterSpace + ctx.measureText(chars.charAt(i - 1)).width;
                }
                ctx[method](chars.charAt(i), left + charShift, top);
            }    
        }else if(this.textAlign == 'right'){
    
            characters.reverse();
            chars = characters.join('');
            var charShift = 0;
            for (var i = 0; i < chars.length; i++) {
                if (i > 0) {
                    charShift += this.letterSpace + ctx.measureText(chars.charAt(i - 1)).width;
                }
                ctx[method](chars.charAt(i), left - charShift, top);
            }    
        }else if(this.textAlign == 'center'){
    
            var totalWidth = 0;
            for (var i = 0; i < characters.length; i++) {
                totalWidth += (ctx.measureText(characters[i]).width + this.letterSpace);
            }
            var currentPosition = left - (totalWidth / 2);
    
    
            var charShift = 0;
            for (var i = 0; i < chars.length; i++) {
                if (i > 0) {
                    charShift += this.letterSpace + ctx.measureText(chars.charAt(i - 1)).width;
                }
                ctx[method](chars.charAt(i), currentPosition + left + charShift, top);
            }    
        }
    
    },
    _getLineWidth: function (ctx, lineIndex) {
        var lineLength = this._textLines[lineIndex].length;
        var additionalSpaceSum = 0
        if (lineLength > 0) {
            additionalSpaceSum = this.letterSpace * (lineLength - 1);
        }
        this.__lineWidths[lineIndex] = ctx.measureText(this._textLines[lineIndex]).width + additionalSpaceSum;
        return this.__lineWidths[lineIndex];
    },
    _renderExtended: function (ctx) {
        this.clipTo && fabric.util.clipContext(this, ctx);
        this.extendedRender = true;
        this._renderTextBackground(ctx);
        this._renderText(ctx);
    
        this._renderTextDecoration(ctx);
        this.clipTo && ctx.restore();
    }});
    

    这里是一个例子:http://jsfiddle.net/peybdq94/

    【讨论】:

    • 这段代码在不太宽的字符上出现居中文本的问题,比如 I 和小写 l。我还没有找到解决方案,这是您的 jsfiddle 的分叉版本,它演示了这个问题:jsfiddle.net/bslinger/rbow7Lyx/2
    【解决方案3】:

    我尝试实现此功能并通过扩展 _renderChar 提出了此 https://jsfiddle.net/ghazaltaimur/bx0f4qpg/1/。我做了一些补充。该代码允许将字母间距应用于所选文本而不是仅应用于整个对象。此外,如果要添加字母间距,则必须考虑 itext 选择、边界框和光标位置。我也试图涵盖这些方面。可能还有几个问题需要解决。

        fabric.util.object.extend(fabric.IText.prototype, {
          letterSpace: 0,
          _renderChar: function(method, ctx, lineIndex, i, _char, left, top, lineHeight) {
            var decl, charWidth, charHeight,
              offset = this._fontSizeFraction * lineHeight / this.lineHeight;
            if (this.styles && this.styles[lineIndex] && (decl = this.styles[lineIndex][i])) {
              var shouldStroke = decl.stroke || this.stroke,
                shouldFill = decl.fill || this.fill;
              ctx.save();
              charWidth = this._applyCharStylesGetWidth(ctx, _char, lineIndex, i, decl);
              charHeight = this._getHeightOfChar(ctx, _char, lineIndex, i);
              var chars = _char;
              var characters = String.prototype.split.call(chars, '');
              var charShift = 0;
              var leftcharShift = 0;
              var letterSpace;
              for (var i = 0; i < chars.length; i++) {
                var style = this.getCurrentCharStyle(lineIndex, i + 1);
                letterSpace = style.letterSpace;
                if (i > 0) {
                  charShift += parseInt(letterSpace) + parseInt(ctx.measureText(chars.charAt(i - 1)).width);
                }
                if (this.text.indexOf(chars) !== 0 && charShift === 0) {
                  charShift = this.text.indexOf(chars) * parseInt(letterSpace);
                }
                leftcharShift = parseInt(left) + parseInt(charShift);
                if (shouldFill) {
                  ctx.fillText(chars.charAt(i), leftcharShift, top);
                }
                if (shouldStroke) {
                  ctx.strokeText(chars.charAt(i), leftcharShift, top);
                }
              }
              this._renderCharDecoration(ctx, decl, left, top, offset, charWidth, charHeight);
              ctx.restore();
              ctx.translate(charWidth, 0);
            } else {
              charWidth = this._applyCharStylesGetWidth(ctx, _char, lineIndex, i);
              var chars = _char;
              var characters = String.prototype.split.call(chars, '');
              var charShift = 0;
              var leftcharShift = 0;
              var letterSpace;
              for (var i = 0; i < chars.length; i++) {
                var style = this.getCurrentCharStyle(lineIndex, i + 1);
                letterSpace = style.letterSpace;
                if (i > 0) {
                  charShift += parseInt(letterSpace) + parseInt(ctx.measureText(chars.charAt(i - 1)).width);
                }
                if (this.text.indexOf(chars) !== 0 && charShift === 0) {
                  charShift = this.text.indexOf(chars) * parseInt(letterSpace);
                }
                leftcharShift = parseInt(left) + parseInt(charShift);
                if (method === 'strokeText' && this.stroke) {
                  ctx[method](chars.charAt(i), leftcharShift, top);
                }
                if (method === 'fillText' && this.fill) {
                  ctx[method](chars.charAt(i), leftcharShift, top);
                }
              }
              this._renderCharDecoration(ctx, null, left, top, offset, charWidth, this.fontSize);
              ctx.translate(ctx.measureText(_char).width, 0);
            }},
        getCurrentCharStyle: function(lineIndex, charIndex) {
            var style = this.styles[lineIndex] && this.styles[lineIndex][charIndex === 0 ? 0 : (charIndex - 1)];
            return {
              fontSize: style && style.fontSize || this.fontSize,
              fill: style && style.fill || this.fill,
              textBackgroundColor: style && style.textBackgroundColor || this.textBackgroundColor,
              textDecoration: style && style.textDecoration || this.textDecoration,
              fontFamily: style && style.fontFamily || this.fontFamily,
              fontWeight: style && style.fontWeight || this.fontWeight,
              fontStyle: style && style.fontStyle || this.fontStyle,
              stroke: style && style.stroke || this.stroke,
              strokeWidth: style && style.strokeWidth || this.strokeWidth,
              letterSpace: style && style.letterSpace || this.letterSpace
            };
          },
          _renderTextLine: function(method, ctx, line, left, top, lineIndex) {
            // to "cancel" this.fontSize subtraction in fabric.Text#_renderTextLine
            // the adding 0.05 is just to align text with itext by overlap test
            if (!this.isEmptyStyles()) {
              top += this.fontSize * (this._fontSizeFraction + 0.05);
            }
            this.callSuper('_renderTextLine', method, ctx, line, left, top, lineIndex);
          },
          _getWidthOfChar: function(ctx, _char, lineIndex, charIndex) {
            if (this.textAlign === 'justify' && /\s/.test(_char)) {
              return this._getWidthOfSpace(ctx, lineIndex);
            }

    var styleDeclaration = this._getStyleDeclaration(lineIndex, charIndex); this._applyFontStyles(styleDeclaration); var cacheProp = this._getCacheProp(_char, styleDeclaration); var style = this.getCurrentCharStyle(lineIndex, charIndex); var letterSpace = style.letterSpace; if (this._charWidthsCache[cacheProp] && this.caching) { 返回 parseInt(this._charWidthsCache[cacheProp]) + parseInt(letterSpace); }否则如果(ctx){ ctx.save(); var width = this._applyCharStylesGetWidth(ctx, _char, lineIndex, charIndex); 宽度 = parseInt(width) + parseInt(letterSpace); ctx.restore(); 返回宽度; } }, }); // 结构 js 代码 var canvas = new fabric.Canvas('fabric_canvas'); // 添加文字 fabric.util.addListener(document.getElementById('addText'), 'click', function() { var itext = new fabric.IText("添加文本", { 左:50, 最高:50 }); canvas.add(itext); canvas.setActiveObject(itext); var obj = canvas.getActiveObject(); var seletedText = obj.getSelectedText(); itext.selectAll(); itext.enterEditing(); if (obj.setSelectionStyles && obj.isEditing) obj.setSelectionStyles({ 字母空间:1 }); if (seletedText === "") { obj.exitEditing(); } canvas.renderAll(); }); // 添加字母间距 fabric.util.addListener(document.getElementById('addLetterSpacing'), 'click', function() { var activeObject = canvas.getActiveObject(); var seletedText = activeObject.getSelectedText(); if (seletedText === "") { activeObject.selectAll(); activeObject.enterEditing(); } if (activeObject.setSelectionStyles && activeObject.isEditing) activeObject.setSelectionStyles({ 字母空间:30 }); if (seletedText === "") { activeObject.exitEditing(); } var ctx = activeObject.ctx; var textLines = activeObject.text.split(activeObject._reNewline); var letterSpace = (activeObject.getSelectionStyles && activeObject.isEditing && activeObject.evented === true) ? activeObject.getSelectionStyles()["letterSpace"] : activeObject["letterSpace"]; activeObject.width = activeObject._getTextWidth(ctx, textLines, activeObject) + (activeObject.text.length * letterSpace); activeObject.height = activeObject._getTextHeight(ctx, textLines, activeObject); activeObject.callSuper('setCoords'); canvas.renderAll(); }); [1]:https://jsfiddle.net/ghazaltaimur/bx0f4qpg/1/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多