views:

3343

answers:

6

Are there any documents/tutorials on how to clip or cut a large image so that the user only sees a small portion of this image? Let's say the source image is 10 frames of animation, stacked end-on-end so that it's really wide. What could I do with Javascript to only display 1 arbitrary frame of animation at a time?

I've looked into this "CSS Spriting" technique but I don't think I can use that here. The source image is produced dynamically from the server; I won't know the total length, or the size of each frame, until it comes back from the server. I'm hoping that I can do something like:

var image = getElementByID('some-id');

image.src = pathToReallyLongImage;

// Any way to do this?!
image.width = cellWidth;
image.offset = cellWidth * imageNumber;
A: 

The width/height properties of the document's image object are read only. If you could change them, however, you would only squish the frames, not cut the frames up like you desire. The kind of image manipulation you want can not be done with client-side javascript. I suggest cutting the images up on the server, or overlay a div on the image to hide the parts you do not wish to display.

ForYourOwnGood
Yes, if you want to clip the image you need to put it inside another element (div is the most common), then you set the overflow of this element as hidden and you move the image inside of it, also think about using the image as a background.
Ricardo Vega
We have one implementation that just serves up the individual images, and there's some AJAX to get them dynamically. However, we were hoping that loading 1 big image and clipping it on the client side would make for a better user experience...
Outlaw Programmer
+3  A: 

This can be done by enclosing your image in a "viewport" div. Set a width and height on the div (according to your needs), then set position: relative and overflow: hidden on it. Absolutely position your image inside of it and change the position to change which portions are displayed.

To display a 30x40 section of an image starting at (10,20):

<style type="text/css">
    div.viewport {
        overflow: hidden:
        position: relative;
    }

    img.clipped {
        display: block;
        position: absolute;
    }
</style>

<script type="text/css">
    function setViewport(img, x, y, width, height) {
        img.style.left = "-" + x + "px";
        img.style.top  = "-" + y + "px";

        if (width !== undefined) {
            img.parentNode.style.width  = width  + "px";
            img.parentNode.style.height = height + "px";
        }
    }

    setViewport(document.getElementsByTagName("img")[0], 10, 20, 30, 40);
</script>

<div class="viewport">
    <img class="clipped" src="/images/clipped.png" alt="Clipped image"/>
</div>

The common CSS properties are associated with classes so that you can have multiple viewports / clipped images on your page. The setViewport(…) function can be called at any time to change what part of the image is displayed.

Ben Blank
VERY COOL. Worked almost instantly. Only problem with your code is that img.style.top is using the 'x' parameter when it should be using 'y', same thing for left. Other than that, worked like a charm!
Outlaw Programmer
D'oh! Lemme fix that. :-)
Ben Blank
Just for fun, I've also changed setViewport so that the width and height can be omitted if you don't want to change them.
Ben Blank
A: 

What spriting does is essentially position a absolutely-positioned DIV inside another DIV that has overflow:hidden. You can do the same, all you need to do is resize the outer DIV depending on the size of each frame of the larger image. You can do that in code easily.

You can just set the inner DIV's style:

left: (your x-position = 0 or a negative integer * frame width)px

Most JavaScript Frameworks make this quite easy.

Diodeus
+1  A: 

CSS also defines a style for clipping. See the clip property in the CSS specs.

DMKing
A: 

Alas, JavaScript simply isn't capable of extracting the properties of the image you'd require to do something like this. However, there may be salvation in the form of the HTML <canvas> element combined with a bit of server-side scripting.

PHP code to go about extracting the width and height of the really large image:

<?php
$large_image = 'path/to/large_image';
$full_w = imagesx($large_image);
$full_h = imagesy($large_image);
?>

From here, you'd then load the image into a <canvas> element, an example of which is documented here. Now, my theory was that you may be able to extract pixel data from a <canvas> element; assuming that you can, you would simply make sure to have some form of definite divider between the frames of the large image and then search for it within the canvas. Let's say you found the divider 110 pixels from the left of the image; you would then know that each "frame" was 110 pixels wide, and you've already got the full width stored in a PHP variable, so deciphering how much image you're working with would be a breeze.

The only speculative aspect to this method is whether or not JavaScript is capable of extracting color data from a specified location within an image loaded into a <canvas> element; if this is possible, then what you're trying to accomplish is entirely feasible.

Hexagon Theory
A: 

I suppose you want to take a thumbnail for your image. You can use ImageThumbnail.js that created from prototype library in this way:

<script type="text/javascript" src="prototype.js"></script>
<script type="text/javascript" src="ImageThumbnail.js"></script>
<input type="file" id="photo">
<img src="empty.gif" id="thumbnail" width="80" height="0">
<script type="text/javascript">
<!--
    new Image.Thumbnail('thumbnail', 'photo');
//-->
</script>

for more information

ecleel