There have been many times I have come across the need to take an image and cut an irregular shape out of it. Normally, when a developer comes across this requirement, the only thing to do is to open the image up with your favorite graphics editor, use the select tool to cut out the shape you want, and then save the result as a PNG, since it is the only image format used by all web browsers that support alpha channels. The problem is that PNG images, while compressed, are not as small as JPEGs if the source image is a photograph, and the download time of a page can balloon to unacceptable levels if there are many of these types of image on a page. When I first came across this problem, I didn’t think there was an obvious solution, but after a lot of thought, I created a library that uses HTML5
canvas using VML.
Okay, How Can I Do The Same Thing?
- Download my script from github (It includes jQuery 1.6.4 and excanvas release 3. It should work with later versions — if it doesn’t, please let me know and I’ll fix it ;-) ) .
- Include them into the head of your document.
<script src="/path/to/js/jquery-1.6.2.min.js"></script> <!--[if lt IE 9 ]> <script src="/path/to/js/excanvas/excanvas.compiled.js"></script> <![endif]--> <script src="/path/to/js/polyClip-p.js"></script>
- Layout your page as normal, placing
imgtags where you want the clipped images to go:
<div class="clipParent"> <img src="images/image.jpg" /> </div>
divtag with the class of
clipParent. You must surround all the image tags with
data-polyclipattributes set one. This is so you can style the image correctly, since the library will remove the image tag and replace it with a
- For every image on your page that you want to clip, calculate the points of the shape you want to cut out of the image and place them in the
data-polyclipattribute. For example, let’s say you have the following shape you want to cut out of a photograph:(487, 4)(500, 239)(19, 239)(43, 195)
You would then just set the
data-polyclipattribute to those points:
<img src="image.jpg" data-polyclip="487, 4, 500, 239, 19, 239, 43, 195" />
Note that the point co-ordinates are comma delimited. If you don’t want to calculate these numbers by hand, you can use your favorite imagemap generation tool to do generate the list of coordinates. Just remember to take the coordinates out of the imagemap code and stick it in the
data-polyclipattribute (for the examples on this page, I used the on-line tool available at image-maps.com).
Why Should I Do This Instead of Using a PNG?
Compare the image above with a PNG clipped with the GIMP. Even when I compressed the PNG with my PNG optimization script, the 191K PNG file is huge compared to it’s tiny 18K polyclipped JPEG analogue (Note: file sizes refer to the size of the full image as displayed at the top of this article):
|JPG using polyClip.js (18K)||PNG (191K)|
A Few Caveats
- In IE7 and 8, the image may appear briefly as a black outline before the image appears. Other than that, it looks about the same as the other browsers.
- The image does not show up correctly in Opera Mini. Then again, a lot of things (e.g. CSS3 text-shadows, CSS3 Transforms, etc.) don’t show up correctly in Opera Mini. :-)