2015-05-17 101 views
0

我有越權fabricjs文本對象,使字母間距Fabricjs文字間距

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]; 
    } 
}); 

間距的作品不錯,但寬度是不正確的,如何提高寬度計算?

我必須提高我在這個問題上的代碼,現在它很好地工作))

對不起,不顯示以前的錯誤,但這裏是太難明確鱈魚,而我在本題正確以前。

但是我已經寫了左邊的文字對齊,如果你使用不同的對齊,你需要更正它。對我來說,這已經足夠了

回答

0

我改進了我的代碼,現在它工作正常))抱歉。

但是我已經寫了左邊的文字對齊,如果你使用不同的對齊,你需要更正它。對我來說,這已經足夠了

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(); 
    } 
}); 
+0

你會告訴我如何使用擴展屬性。 –

+0

正如我寫的,我改進了我的代碼。但是現在我已經在我的答案上覆制了它。但它爲我工作!我沒有使用不同的顏色 – webmak10

+0

實際上我試圖在我的項目中使用我的代碼。但我不明白我將如何在客戶端使用它。 –

0

此代碼對於所有排列:

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/

+0

這段代碼有一些問題,中心文字不是很寬的字符,如I和小寫l。我還沒有發現一個解決方案,這裏是你的jsfiddle分叉版本,它演示了這個問題:http://jsfiddle.net/bslinger/rbow7Lyx/2/ –

0

我想實現這個功能,並通過擴展_renderChar本https://jsfiddle.net/ghazaltaimur/bx0f4qpg/1/想出了。我做了一些補充。該代碼允許在所選文本上應用字母間距,而不是僅在整個對象上應用字母間距。如果要添加字母間距,則必須考慮迭代文本選擇,邊界框和光標位置。我也試圖涵蓋這些方面。可能有幾個問題仍然需要解決。

 
    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) { return parseInt(this._charWidthsCache[cacheProp]) + parseInt(letterSpace); } else if (ctx) { ctx.save(); var width = this._applyCharStylesGetWidth(ctx, _char, lineIndex, charIndex); width = parseInt(width) + parseInt(letterSpace); ctx.restore(); return width; } }, }); // fabric js code var canvas = new fabric.Canvas('fabric_canvas'); // add text fabric.util.addListener(document.getElementById('addText'), 'click', function() { var itext = new fabric.IText("Add text", { left: 50, top: 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({ letterSpace: 1 }); if (seletedText === "") { obj.exitEditing(); } canvas.renderAll(); }); // add letter spacing 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({ letterSpace: 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(); }); </code></pre> [1]: https://jsfiddle.net/ghazaltaimur/bx0f4qpg/1/