Information:
The images have large transparent sections, so each must be overlapped to create the needed effect. Specifically, the clickable portions of each image are in weird trapezoid shapes meant to be pressed up against each other.
Images have image maps with large portions being overlapped by the transparent portions of other nearby (trapezoid) images. I don't expect any change in z indexes will solve this...
Combining the image files into a larger single one to overlay a single image map for each section seems less than ideal, especially since I may need to re-order or rename them later and such. Never mind hover animations and other possibilities down the road.
What would be the best workaround?
Alright, after much tinkering I think I've found a solution: I just took a 1px transparent gif, scaled it up to cover the whole area (with a higher z-index, of course), and then mapped the image map polygons within that. Seems to work.
Related
I need to set up a clickable image system for dynamically created content. The image consists of a background image, and several grey-scale mask images.
Background Image:
(source: goehler.dk)
Masks:
(source: goehler.dk)
,
(source: goehler.dk)
,
(source: goehler.dk)
,
(source: goehler.dk)
,
(source: goehler.dk)
Each area, defined by a mask, should be highlighted on mouse over, clickable on the image, and open a certain link.
How do I do this the smartest way? I need this to be responsive, and work with a couple of hundred masks.
I haven't tried anything yet, but I've done some research, which have resulted in two possible solutions:
A. Trace the masks, and create imagemap coordinates for each, which can be overlayed the original image. (seems difficult, especially with masks that have holes).
B. Layer all masks on top, and shuffle through them and search for white pixels. (seems processor intensive, shuffling though hundres of images).
I hope however, that there is a third, simpler, more optimized and more elegant solution?
Any advice?
I'd love to hear from anyone who have any experience with something similar.
You should try to precompute as much of this as possible, especially because it's probably not feasible to download hundreds of these mask images in the user's browser.
Your solution A seems like a good way to go, provided it's possible to compute coordinates from the pixel shapes.
Another idea could be combining the mask images in a single image by color-coding the mask shapes (filling each shape with a different color). Colors can be assigned randomly as long as they are used only once. Along with that, provide a simple lookup table for the color-to-shape mapping (e.g. #f00 => cube, #0f0 => donut, ...). Now, when the original image is clicked:
Find the pixel coordinate of the click
Lookup the color in the mask image at the same coordinate
Lookup the shape for the color in the lookup table
First of all, even with 100s of masks, this should not be slow, because the required algorithm has a complexity of O(n) and that is not slow.
The only bottleneck you will have is the pixel lookup, which is an expensive operation (unless you do certain modifications).
I would go with B.
Lets say your mouse coordinates are x:400, y:300, relative to your background image which has the dimensions 800x600.
You would iterate over all masks, and check:
mask.getPixel(400, 300) == white?
If so, use that mask, blend it over the original image with a specific alpha factor so the background get grayed out.
The bottleneck is: mask.getPixel()
You would have to do that n times if you have n masks and its the last one.
As I stated, its an expensive lookup; so can you optimise it?
Yes, cut out unnecessary look-ups by using: bounding boxes.
But to use bounding boxes, you must first create the bounding box data for each mask, which you could do once when you load (no problem).
The bounding box defines the upper left and bottom right corner that "bounds" the white area snugly. In other words, you must determine min and max X & Y coordinate where the pixel is white.
If the mouse coordinates are outside of this box, do not bother making a lookup, as it will certainly not be in the white area.
Edit: Since I was bored, I went ahead and implemented it...
Check it out.
//preProcessMasks() & trackMouse() is where everything happens
Gotto have the background image "img.jpg" and the masks "1.jpg" .. "5.jpg" in the same folder!
Works with firefox, chrome says "The canvas has been tainted by cross-origin data"... its a quick n dirty hack, do whatever you want with it, if its of any use to you!
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I was looking around to find some best practice and hints when building css image sprite.
The questions:
Consider a site with lots of images:
Should I group and put images with approximately same size in one png?
What is the acceptable sprite image size? Is it recommended to make different sprite images, instead of one huge file?!
Is there any recommendation for number of images in one sprite image ?!
Is it make any difference on how to put and align images in the sprite image? I just find a hint at http://webdesign.tutsplus.com/articles/css-sprite-sheets-best-practices-tools-and-helpful-applications--webdesign-8340 which mentioned (keep images Organized, it will be more maintainable) but is it the only reason
If it helps:
I use compass sprites utility, and it automatically convert a folder of images to one png file and creates a css file for it. The images aligned under each other automatically
Should I group and put images with approximately same size in one png?
While Michael has a good point on grouping images by usage, you may also want to keep in mind that the optimal sprites have as little whitespace as possible. Saving file requests is awesome, but you do not want to load a bunch of unused pixels instead.
What is the acceptable sprite image size? Is it recommended to make different sprite images, instead of one huge file?!
Imagine a website with a huuuuge collection of icons, buttons and other graphical elements. Now image you put all those elements in one sprite, because, you know, low amount of requests and all. The sprite is 5MB big.
A visitor enters the page, and loading begins. Text appears, but you are still waiting for Megasprite to download. Depending on the filesize and the internet connection, a visitor has to wait a potentially long time before crucial (navigational) elements of the site are usable.
For a simple site a single sprite will do, but when things get more elaborate, it might be beneficial to use a couple of sprites. Furthermore, putting all your images in one sprite is a pain in the gluteus maximus when it comes to maintenance (although automation helps a lot). All in all, huge sprites are bad sprites.
Is it make any difference on how to put and align images in the sprite image?
Not really. There are a few thing you should keep in mind though. First of all, you want the sprite to be as compact as possible; the less unused space the better. However, that may force you to do ridiculous meticulous positioning in CSS. If you're willing to set background-position for each element by hand that's no problem, but nobody will blame you for cheating a little bit and using positions that are easier to work with.
One more thing
Have you considered using SVG sprites? Small in file size, perfectly smooth and crisp at every resolution. CSS Tricks has excellent articles on it here and here
To question 1:
From my experience in working on a large mobile service provider website, it is certainly a good idea to group images together, but probably better grouped logically, by what component or section of the project they belong to, rather than size. So I would group sprites that make a border (sides, rounded corners, etc.) or background images together.
It will make bits of them easier to find and to maintain during development.
On the other hand, if you're making a game and you have all your images created already (e.g. 64 images of animated character) You might as well stick them all in the one file.
Hope this helps.
Michael
What are CSS Sprites?
CSS Sprites is a method of combining multiple images used throughout your website into one big image. You can then use the proper background-position CSS attribute to load the particular image you want from your CSS Sprite using the X and Y coordinates.
CSS Sprites and Website Performance
A lot of people are under the assumption that it would be faster to reduce image file sizes and load every image individually. This is not true, in fact, it’s quite the opposite. The reason for this is because every time you make an HTTP request (whether it’s in your HTML code or your CSS code) you essentially create one more connection that has to occur in order to fully load a given page. So, for instance, if you have a page with 16 background images (as referenced in your website’s CSS file) that means that in order for that page to load it has to make 16 individual HTTP requests for each of those images. That’s not to mention any additional HTTP requests that will have to be made for stylesheets, JavaScripts, etc..
By combining all 16 of those background images into one big CSS Sprite the website only has to make one HTTP connection instead of 16 individual connections. This also means that anytime an image needs to be loaded on the fly (i.e. a rollover image) that image will already be loaded without any delay thanks to the fact that it’s already been loaded as part of your single CSS Sprite file.
So, not only are you drastically increasing performance by reducing the amount of connections but you can also take advantage of your CSS Sprites by using CSS image preloading.
How to Make a CSS Sprite
When it comes to creating CSS Sprites you’ve got two options. If you’re proficient enough with a photo editing program such as Adobe Fireworks or Adobe Photoshop then you’ll have no problem creating a CSS Sprite. For people who aren’t as savvy with those sorts of programs we recommend using SpriteMe. SpriteMe is a bookmarklet. After you’ve added it to your bookmarks bar, you simply go to any website and click the SpriteMe bookmarklet. SpriteMe will then open up an overlay over the right side of your screen with everything you need. You’ll also find that there is a demo on the SpriteMe site which will greatly assist anyone who isn’t as knowledgable.
Here’s an example of what a CSS Sprite would look like (this was created in Adobe Fireworks):
CSS Sprite Example
The above is an example of what a CSS Sprite might look like. Keep in mind there are a lot of different ways to do this. Some people like to leave 1 pixel of space in between each image just to provide some space. Other people like to leave a substantial amount of space between images. You’ll also find some people who like to stack things next to each other in rows to maximize the use of space. The bottom line is that there really isn’t a wrong way of doing this. So, with that being said consider the above example just that, an example.
Implementing the CSS Code
Now that you’ve finished making your CSS Sprite it’s time to get down to the nitty gritty and put CSS code in place so that we can actually make use of our CSS Sprite. For our example we’ll use the CSS Sprite above and show you how we made it work with the ‘Submit Comment’ button on our Comment Form at the bottom of this post.
#commentform input[type=submit] {
width: 122px;
height: 26px;
border: 0px;
background-color: #FFFFFF;
background-color: #FFFFFF;
background: url(/images/btn-sprite.png) no-repeat 0px 201px;
}
#commentform input[type=submit]:hover {
cursor: pointer;
background-position: 0px 175px;
}
Basically the trick here in using the CSS Sprites in your code is that you’re referencing the X and Y axis from the CSS Sprite. In this case the CSS code uses the background attribute, references the image URL, and finally addresses the X and Y axis which happen to be 0px for both.
The hover version of the button doesn’t have to reference the background image URL since it’s already been referenced above. Instead you simply need to change the Y axis to 175px to reflect the fact that the hover state of the button is above the non-hover state of the button.
I realize this might initially come off as confusing but I promise you once you play around with it you’ll see it’s actually very simple. If all of the CSS Sprite images are aligned to the left then your Y axis always remains at 0 pixels. This is one reason we prefer to stack our images all aligned to the left since it takes a lot of the guess work out of it. Given that your Y axis would always be the same in this case the only thing that would change is your X-axis. So, if the non hover button is at 0 pixels on the Y-axis and 201 pixels on the X-axis then the hover button above it would be at 0 pixels on the Y-axis and 175 pixels on the X-axis.
I basically want to put a canvas on top of another and define the way their contents are blended.
I have one white canvas with black characters on it, and I want to highlight a part of it with a transparent blue rectangle, without having my black characters in the background turning dark blue. In fact, I need the aspect I'd get if I merged the two canvases with globalCompositeOperation set to "multiply" instead of default, while keeping both canvases separated and overlapping.
Here's what I have :
Here's what I want :
I am aware that globalCompositeOperation would allow me to do that if I merged the two canvases into one. But I'd rather keep both canvases : my background canvas is displayed by a lib. I can still draw in it, but that would complicate things a lot:
I'd be too dependent on their logic and would have to tweak mine and theirs to make it work,
performance is critical and this solution would imply much more drawing at 24fps,
I'd struggle every time the lib is updated...
All in all it seems way better to keep away from interfering with the lib. Is there a way to choose how overlapping canvases will behave?
Thanks in advance!
EDIT: We've also thought of transforming the white parts of the background canvas into transparent parts and adding our highlight canvas underneath, but that's also complicated, if not impossible.
Do I understand that the letters canvas the lib draws has an opaque (white) background rather than a transparent one?
If so, any options for applying highlighting will be relatively poor in performance.
Standard canvas compositing won't help as there is no blending mode that combines source-destination pixels.
What you're left with is .getImageData to get the letters pixels. Then apply blue pixels where they overlap white pixels but not where they overlap black(letter) pixels.
However .getImageData is not GPU accelerated and is therefore relatively slow.
Putting the blue highlighting canvas behind a non-opaque letters canvas would give you the best performance.
Bottom line: If performance is critical and you want 24+ fps then hack that library to make the background transparent instead of opaque-white. (sorry!)
I was wondering how does pygame.blit manages the images blitted on screen. When I blit an multiple images on the screen, I see that each image is stacked on top the previous one.
How do I clear all these images? Wouldn't(somehow) there be a big problem when there are LOTS of images stacking on top of each other on the screen? Currently, I'm just blitting a white bg or custom bg on the whole screen to "clear" the screen. So far no problems or anything since the app I am working on is very small.
When you blit an image to a surface, it basicly draws it on the surface. The location of the blitting or the object blitted is not saved and cannot be changed. It's like if you were painting the images onto a canvas. The new ones would go over the old ones and there would be no way to get rid of one image if it were colliding with another image.
The most common approach to solving this is to just completly clear the screen using surface.fill(), and redraw the images each frame.
To answer your question about if there woudl be problems when there are lots of images, no. The window will only be saved as each individual pixel being a certain color, much like a regular picture you would take a camera, so no matter how many objects you blit, the game will always take the same amount of time.
There are multiple approaches:
Clean the whole background, as you are doing.
If the computer keeps up with the fps, perhaps it's better to leave it like this.
Clean only the areas where you blitted objects (see pygame.sprite.RenderUpdates)
In your case, if you have many stacked objects, perhaps it's better to write your own solution, trying to find the union between colliding rectangles, to avoid reblitting the same background over and over.
I was wondering how one would go about automatically making an image map based on just the opaque parts of a png image. You are normally able to click anywhere on the png image, even transparent areas, and it will register as clicking the image. Is there any way to exclude transparent areas and only have opaque areas register?
I assume there is some sort of javascript color detection feature, or something along those lines. I have access to jQuery on my website, as well.
Thank you for taking time to read and answer.
Trying to do this with images will be a major headache. It's possible that there is a javascript library out there to detect colors, but that's very complex stuff.
Maybe give svg a go if the graphics are simple.
This site (not mine) has a nice map using svg.