I have a HTML5 canvas application drawing some shapes (using KineticJS at the moment). I want to show a popup menu whenever a user hovers over a shape.
The menu should look reasonably similar to an ordinary right-click popup menu, but I would prefer if it had some rich text formatting capabilities (e.g., some menu items are another color or bold), and it doesn't have to be on the right-click (just appearing when hovering is fine).
Each of the shapes can have a different number of elements in the popup menu (thus menus are of flexible height), and each element can be a different text length (thus having a different width). The elements being individually clickable is an optional extra.
While I'm sure I can hand-craft such a functionality with some effort (calculating font metrics for all the texts, drawing rectangles and texts to present each element, etc.), that seems re-inventing the wheel, I'd like to use some existing library to do this (or at least help with the layout).
For now, I've looked at:
Some proper native KineticJS way to do this (or at least help with layout) - haven't found one so far, as far as I see I'd have to calculate fontmetrics, layout sizes, and then setting all coordinates for text / formatting rectangles manually.
ZebKit - but I'm not sure if ZebKit and KineticJS will play nicely together on one HTML5 canvas.
html2canvas - in order to render a menu as HTML fragment to an image, then render it back onto the canvas; but it doesn't seem to work with hidden/off-screen HTML fragments.
Other HTML5 frameworks, e.g., EaselJs, Paper.js - none seemed to offer such functionality
htmlcanvas - abandoned 4 years ago
rasterizeHTML - looked very promising, but didn't work right under Chrome for me.
Moving away from HTML5 Canvas and just doing very fancy CSS drawing using something like JsGraphics instead, and then use something like jQuery UI or any of the proper HTML frameworks for this instead. That would seriously limit the other functionality of my application, just for the sake of the menus being easier.
Generate a dynamic SVG, render using canvg - still have to calculate the layouts manually for the SVG, and it doesn't seem like the right tool for the job
GWT + LibGDX + TWL - seems very complex and quite an overkill
A related (though more generic, as it focuses on abstract HTML, but in my case anything structured that ends up looking as a popup menu would do) SO question is this one:
Am I missing some relatively easy standard solution to this?
Edit - rasterizeHTML still seems somewhat promising but I'm getting:
Uncaught SecurityError: An attempt was made to break through the security policy of the user agent. [VM] kinetic-v4.7.2.js (521):7621
Kinetic.Util.addMethods.getIntersection [VM] kinetic-v4.7.2.js (521):7621
Kinetic.Util.addMethods.getIntersection [VM] kinetic-v4.7.2.js (521):7196
Kinetic.Util.addMethods._mousemove [VM] kinetic-v4.7.2.js (521):7294
(anonymous function)
Unable to get image data from canvas because the canvas has been tainted by cross-origin data. [VM] kinetic-v4.7.2.js (521):7
Kinetic.Util.addMethods.getIntersection [VM] kinetic-v4.7.2.js (521):7621
Kinetic.Util.addMethods.getIntersection [VM] kinetic-v4.7.2.js (521):7196
Kinetic.Util.addMethods._mousemove [VM] kinetic-v4.7.2.js (521):7294
(anonymous function)
... when doing something like ....
result.popupMenu = new Kinetic.Shape({
drawFunc: function(context) {
var subCanvas = renderToCanvas(578, 200, function(canvas) {
rasterizeHTML.drawHTML(result.popupMenuHtml, canvas, {}, function(image) {
context.drawImage(image, 0, 0);
});
});
});
Basically it looks like the rendered image is considered as unsafe and thus corrupts the whole context, and KineticJS is unhappy about that.