Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do I make my image map resize with all its coordinates #42

Closed
rahulkpg opened this issue Feb 8, 2012 · 35 comments
Closed

How do I make my image map resize with all its coordinates #42

rahulkpg opened this issue Feb 8, 2012 · 35 comments

Comments

@rahulkpg
Copy link

rahulkpg commented Feb 8, 2012

First of all thanks for the awesome plugin. I am a engineering college student in Bangalore,India doing my internship and your plugin has saved me a lot of work.

http://jsfiddle.net/JpgYm/2/

Above is my code I'm trying to make my image map scalable so that it can be used on android devices.Its a simple game where user can select part of the image and then select the relevant option button.

I tried using the mapScale option setting it to true. I haven't used any css here.So how do I scale the image? I did read the docs but I couldn't figure it out.

Also I'm new to fiddle, I tried separating the js and html , it didn't work so I put it all together, its sort of working but its not showing the imagemap but if you copy the same code and run it on chrome or firefox, it works perfectly well(except the image scaling)

cheers,
Rahul Agarwal

@jamietre
Copy link
Owner

jamietre commented Feb 8, 2012

Here's an update to the demo:

http://jsfiddle.net/JpgYm/8/

I think this is what you want to do. mapScale is designed to automatically change an imagemap to match the size of an image that you've set in advance through CSS.

It sounds like you want to do something a little different - match the size of the image to the user's screen. You need to first detect the size and then use resize to change it. You could do this one of two ways, either before binding imagemapster and then setting the image to the correct size with CSS, at which point mapster will automatically change the imagemap to the right size. The other way is to use resize method of imagemapster to change it after binding.

The demo above uses the 2nd method, calling a function after binding (see the onConfigured option). This checks the size of the window, and calls resize to change the size. This is safer because this way you can be sure the image has finished loading. (onConfigured will not be called until the bound image is done loading). If you tried to check the size of the image before it was done loading, you might not get any data.

The math in the function finishSetup compares the width & height of the window against the width & height of the image, and scales it so that it uses the most space possible without either dimension being larger than the window. (You need to check both, because the image could be a different width/height ratio than the window).

@jamietre
Copy link
Owner

jamietre commented Feb 8, 2012

Updated the demo so the buttons work, for some reason onclick doesn't work with jsfiddle. http://jsfiddle.net/JpgYm/8/

@rahulkpg
Copy link
Author

rahulkpg commented Feb 8, 2012

Hey thanks for this I'll try it out.
Yes I do want want to resize the image and and also get the new coordinates

http://jsfiddle.net/8qLFc/4/ -here u can see how I wished my image would resize but this wasnt working once I used your plugin

@jamietre
Copy link
Owner

jamietre commented Feb 8, 2012

Oh ok - actually I have never really thought about using % scales with images, and there's no reason imagemapster can't work that way. Here's the same demo using that CSS

http://jsfiddle.net/J9nw7/4/

The only issue is how you assign the CSS (which is why it probaly didn't work for you before). This issomething I can address in the code to make it work better, because right now, though, imagemapster will lose whatever classes and IDs you assign to an image when it makes a copy. So in the link above, I bound the class with "max-width:100%" to it using a DIV wrapper to get around this.

(note - i left the "finishSetup" function in there, but it's no longer used)

@rahulkpg
Copy link
Author

rahulkpg commented Feb 8, 2012

This is just a trial code that I'm working on so please don't worry about some useless(redundant) thats there, that can all be cleared up later.
I checked( http://jsfiddle.net/J9nw7/4/ ) this fiddle but if i resize the output window the image doesn't resize along with it whereas here (http://jsfiddle.net/8qLFc/4/ )if you try resizing the window, the image scales automatically. Works likewise on chrome/firefox as well, haven't tried on other browsers.

And using %scales wasn't my idea, just something i picked up on stackoverflow, where I eventually found your plugin as well.

Off topic, I'm really surprised at how quickly you responded, totally unexpected. I respect your approach and dedication and Thank you.

@jamietre
Copy link
Owner

jamietre commented Feb 8, 2012

No problem. Try this:

http://jsfiddle.net/J9nw7/8/

The reason it didn't resize is because ImageMapster wraps the image in a DIV hardcoded with the width and height of the image. This might not be necessary (but is a legacy from how the code used to handle some other stuff) but for now that's what we're dealing with. But no big deal - in order to make it track the size of the image when the window changes, you need to capture the resize event and deal with it anyway.

First the CSS needs to be changed to "width" instead of "max-width" (otherwise it will max out at the original width). Then we capture the resize event and call 'resize' to match the new dimensions. It's a little tricky because you can't just try to resize it every time the browser says the window has been resized. This event gets called dozens of times per second -- and imagemapster would not be able to keep up.

Instead, we set a timer to check a split second later to see if the size is still changing. Once it's done, THEN we actually call the mapster resize. This is all coded above.

In the demo above I used an effect to animate the resize by setting the 3rd parameter for "resize" to be a number (this is length of time in milliseconds that the resize effect will take). If you change this:

image.mapster('resize',newWidth,newHeight,200);   

to

image.mapster('resize',newWidth,newHeight,0);   

It won't animate the image resize.

@rahulkpg
Copy link
Author

Hey there this seems to be working well. I just need to spend some time understanding how its all working. Thanks.

@jamietre
Copy link
Owner

No prob, feel free to ask if you need any further clarificaton.

@rahulkpg
Copy link
Author

Actually I reverted back to this method http://jsfiddle.net/J9nw7/4/ as it did resize but only onload which is sufficient.
The thing is I am making it for android so it should just adjust to the resolution once, the manual resize method wouldn't work as it worked only after the window was resized. But the earlier method was sufficient

Once I put it in .apk(for android app) using Titanium studio, thats when the new trouble came up, its just not working on the phone , it takes a while to select an area and then crashes if i select another map area.
The resizing is working, the mapping is working as well, because the area sections can be selected, I can't figure out why its so slow and crashing on the second selection.

This is what my code looks like right now :http://jsfiddle.net/rahulkpg/ZVGEz/

@jamietre
Copy link
Owner

Are you using the current dev code, or 1.2.4 on the android? There are a huge number of changes some of which address some issues I had found with mobile devices in the current dev code. There are also some major performance improvements in the dev code -- though with only a few areas that shouldn't make much difference.

The fiddle (your last link) actually seems to work fine for me on my Bionic (tried it in the default browser & Dolphin). Are you testing the fiddle or another web page perhaps using the older (release) code...

@rahulkpg
Copy link
Author

Hey there, sorry I have been busy with college and other stuff.

Well yes I am using 1.2.4, should I shift to the dev code and try?

I didn't actually visit the fiddle using the phone, what I did is I gave the code to someone who used Titanium Appaccelearator(http://www.appcelerator.com/) to convert it into an .apk file. Now I don't know how this works, it was done by someone else, but in essence what it does is wrap the html into an app which runs without a browser.
If you have any specific doubts about this or if you want the .apk I can give it to you.

Could it be incompatible ? because it runs beautifully on chrome so it should in turn work the same on android right ?

Also I wanted to implement drag and drop instead of a click interface, fiddle: http://jsfiddle.net/rahulkpg/5HVcu/
Initially I wasn't able to use draggable as well, i had to change my buttons to div's, draggable is now working but I can't seem to make area's droppable. Can this be done?

@jamietre
Copy link
Owner

Hi - I haven't tried it with Titanium before (actually have only become aware of its existence recently!) as I have not done much that's specifically mobile targeted, but it looks interesting and I should probably start testing. Looks like the basic version of the titanium sdk is free. I may have time tomorrow to give it a try.

I can't think of any reason why it should be incompatible with titanium, since it works fine with every other HTML5 platform, but I don't know anything about its browser implementation either, is it a proprietary browser wrapper? If it is webkit based it should work well.

You could try using Zepto instead of jquery since you are targeting only mobile browsers. Zepto is a minimal jQuery subset that is designed only to work with webkit. (That does exclude some devices, though, like Windows Mobile ones, since it really only works with webkit - doesn't even work with IE9). I just pushed an update which is tested against the current version of Zepto and everything seems well. I think it may be useful to at least test with Zepto, whether or not this works for your target audience.

To run ImageMapster with zepto you only need zetpo.js, event.js, and only if using resize, fx.js.

@jamietre
Copy link
Owner

Oh and you also need to include the zepto patch file (dist/jquery.imagemapter.zepto.js) after zepto, and before imagemapster.

@rahulkpg
Copy link
Author

Ok I'll try zepto and let you know how it works out.
and did you see this http://jsfiddle.net/rahulkpg/5HVcu/
I made the buttons draggable, now I want to make the areas of the image map droppable, is that possible?

@jamietre
Copy link
Owner

re: draggable

Well that turned out to be an interesting problem. Lucky for you I was in the mood to solve one :)

http://jsfiddle.net/jamietre/5HVcu/8/

There are a few things going on here.

Apparently, while dragging, image maps are not active (since the mouseover events do not fire). I don't know if this is because of the way draggable is implemented by jqueryUI or what, but seemed easiest to address it externally. I put in a couple functions to figure out what's going on at any point. The pnpoly function is brilliant, from here: http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html and even though it's pretty brute force it seems to be plenty fast (especially since you don't have too many areas).

Note this only works for complex polygons - though the math for rects & circles is a lot easier if you ever needed to add it.

So what I did was:

  1. On configure, create number arrays from the polygon coordinates up front for each area. Save them as jquery data.

  2. During drag events, continually check if we're in an area. Manually highlight it, if not, or unhighlight any active area, if so. If you had a big image map, this would probably bring your browser to its knees, but you could address that by only checking every 100 ms. or something instead of every single time the drag event fires.

  3. Finally, on drop, check again where we are and act accordingly.

It seems to work pretty darn well!!

@jamietre
Copy link
Owner

Actually there is a simpler way to solve the problem :-/ it's just a z-index issue.

http://jsfiddle.net/jamietre/DKLQp/1/

It's still a tad tricky because in order for the imagemap to work, the z-index of the imagemap must be higher than the z-index of what you're dragging. But then when you drop it, you have to change the z-index of the original element to be highest, or you won't be able to grab it again!

But this is a lot simpler than what I had before, anyway, and it's smoother.

@jamietre
Copy link
Owner

See blog post for a detailed explanation! http://blog.outsharked.com/2012/02/dragging-and-dropping-onto-html-image.html

@rahulkpg
Copy link
Author

Wow you did all that? Thanks again. How did you figure it out? I spent the whole of yesterday trying to get that working.
And you are right about potential applications of this.
I'll try and get the whole thing working with drag and drop and then make two versions, one using zepto and the other jQuery. Lets see how it works on android.

Oh and what do you use to get your image map coordinates. Right now I am using www.image-mapper.com

Update: My current code using your technique http://jsfiddle.net/rahulkpg/DEbLe/ , still lots of issues, especially being slow on the phone, on the upside it isn't crashing anymore,then there's resizing which isn't working very well on the phone. And they want it in landscape mode now. Will keep you updated.

@jamietre
Copy link
Owner

I just tried it on an ipad - which theoretically should not be too different from android since they are both webkit - and the dragging doesn't work at all for me. I haven't done a ton of mobile development so I'm not sure why, but apparently the standard click-drag methods of jqueryUI are no good with touch screens.

For imagemapping - I have not had to make my own imagemaps in the past for the most part, usually i've used existing geographical maps or grabbed something already there for a demo - but when I have I actually used photoshop. The last time I looked for web sites, I don't think image-mapper.com was around - because it looks easier than what I've used before.

Does the dragging part actally work for you on your phone?? I'll try on my droid later.

For the speed part - try it outside a fiddle before coming to any conclusions :) jsfiddle has a lot going on. But it probably has a lot more to do with jquery than with imagemapster , which really isn't doing anything until the highlights activate.

Perhaps jQuery mobile is worth looking at? I have never used it - not once - so I don't know if it could be just dropped in, or if there would be things I need to address. Or maybe Zepto deals with this stuff too.

Of all the problems though the resizing should be the least of them... but that one should be in our control anyway.

I'll look into this a bit more later, though i may not have a ton of time today, lots of meetings.

@rahulkpg
Copy link
Author

Hey there,
no the drag and drop does not work yet but this:http://furf.com/exp/touch-punch/ should make it work. Working on it now, but its overtime already for me so I don't think I'll finish much either today.
UPDATE: Using touch-punch(just had to include the file after the other scripts,that was causing the problem) drag is working, but it isn't dropping onto the image where it should. On dragover the image area isn't getting highlighted, if i click an area(which highlights it) and then drag and drop the correct option it works.

And the resizing is actually just a problem because I don't really know css that well.
Can use something like this: http://webdesignerwall.com/tutorials/responsive-design-with-css3-media-queries
The thing is if I explicitly change the % of img to anything below 100 the image doesn't remap coordinates, like in my code if I make
#wrap img
{
max-width: 50%;
height: auto;
}
The image will resize to 50% but the image map will stay where it is, I am guessing this is because the imagemap areas like you showed in your layer diagram in yesterday's blog post is a separate image if I understood correctly.
And i never use jsfiddle to test it or anything, thats just to share it here. The speed is awesome on the browser but its really slow on phone

@rahulkpg rahulkpg reopened this Feb 17, 2012
@jamietre
Copy link
Owner

Hey just catching up on this, the next few days are looking really rough so I am probably not going to have much time, but I will try to at least answer questions.

@rahulkpg
Copy link
Author

Hey there,
You've been busy, I was a little unwell myself so I couldn't reply earlier.

As of now

  1. scaling issue is solved- all I had to do is set the viewport.

2)Speed on the phone is now fine, don't know what the problem was(I installed a new ROM maybe that was the issue,though I doubt it)

  1. Drag and drop works using the touch punch plugin which maps the mouse commands to touch commands, earlier it was not working because the dragging and dropping functions were bound to mousedown, mousemove and mouseup

The problem is that on dragging the buttons over the target area, the highlight does not appear on phone, it works on browser but not on phone, I have updated the fiddle, can you take a look ?
What I figure is that the highlighting of an area is also configured to mouseover and I need to bind that to touch as well somehow.

UPDATED FIDDLE:http://jsfiddle.net/rahulkpg/DEbLe/4/

@jamietre
Copy link
Owner

Well that sounds like a ton of progress. I am likely not going to have any time at all today but should have a chance tomorrow if not.

@rahulkpg
Copy link
Author

Hey if you have some time could you please look into this issue of highlighting on dragover on the phone.

@jamietre
Copy link
Owner

Hey I am still slammed at work. But I actually had an idea about why this is happening, and it's stunningly simple if it works.

ImageMapster detects mobile devices and disables the "mouseover" event by default since (not being a mobile developer) this seemed to be sensible. Normally when you would touch an area it would fire mouseenter and click at the same time, causing slowness and sometimes other problems.

I bet if you just reenable it it will work. It may cause problems again when not dragging - and there is probably a good way to deal with this in the big picture (e.g. instead of just disabling mouseover for mobile devices, I can check if dragging is active and enable it only then) but try this first.

Just add an option:

highlight: true

If that has no effect try adding it explicitly to "render_highlight" e.g.

render_highlight: {
highlight: true
}

(You shouldn't have to do that but I just noticed the default option is in the wrong place and it might not work as a global option).

Let me know if that changes anything. This should have no effect on non-touchscreen devices.

@rahulkpg
Copy link
Author

Well I already tried highlight:true after reading your documentation but it didn't make any difference on the phone or otherwise.

Now I tried adding it explicitly as you said and it still didn't make any difference.
I still haven't figured why this issue exists,it may be because of the way mouse events are bound to touch events or the way the highlight function is working right now because adding any highlight options don't seem to be causing any effect. I can't seem to disable highlighting either.(explicitly or the default option)

This is the updated fiddle if you need to take a look at my code:
http://jsfiddle.net/rahulkpg/DEbLe/

@jamietre
Copy link
Owner

FYI I updated the fiddle to use the latest dev release. I don't think there's antyhing specific to this issue that I changed but you never know.

http://jsfiddle.net/DEbLe/10/

btw I just tried this on my android, and I can't drag at all. Is the fiddle supposed to work or does this need to be built in titanium to test on mobile device? I really know very little about mobile targeted apps!

@rahulkpg
Copy link
Author

Ok I have sent you an email, take a look when you can. maybe its an issue with jsfiddle.

It doesn't have to be built to be tested, titanium or phonegap just creates a wrapper to create an apk.
the html, css, jquery behaves exactly the same way as it would by opening the html file.

@rahulkpg
Copy link
Author

Is there any other way that I can get the position/ id of the area where the button is dropped?

There is a jquery function droppable which we are using for the image but I couldn't use it on the individual image map areas because they all pointed to the top-left corner of the entire image.

EDIT: I just looked up this thread and realized maybe I can use the pnpoly function and that method of implementation since that works as well.

@jamietre
Copy link
Owner

How are you doing with this? I got slammed at work, but have emerged.

The pnpoly method could be optimized a lot - that is, you could build a set of rectangles around each area up front and use that to dramatically narrow down the areas you need to check with pnpoly. This should be plenty fast enough even for an android because you shouldn't often have more than a few rectangles bounding areas that overlap within a single point. Maybe it's fast enough even as it is now for you since you don't have too many areas, too.

But this might be the way to go for your situation, it sounds like the browsers can't deal with the layers needed to support dragging and the image maps.

@jamietre
Copy link
Owner

I think this would be really difficult to do effectively. You'd basically be doing pnpoly twice, once for the area being dragged, once for the hotspots. Then what would you do if the thing being dragged was touching more than one area? You are not just dealing with a single point for the mouse any more, you're dealing with the intersection of two areas. Even if you could do all the math right I am not sure it would be a good user experience, since whatever your dragging is bigger than the areas themselves, it would be hard to know which area to highlight.

This is getting into video game kind of math, sprite collisions and so on. I'm sure there are libraries to help but I doubt it's worth all that overhead for dragging and dropping.

@rishiphp
Copy link

rishiphp commented May 1, 2012

thanks bro, is this possible to achive above action by measuring xy cords of both part as well label..?
Can means pls explain how..?

@jamietre
Copy link
Owner

jamietre commented May 1, 2012

I just don't know how you would do it. You need an algorithm to figure out where a set of shapes intersect. I've never done anything like that before. Like I said you might try looking at libraries used for video games. But this is definitely outside of my area of expertise.

@rishiphp
Copy link

hi bro, i done above action using "document.elementFromPoint(x, y)".

http://jsfiddle.net/DEbLe/16/

please look at this and say any thing wrong or any thing to improve.

@jamietre
Copy link
Owner

Hey I'm closing this now - it's been open forever and I think we've moved on to new issues :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants