javascripthtmlcanvasbidi

HTML5 Canvas RTL for Individual Texts


I have a <canvas> on which I want to render right-to-left strings (e.g. Hebrew sentence with some English words somewhere in the middle).

For the whole canvas, a dir attribute may be specified. So, in my example I'd use <canvas dir="rtl />.

Unfortunately, this solution is far from being complete. I have some sentences in the same application that are LTR (for example, English only, or English with some Hebrew at the middle, but not the opposite).

Here's a naive example of how the dir attribute chages that way the canvas handles bidirectional strings:

var text = 'קצת text בעברית'

var rtlCanvas = document.getElementById('rtl-canvas')
var rtlCtx = rtlCanvas.getContext('2d')
rtlCtx.font = '24px Arial'
rtlCtx.fillText(text, 250, 50)

var ltrCanvas = document.getElementById('ltr-canvas')
var ltrCtx = ltrCanvas.getContext('2d')
ltrCtx.font = '24px Arial'
ltrCtx.fillText(text, 0, 50)
<div>
  <p>Looking good with dir=rtl:</p>
  <canvas id="rtl-canvas" dir="rtl" width=300 height=100/>
</div>

<div>
  <p>With dir=ltr, first and last words are swapped</p>
  <canvas id="ltr-canvas" dir="ltr" width=300 height=100/>
</div>


Solution

  • You can control the direction per string by changing the dir attribute programmatically as needed:

    var text = 'קצת text בעברית'
    var canvas = document.getElementById('canvas')
    var ctx = canvas.getContext('2d')
    
    ctx.font = '24px Arial'
    ctx.fillText(text, 165, 50)
    
    canvas.setAttribute('dir','ltr');
    ctx.fillText(text, 0, 100)
       
    <div>
      <canvas id="canvas" dir="rtl" width=300 height=300/>
    </div>