Brian K.
Brian K.

Reputation: 93

Creating masks across browsers

I see that there are ways to do this in webkit browsers, but I don't see ways to do it in others. Is this simply a feature that hasn't been implemented in all the browsers?

I don't have standard images, so clip won't work. I may have to render everything ahead of time, which will make my work exponential, but you deal with what you have, right?

I'd also want to be able to activate this stuff from javascript. :/

Thanks if you can provide support.

Upvotes: 3

Views: 1278

Answers (3)

Brian K.
Brian K.

Reputation: 93

I'm just going to skip the CSS variant in favor of this:

Example of a working mask: http://gumonshoe.net/NewCard/MaskTest.html

I acquired a javascript class from another website tutorial: http://gumonshoe.net/js/canvasMask.js

It reads the image data and applies the alpha pixels from the mask to the target image:

function applyCanvasMask(image, mask, width, height, asBase64) {
    // check we have Canvas, and return the unmasked image if not
    if (!document.createElement('canvas').getContext) return image;

    var bufferCanvas = document.createElement('canvas'),
        buffer = bufferCanvas.getContext('2d'),
        outputCanvas = document.createElement('canvas'),
        output = outputCanvas.getContext('2d'),

        contents = null,
        imageData = null,
        alphaData = null;

    // set sizes to ensure all pixels are drawn to Canvas
    bufferCanvas.width = width;
    bufferCanvas.height = height * 2;
    outputCanvas.width = width;
    outputCanvas.height = height;

    // draw the base image
    buffer.drawImage(image, 0, 0);

    // draw the mask directly below
    buffer.drawImage(mask, 0, height);

    // grab the pixel data for base image
    contents = buffer.getImageData(0, 0, width, height);

    // store pixel data array seperately so we can manipulate
    imageData = contents.data;

    // store mask data
    alphaData = buffer.getImageData(0, height, width, height).data;

    // loop through alpha mask and apply alpha values to base image
    for (var i = 3, len = imageData.length; i < len; i = i + 4) {
        imageData[i] = alphaData[i];
    }

    // return the pixel data with alpha values applied
    if (asBase64) {
        output.clearRect(0, 0, width, height);
        output.putImageData(contents, 0, 0);

        return outputCanvas.toDataURL();
    }
    else {
        return contents;    
    }
}

Upvotes: 1

InanisAtheos
InanisAtheos

Reputation: 632

Here are my 2 cents, if it is indeed CSS Sprites you are after.

<head>
<style type="text/css"><!--
#imagemask {
    background-image: url(image.png);
    background-repeat: no-repeat;
    background-color: transparent;
    height: 40px;
    width: 40px;
}
.mask1 { background-position: top left; }
.mask2 { background-position: 0 40px; }
.mask3 { background-position: 0 80px; }/* And so on, however your image file is 'layed out' */
--></style>
<script type="text/javascript">
    function mask1(){ document.getElementById("imagemask").setAttribute("class", "mask1"); }
    function mask2(){ document.getElementById("imagemask").setAttribute("class", "mask1"); }
    function mask3(){ document.getElementById("imagemask").setAttribute("class", "mask1"); }
</script>
</head>

<body>
    <a href="#" onclick="javascript:mask1()">mask 1</a>
    <a href="#" onclick="javascript:mask2()">mask 2</a>
    <a href="#" onclick="javascript:mask3()">mask 3</a>
    <div id="imagemask" class="mask1"></div>
</body>
  1. We define the div#imagemask to contain 1 image file as a background and set it to not repeat around, as that would sort of defy the point.
  2. We define how to "move around" the image inside the "mask" (div) with fixed width and height.
  3. As a reference, I've then added the javascript you need to switch between the masks on the fly. I wrote that in about 10 seconds, you could probably write something a little more elegant if you want.
  4. Add the links with onclick= events
  5. Finally, add the div#imagemask to the body.

Given that I don't know the width or height of your image file or it's target masking, you'll have to do some substantial edits to this code. But you get the idea :)

Upvotes: 1

user926352
user926352

Reputation:

Just off the top of my head - and without an actual problem from you for us to solve - here's a possible way to accomplish what you want...

HTML

<div class="myImage">

    <img src="path_to_image" title="Lorem ipsum" alt="Dolar sit amet" />    

    <div class="myMask">
    </div><!-- /myMask -->

</div><!-- /myImage -->

CSS

.myImage {
    position: relative;
}

.myMask {
    position:absolute;
    top: 0;
    left: 0;
    background-color: transparent;
    background-image: url('path_to_masking_image');
}

Alternatively, use an <img /> inside the myMask div, and remove the background-image property from the CSS.


The way it's currently laid out, you would need two images: the image itself in all its glory, and the mask.

The way you would accomplish the 'masking effect' is to have the mask image be a static solid color that matches background of the container its in - ie white, black, whatever.

Kapeesh? This would work in all browsers, which is what you asked for. The background-clip property has -webkit and -moz selectors, but is not supported in browsers like IE or (to my knowledge) Opera.

Upvotes: 1

Related Questions