PDA

View Full Version : Image Map / Hotspot Library


mjessup
02-05-2009, 10:45 AM
In response to one of the help questions I have created a library for a simple (but I believe versatile) set of classes for creating image maps / adding hotspots to a view.

The attached zip contains the library plus two examples. The files are:

1. imagemap.lzx: The library classes
2. DrawView.lzx: A simple example that creates some hotspots on a view and draws them using drawview
3. DrawView.xml: The shape data used by DrawView.lzx
4. Map.lzx: An image map example, that creates hotspots on a loaded image resource.
5. Map.xml: The hotspot data for Map.lzx
6. northeast.jpg: The image resource used by Map.lzx
7. MapZoom.llzx: An Image example with a clickable hotspots that will display a subview. Illustrates suspend and resume.

I have created/tested the examples using LPS4.1.1 in both swf8 and dhtml, and have not encountered any problems.

About The Library

The library contains four classes. The first is "hotspot". This class is a general interface contract class for use by the library. It specifies any hotspot class must define three methods:

1. contains(x, y): true if the hotspot contains the given x, y coordinate, false otherwise
2. doActivate(): called when a hotspot is activated.
3. doDeactivate: called when a hotspot is deactivated.

The next two classes are implementations of Hotspot. The first "polygonhotspot" implements an N-sided polygon. It contains four additional methods in addition to those defined by hotspot:

1. addPoint(x, y): Adds a new point to the path that describes the polygon
2. clearPoints(): Clears all points in the polygon
3. getNumPoints(): Returns the number of points describing the polygon
4. getPoint(n): Gets an object with an 'x' and 'y' attribute for the Nth point in the polygon (or null if n is out of range)

This class is used by first constructing the object and then making consecutive calls to addPoint for each point in the polygon.

The second implementation of Hotspot is "circlehotspot". This describe a simple circle with three numeric attributes:

1. x: The x coordinate of the center of the circle
2. y: The y coordinate of the center of the circle
3. radius: The raidus of the circle

The final class is "imagemap". This is the image map itself. It will attach itself to the parent view in which it is created, and then activate or deactivate its hotspots as the mouse passes in or out of them. The public members of the class are:

1. exclusive: A boolean attribute. When true only one hotspot controlled by the map may be active at any given time. If false multiple hotspots may be active at once (if hotspots overlap).
2. addHotspot(spot): Adds the given spot (implementation of "Hotspot") to the list of those controlled by the map.
3. clearHotspots(): Removes all hotspots from the map.
4. suspend(): Suspend activity by the map. The activation state of the hotspots will not change until resume is called.
5. resume(): Resume activity by the map. Checking will resume and all spot states will be updated.

The Example Programs

The first example "DrawView.lzx" will load a set of hotspots and then draw them. This example illustrates what a hotspot looks like in terms of its bounds and can also be used to view how chnaging the exclusive attribute of ImageMap effects the behavior as some of the hotspots overlap.

The second example "Map.lzx" is an example of creating something along the lines of a traditional HTML image map. This uses a picture (of the NE U.S.) as a resource and then creates hot areas on it (one for each state). As the mouse moves over each state it will display the states name (note for the sake of time the hotspot boundaries are a little crude).

The final example "MapZoom.lzx" is an extension of the second. In addition to its behavior when you click on a hotspot a subview will appear and map detection will be suspended. When the subview is closed the map detection is resumed.

Both of these examples also have further subclasses of those defined in the library showing how doActivate and doDeactivate can be overridden. They also contain code illustrating loading hotspot data from a dataset.

Two final notes about using the library. First as can be see in the example code, the view with the hotspots must have clickable="true". In addition if you create a subview over the hostspot view with clickable regions it may interfere with the detection of mousein/mouseout events, therefore if you want something clickable to appear I suggest either you suspend the map until the subview is destroyed, or have the subview "stay out of the way" of the mouse.

I have tested the examples using LPS4.1.1 and LPS4.2.0. They all seem to work, except DrawView.lzx in LPS4.2.0 compiled as DHTML (though I think this may be a problem with drawview in DHTML), everything works in SWF8/9 and the other examples work in DHTML.

You are free to use this code for any purpose, though if you create a subclass of Hotspot for another shape it would be appreciated if you share the code. I would also be interested to hear any comments about this library (is it useful? have you found bugs?).

brknindexfinger
04-04-2009, 09:54 AM
Hi Mjessup, and thank you very much for this library.

I'm looking for a way to create some elearning interactions, deployed solo as swfs. I'd like to retool map.lzx to place a single rollover hotspot over an image and make another version to place an invisible click hotspot.

I'm an openlazlo noob, and trying to learn fast. I'd like to know if you might have any ideas for making these changes:

1) Is there any way to modify the text object that is displayed? By adding a border, for example? I found that I can modify the text attributes by adding some attributes to the oninit handler:


<handler name="oninit">
this.__popup = new LzView(parentView, {'visible': false, 'bgcolor': 'white', 'fontsize':'12', 'fontstyle':'bold' });
new LzText(this.__popup, {'text': this.text});
this.__followDel = new LzDelegate(this, 'follow');
</handler>


But there doesn't seen to be any way to add some padding to the text object or add a border. (Maybe my thinking about this is too "flash"?)

2) I'd also like to create another version of map.lzx that displays the text on a click event, instead of on a mouseover. I've determined that I need to change some of the library elements to make this work, possibly writing a new js function for the imagemap class, but not quite sure how to make the changes. If you have the time to give me any pointers, I'd be extremely grateful.

Best,
brknindexfinger

mjessup
04-06-2009, 04:31 AM
Hi brknindexfinger,
I'm a little unclear what you mean with your first question about being able to "place a single rollover hotspot over an image". If you would just like to have a single image object be clickable then the hotspot library isn't necessary. You can just create a view with an image resource, set its "clickable" attribute to true, and listen for mouse events. You can do it with the library, but it would be overkill. The intent of the library is to handler either complex shapes or multiple areas within a view that aren't independent within the flash/laszlo model. Generally if you want to have something occur for an entire view and are using rectangular areas "clickable=true" and event handlers should do the trick most of the time.

Your other two questions require some fairly simple modifications (once you have had a chance to learn laszlo of course). For the first about changing the way the text appears; you can create your own class for the popup view instead of the simple LzText in Map.lzx. This is shown in "BorderPadPopup.lzx" in the examples. Here I have defined a class (lines 9-34) that uses four extra views to create an outline border around the text, and some constraints to have a constant padding between the border and text. Then it is a matter of creating an instance of that class for the hotspot popup (lines 54-56). I left the original code so you could see where I made the change.

Your second question about showing the popup on a click event does not require modification to the library and can be done by adding a level of indirection. This is in the example "ClickMap.lzx". The trick here is to use the "doActivate" and "doDeactivate" methods to modify a listener. First define an extra delegate that can be registered for mouse clicks (lines 14,20-22), and a method for it to invoke to show the view (lines 25-35). Then modify the doActivate method so that instead of showing the view it registers the listener (lines 37-41). With the delegate registered the mouse clicks will invoke the delegate, which will in turn display the popup. Finally in doDeactivate in addition to hiding the view, remove the listener (line 48).

Both examples (based on Map.lzx) are in the attached zip, and require the library code from my first post in this thread (not in this zip). I have tried these using LPS4.1.1 in both SWF and DHTML without problem. As an FYI I have donated the hotspot code to laszlo and as of the latest release (4.3) it is included in the incubator.

Finally, as you said you are new to laszlo, and having taught myself laszlo over the last year, in my opinion things made the most sense when I first understood the basic declarative structure of the language (views, nesting parent/child relationships) and layouts, then constraints, then delegates and databinding. The last two for me took the longest to grasp fully (I am still working on some of the finer points of databinding), but in my opinion are what give laszlo its power and let you create the most interesting apps.

Let me know if you have any questions about these two examples or anything else about using the library.

brknindexfinger
04-20-2009, 05:56 PM
Hi mjessup,

Thanks for this helpful response. You were right that the imagemap was overkill. In fact, it's far easier to add a click-sensitive object to the canvas using a handler and setAttribute(). Slowly but surely. :)

Best,
-brkn

brknindexfinger
04-21-2009, 11:31 AM
Hi there, mjessup. I have one more stupid question about the class library. Can you deploy solo when your .lzx is importing a class library in another .lzx file? I know that images used by views in an .lzx get "baked in" to the swf. Is it the same for an imported class library? Or does SOLO deploy require that the class library be in the original .lzx file, and not imported?

Best,
~brknindexfinger

brknindexfinger
04-21-2009, 03:11 PM
Never mind. I figured it out. Thanks again.
http://www.openlaszlo.org/lps4/docs/developers/program-structure.html#d0e30455

Alex__19
04-29-2009, 01:40 AM
[QUOTE=mjessup;42051]In response to one of the help questions I have created a library for a simple (but I believe versatile) set of classes for QUOTE]



HI it is Useful !!!

SENKS a LOT

Is it possible add "text1" and "text2" fild то XML file, and show it in zoome mod(for example)?

Why dataset? not remote data set? (need recompil if XML file chenched)

mjessup
04-29-2009, 02:47 AM
Hi Alex, I'm glad you have found the library useful. I'm not sure I fully understand what you mean with your first question about

Is it possible add "text1" and "text2" fild то XML file, and show it in zoome mod(for example)?

You can certainly add another attribute to the XML (or use a completely different sturcture than I did, or even some other mechanism of your own invention to configure the map), and then alter the view or the behavior of the mouse over, or add a click event as in the file "ClickMap.lzx" in the second set of examples I posted.

As for your second question the use of a compiled dataset for the examples was arbitrary. You should be able to just as easily use a remote dataset. You would just need to use appropriate logic to configure the library with the "onload" of the dataset, as opposed to my example which does the configuration during the oninit, since the dataset is compiled in and available immediately.

Let me know if I have misinterpreted your questions or the above explanations are unclear.

Alex__19
04-30-2009, 01:17 AM
You can certainly add another attribute to the XML (or use a completely different sturcture than.

Hi
i added new attribute to the XML, ALL work OK
senks
sorry for my english.
Alex