views:

1344

answers:

7

Any suggestion is highly appreciated.

+1  A: 

canvas is just a drawing surface. You render and the result is pixels. So, you'd need to track the positions of all text you have rendered to the canvas in a some kind of data structure which you'd process during mouse events.

Scott Evernden
+1  A: 

If you need to have selectable text it would be a lot easier to just create a div or whatever, and position it on top of the canvas where you want the text to show.

canvas does not have any built-in mechanism for selecting text, so you would have to roll out your own text rendering and selecting code - which can be rather tricky to get right.

Jani Hartikainen
+2  A: 

Hello, the text drawn in canvas elements cannot be selected, because of the nature of the canvas tag. But there are a few workarounds, like the one used in typefaceJS.

Another solution would be to add text with positioned div elements instead of useing strokeText or fillText.

Fabien Ménager
+3  A: 

You may get some ideas from Bespin.

They implemented a text editor in javascript using canvas with text selection, scroll bars, cursor blinking, etc.

Source Code

andre-r
+1  A: 

A simple answer would be: either use HTML or SVG instead of canvas. Unless you really need the degree of lowlevel control canvas offers.

Erik Dahlström
+7  A: 

Text selection has many components to it some visual, some non-visual.

First, make text selectable you must keep an array, of where the text is, what the text is, and what font was used. You will use this information with the Canvas function measureText.

By using measureText, with your text string, you can identify what letter the cursor should land on when you click on an image.

ctx.fillText("My String", 100, 100);
textWidth = ctx.measureText("My String").width;

You will still have to parse the font height from the "font" property, as it is not currently included in text metrics. Canvas text is aligned to the baseline by default.

With this information, you now have a bounding box, which you can check against. If the cursor is inside of the bounding box, you now have the unfortunate task of deducing which letter was intentionally selected; where the start of your cursor should be placed. This may involve calling measureText several times.

At that point you know where the cursor should go; you will need to store your text string as a text string, in a variable, of course.

Once you have defined the start and stop points of your range, you have to draw a selection indicator. This can be done in a new layer (a second canvas element), or by drawing a rectangle using the XOR composition mode. It can also be done by simply clearing and redrawing the text on top of a filled rectangle.

All told, text selection, text editing in Canvas are quite laborious to program, and it would be wise to re-use components already written, Bespin being an excellent example.

I'll edit my post should I come across other public examples. I believe that Bespin uses a grid-based selection method, possibly requiring a monospaced font. Ligatures, kerning, bi-directionality and other advanced features of font rendering require additional programming; it's a complex problem.

Charles Pritchard
Yes, Bespin requires a monospaced font.
devongovett
A: 

I'm facing the same problem and I'd rather stick with canvas for a block of text selection and movement (relocation within the canvas) and leave other elements intact. Not sure the div elements would play out well... would the DIVs automatically converted into the canvas bitmp? or another job to do the conversion? tia.

Don Don