Karthik N Karthik N - 1 month ago 16
Javascript Question

SVG view box crop using jquery

I am doing sticker website for my client. They need image crop within given SVG image. That SVG image is unshaped like Halloween face (see below).

enter image description here

When i upload an image, it will display within the given image. The rest of the image will hide.

How can i achieve this?

Answer

This is really quite easy with SVG clipPaths. It has good browser support as well, except of course IE.

.defs {
    position: absolute;
    width: 0;
    height: 0;
}
.demo {
    text-align:center;
}
.star image {
    clip-path: url(#star-clip);
}
.hex image {
    clip-path: url(#hex-clip);
}
.heart image {
    clip-path: url(#heart-clip);
}
.shape image {
    clip-path: url(#shape-clip);
}
<svg class="defs">
    <defs>
        <clipPath id="star-clip">
            <polygon id="star" points="150,7.3 196.4,101.3 300,116.3 225,189.4 242.7,292.7 150,243.9 57.3,292.7 75,189.4 0,116.3 103.6,101.3" />
        </clipPath>
        <clipPath id="hex-clip">
            <polygon id="hex" points="222.5,295 77.5,295 5,150 77.5,5 222.5,5 295,150" />
        </clipPath>
        <clipPath id="heart-clip">
            <path id="heart" d="M248.078,5.883c-36.691-14.739-77.771-0.839-98.517,31.125C128.817,5.044,87.735-8.856,51.043,5.883 C9.354,22.632-10.863,70.009,5.887,111.696c16.06,39.98,143.314,139.607,143.314,139.607l0.359,0.28l0.36-0.28 c0,0,127.251-99.627,143.314-139.607C309.986,70.009,289.768,22.632,248.078,5.883z"/>
        </clipPath>
        <clipPath id="shape-clip">
            <path id="shape" d="M132.9,0.9c-12.5,1-34.7,4.4-44.9,6.7c-33.5,7.6-55.7,28.2-63.8,58.8c-1.8,6.9-2.2,9.7-2.3,20.1c0,10.5,0.2,13.3,2.3,21.6 c9.5,40.7,33.2,90.2,71.5,149.8c10.5,16.4,14.8,21.8,22.8,29.3c4.3,3.9,8.3,6.8,13,9.2l6.9,3.4h10.9c10.9,0,10.9,0,17-2.9 c7.6-3.7,14.3-8.7,21.4-16.2c6.9-7.2,10.5-12.3,21.9-30.3C248,188.7,272,134.3,277.4,96.6c1.2-8.6,0.5-22.4-1.7-31.3 c-5.6-23.4-20.8-41.2-43.6-50.9c-15.3-6.5-27.5-10-44.5-12.5C177.7,0.5,144.9-0.1,132.9,0.9z"/>
        </clipPath>
    </defs>
</svg>
<div class="demo heart">
    <svg width="300" height="300">
        <image xlink:href="http://lorempixel.com/output/city-q-c-300-300-4.jpg" width="300" height="300" />
    </svg>
</div>
<div class="demo star">
    <svg width="300" height="300">
        <image xlink:href="http://lorempixel.com/output/cats-q-c-300-300-10.jpg" width="300" height="300" />
    </svg>
</div>
<div class="demo hex">
    <svg width="300" height="300">
        <image xlink:href="http://lorempixel.com/output/people-q-c-300-300-8.jpg" width="300" height="300" />
    </svg>
</div>
<div class="demo shape">
    <svg width="300" height="300">
        <image xlink:href="http://lorempixel.com/output/nightlife-q-c-300-300-6.jpg" width="300" height="300" />
    </svg>
</div>

You'll need to define your clipPath and then apply it to your image. In the demo, I created a separate SVG element that contains all of the shapes as path or polygon definitions and simply applied them using external styles. You can of course do this in a single SVG, such as:

<svg width="120" height="120">
    <defs>
        <clipPath id="shape-clip">
            <path id="shape" d="M60,117.4c-20.4,0-44.8-53.6-49-76.4C7.3,21,26.6,4.2,46.9,2.6c7-0.5,19.8-0.2,26.2,0 C93.5,3.4,112.7,21,109,41C104.8,63.8,79.3,117.4,60,117.4z"/>
        </clipPath>
    </defs>
    <image xlink:href="http://lorempixel.com/output/nightlife-q-c-120-120-6.jpg" width="120" height="120" style="clip-path: url(#shape-clip);" />
</svg> 

Some things to keep in mind:

  1. Your defs need to be defined in the source order before they are used (so you can't put them at the end of your page for example).
  2. The SVG element defs will not display, but they will take up space in the rendered page. I just force them out of the document flow with position: absolute and give them a height and width of 0 to make sure they don't mess with my layout.

For more information, you might want to look at these: