Hi to all, this is a related Firefox problem.

I have a menu in which is applied script.

Typeface 0.11 version doesn't support hover on links. There is an experimental version but doesn't work very well for me, so i tried to implement hover by myself.

Problem is: hover works pretty well changing canvas context property fillColor and then calling fill(), but the stroke on hovered voice remains on another color.

Difficult to explain, so i put some test code online:

As you can see, passing with mouse on the menu voices triggers the hover and the element change, but remains bordered in red.

I tried in many ways, without success.

The core of the hover is this:

var ctx = vectorElement.getContext('2d');


if (ctx.fillStyle.toUpperCase() != '#DF1C1C') { //control if it's already in that color

   ctx.fillStyle = '#DF1C1C';
   //ctx.strokeStyle = '#DF1C1C';   //tried this to change the stroke style                             

   //ctx.clearRect(0, 0, 1000, 1000); //tried this to clean the rectangle

   ctx.fill();
   //ctx.stroke();  //tried this to repaint the stroke                          
}

Any ideas?? Thanks in advance to all!

Dani AI

Generated

Short diagnosis: the canvas is immediate-mode — once a pixel is painted it becomes pixels, not an object you can “recolor”. Changing fillStyle and calling fill() will only draw the current path; previously stroked pixels remain until you erase them and redraw. That explains why the old red outline sticks around. (jenkov.com)

Practical rules to fix the hover reliably:

  • Clear the exact canvas area you must update (coordinates are in the canvas coordinate space; 0,0 is the canvas top-left). For a full clear use ctx.clearRect(0,0,canvas.width,canvas.height). After clearing, call ctx.beginPath() before drawing the new shape so old paths do not bleed into the new drawing. (developer.mozilla.org)

If you are using Typeface (or excanvas/VML fallbacks), confirm you are actually targeting the canvas that holds the pixels: the HTML inside <canvas> is fallback content for non-supporting browsers and will not be erased by clearRect. Inspect the DOM in devtools to see whether the library created extra elements or multiple canvases — clearing one canvas won’t affect siblings or DOM text. (developer.mozilla.org)

Minimal redraw pattern (adapt and call the library’s render for that glyph if available):

var canvas = vectorElement;
var ctx = canvas.getContext('2d');

ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
// re-run typeface renderer for this canvas or recreate the path here
ctx.fillStyle = '#DF1C1C';
ctx.strokeStyle = '#DF1C1C';
ctx.fill();
ctx.stroke();
ctx.restore();

Alternatives: render static text once to a base canvas and put a second overlaid canvas for hover highlights (absolute stacking). That way hover updates only touch the small top canvas and avoid full re-renders. For friendly performance also debounce the hover and use requestAnimationFrame for redraws. (developer.mozilla.org)

References above show the clear/ redraw pattern and the beginPath requirement; verify which DOM nodes the typeface script created before changing only one canvas.

Recommended Answers

All 5 Replies

no canvas experts here? :P

Is it possible to redraw the canvas on however, or is that too slow?

Is it possible to redraw the canvas on however, or is that too slow?

thank you for the answer!

anyway it's not possible because it becomes too slow (and the resulting effect is that some event like mouseout is lost at random time).

I think the best way to resolve my problem could be "cleaning" the canvas area, but i found only the "clearRect" method: seems that it doesn't work.

The definition is

clearRect (x, y, w, h)

, with

x,y

as the top-left point of the area and

w,h

width and height of the rectangle.

I don't understand if the top-left point (starting point) is referred to the area itself (so 0,0 is the starting point), or it's referred to the document / viewport.


Any hint on cleaning that area? Or what coords i have to pass into clearRect function??

thank you for the answer!

anyway it's not possible because it becomes too slow (and the resulting effect is that some event like mouseout is lost at random time).

I think the best way to resolve my problem could be "cleaning" the canvas area, but i found only the "clearRect" method: seems that it doesn't work.

The definition is

clearRect (x, y, w, h)

, with

x,y

as the top-left point of the area and

w,h

width and height of the rectangle.

I don't understand if the top-left point (starting point) is referred to the area itself (so 0,0 is the starting point), or it's referred to the document / viewport.


Any hint on cleaning that area? Or what coords i have to pass into clearRect function??

I'm sure it would be relative to the canvas object. Wouldn't make any sense otherwise.

I'm not too familiar with canvas. I think I read somewhere that it isn't possbile to edit/manipulate elements, but thats something to validate. I remember it was mentioned SVG as a better alternative if you wanted to edit stuff. (Actually I distinctly remember looking at some source code that had to cache canvas objects in order to support an undo property. So I'm pretty sure you cannot edit canvas elements).

I think you could get away with drawing two canvas elements up front. Once for hover, and non-hovered. Then just use display:none;

For hover, its more efficient if you put in a timeout. The timeout would trigger the hover change, after say 100 millisecs. If the user un-hovers, then just cancel the effect. That is a lot more efficient then immediate changes, and more fluid.

BTW: you can get canvas working in IE with excanvas.
http://excanvas.sourceforge.net/

Though in my experience (2-3 years or so ago) it doesn't work with objects created after the DOM rendered. You have to hack it to re-parse the DOM after you create a new Canvas. Hopefully thats fixed now.

Thank you for answer again!

[...]
For hover, its more efficient if you put in a timeout. The timeout would trigger the hover change, after say 100 millisecs. If the user un-hovers, then just cancel the effect. That is a lot more efficient then immediate changes, and more fluid.

Yes it's already so with timeouts, if you look at the first "test code".

BTW: you can get canvas working in IE with excanvas.
http://excanvas.sourceforge.net/

Seems a joke but in IE with vml it works almost perfectly! =)
Anyway ExCanvas is a very good option, I already use it for other things.

Though in my experience (2-3 years or so ago) it doesn't work with objects created after the DOM rendered. You have to hack it to re-parse the DOM after you create a new Canvas. Hopefully thats fixed now.

The facts are that you can change canvas object properties and "redraw" without remove the DOM element:

as I posted in stackoverflow,

i don't explain myself this behaviour: i have done a test file with a canvas object ().

Here i've put a form in which dimensions for clearRect can be sended through the form. When you trigger mouseover on the canvas (NEWS), it applies clearRect with that coords. On mouseout he refills.

Starting values are :

x = 0, y = 0, w = 200, h = 200. Notice that doesn't work.

Then try something like

x: -10000, y: -10000, w: 50000000, h: 50000000 => it seems a joke but this works!

With other values it goes partially cleared.

Someone answer me this:

Your NEWS text appears to be a child of the canvas, and you are trying to use the draw operations to affect it. Don't do that, the behaviour is undefined; canvas should never have children. Either draw the text into the canvas or overlay an opaque canvas over the text using absolute positioning

I've tried removing the text inside canvas, but it continues to work only with that non-sense values and stroke() doesn't work too.

I think that maybe there not must be text inside the canvas element when i create it, but this is a typeface action.

In conclusion, i can't get rid of it. The only way is use

clearRect( -10000, -3000, 50000000, 50000000);

So weird!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.