Clearing a Polygon on mouseout
Asked Answered
C

1

3

I have the following to draw a polygon on a canvas when the mouseover event fires:

      $(document).ready(function() {

        $('#flam').mouseover(function() {

        context.fillStyle = '#f00';
        context.beginPath();
        context.moveTo(98,265);
        context.lineTo(197,240);
        context.lineTo(197,235);
        context.lineTo(227,220);
        context.lineTo(242,220);
        context.lineTo(245,209);
        context.lineTo(252,208);
        context.lineTo(252,200);
        context.lineTo(274,179);
        context.lineTo(277,179);
        context.lineTo(290,166);
        context.lineTo(191,72);
        context.lineTo(164,97);
        context.lineTo(166,112);
        context.lineTo(94,129);
        context.lineTo(105,170);
        context.lineTo(72,177);
        context.closePath();
        context.fill();

            $('#flam').mouseout(function() {
               //What do I need to do here to clear this on mouseout

            ;})
        ;})

Or is there another more efficient way to do this

Cromorne answered 28/9, 2013 at 21:49 Comment(8)
what do you mean by 'clear' : have the polygon drawn in black, or have the previous content restored ?Demilitarize
when the use mouseovers the area it draws that polygon, when the mouse leaves it i want the polygon to no longer be there so yes have it restored to how it was before. also should I be using mouseenter/leave instead?Cromorne
First tell us if a) you have a way to re-paint the whole canvas or b) you build the canvas step by step and have no way to re-paint it all. ??Demilitarize
Build step by step for multiple areas. I am just starting out with this.Cromorne
I added a click event now as well because I need it to save the region that is clicked but when the mouse leaves it clears it how do i remove the mouseout function when it has been clicked? use jquery to remove the identifier?Cromorne
Is it one or several areas that can be selected ? just a draft : You need to handle an object, selectedArea(s), that will store the id(s) of the selected area(s) (selectedArea[id]=true), then, in the mouse out, after clearing the canvas, re-draw the selected area(s).Demilitarize
Only one at a time may be slectedCromorne
Well, i think i answered enough for now, SO is about local issue solving, not building whole solution ;-) Please mark my answer as acccepted, And if you want you can hire me to build or help you to reach your goal. In any case good luck for your project.Demilitarize
D
6

Ok so my answer changed completely :-).

What you need to do :
- set a canvas on top of the image.
--> use for both canvas and image : position:absolute; top:0px; left:0px;
- in order to have IE working (thx to @Kerry Liu's comments), it seems you cannot ignore mouse events on the canvas in IE, so set another empty image on the canvas+image, and hook the area on this latest image.
- add a class to all your area to be able to select them. I choose 'mapPart'.
- Hook an event that will draw the polygon on canvas on mouse
over for all mapParts.
- Hook an event that will clear the canvas on mouse out for all mapParts.

http://jsfiddle.net/gamealchemist/cmKsD/

(using jQuery 1.9.1)

(Credits to this answer from @enhzflep from whom i stoled the polygon drawing :-)
here : How to apply Hovering on html area tag?
One might want to handle other area types as he does. )

html (extract) :

<div id='myImage' class="map">
    <img src="http://www.linkparis.com/images/francemap.jpg" border="0"  
         style='position:absolute; top:0px; left:0px;' />
    <canvas id='myCanvas' height='494' width='494' style='position:absolute; top:0px; left:0px;'>Canvas is not supported by your browser.</canvas>
    <img border="0" usemap="#imgmap" style='position:absolute; top:0px; left:0px; width:100%; height:100%; ' usemap="#imgmap" />
</div>
<map id="imgmap" name="imgmap">
    <area shape="poly" id="flam" class="mapPart" coords="98,265,197,240,197,235,227,220,242,220,245,209,252,208,252,200,274,179,277,179,
        290,166,191,72,164,97,166,112,94,129,105,170,72,177" />
    <area shape="poly" id="ancaster" class="mapPart" coords=" 198,240,97,265,103,274,232,334,254,263,251,261,251,243,243,245,240,235,
        229,240,229,240,222,240,216,244,213,237" />
....

Code :

var cv = document.getElementById('myCanvas');
var context = cv.getContext('2d');

context.clearRect(0, 0, cv.width, cv.height);

$('.mapPart').mouseover(function () {
    var coordStr = this.getAttribute('coords');
    // draw
    drawPolygon(context, coordStr);
});

$('.mapPart').mouseout(function () {
    // clear
    context.clearRect(0, 0, cv.width, cv.height);
});

function drawPolygon(hdc, coOrdStr) {
    var mCoords = coOrdStr.split(',');
    var i, n;
    n = mCoords.length;

    hdc.beginPath();
    hdc.moveTo(mCoords[0], mCoords[1]);
    for (i = 2; i < n; i += 2) {
        hdc.lineTo(mCoords[i], mCoords[i + 1]);
    }
    hdc.lineTo(mCoords[0], mCoords[1]);
    hdc.stroke();
}
Demilitarize answered 28/9, 2013 at 22:28 Comment(18)
I would like to upvote but dont have the rep yet :D But I already have a canvas and the #flam id is from a area within a map already does this make a difference in how I would go about this? Such as is there a way I can grab the coordinates of the <area> tag and draw the polygon that way as well?Cromorne
I never used area, but afaik it is meant for images, not canvases, right ?Demilitarize
sorry I guess I should have mentioned that it is when a user hovers over an image of a map eg city lines of a state. that city needs to be highlighted by a polygon drawn on a canvas, and mouse out it clears. but i am guessing if it has the id of what is being used it should work the same possiblyCromorne
so when does the canvas come in action ? is it located on top of the image ? This might raise some issue for detection, i don't know. While googling for area i found this answer that might quite be of help to you : #12661624Demilitarize
Now we should be pretty close to the answer.Demilitarize
Yes very close I just need to understand better whats going on and be able to write it myself but that wont be too much work :D thank you very much for your helpCromorne
@Demilitarize You may want to find an alternative for pointer-events. They aren't supported in IE.Orlan
@ Kerry Liu : i didn't know that. Do you have a clue ? Re-sending the events might be a solution, but simpler would be better.Demilitarize
@Demilitarize I can think of two options: test for elements at a given point: gist.github.com/gwwar/2166393. Or add an invisible element on top that will receive your mouse events, and add an in-memory model of the bounding boxes you're interested in. Test for collisions. If you want to get fancy you can use something like a Quadtree But if the op doesn't care about IE support your solution will work fine.Orlan
quadtree are nice, but would just be an overkill to handle 5-50 items in a quiet application. I just had this idea : how about setting an empty image on top of the image+canvas, and have the areas bound to this empty image. So we don't need to use pointer-events. I tested it on Chrome and it works, unfortunately i cannot test it on IE which i don't have on my mac. Fiddle is here if you fancy have a try : jsfiddle.net/gamealchemist/cmKsD/3Demilitarize
@Demilitarize Yup it's overkill, but that's what happens when you write this stuff from scratch. Jamie, you may want to look into canvas frameworks like KineticJs which handles canvas events for you.Orlan
I mean by overkill that having a O(n) algorithm that just iterates the areas is just fine for a small n, especially in javascript which has a quite high overhead for arrays/recursion. Yes, KineticJS is fine, createJS is also a candidate. Would you mind testing my latest attempt on IE ?Demilitarize
yup im going to look into as much as possible thanks for the help guysCromorne
@Demilitarize works in my Win7/IE10 image if you downgrade jQuery to 1.9.1Orlan
Thx. I don't know well enough jQuery to know about 1.9 vs 2.0 but the solution seems find now for our friend Jamie :-)Demilitarize
Ok so i edited the post to put this last solution -even if my interest for I.E. is... moderate...- :-)Demilitarize
@Demilitarize jQuery 2.0 drops support for older browsers. It's probably just a bug or IE10 doesn't count. Anyway +1. Sorry for the nits. :)Orlan
Don't be sorry : even if it's between 5 and 20 times slower, some unaware people or company keep on using this rotten browser so...Demilitarize

© 2022 - 2024 — McMap. All rights reserved.