How to fill a polygon with an image? - javascript

I tried putting an image inside a polygon by using patterns, but it doesn't work. Is there any way to fill this?
<svg tabindex="1" style="width: 175px; height: 216.506px;">
<polygon points="25,0 75,0 100,43 75,86 25,86 0,43" class="hexfield" tabindex="1" hex-row="0" hex-column="0"></polygon>
<polygon points="100,44 150,44 175,87 150,130 100,130 75,87" class="hexfield" tabindex="1" hex-row="0" hex-column="1"></polygon>
<polygon points="25,87 75,87 100,130 75,173 25,173 0,130" class="hexfield" tabindex="1" hex-row="1" hex-column="0"></polygon>
<polygon points="100,130 150,130 175,173 150,216 100,216 75,173" class="hexfield" tabindex="1" hex-row="1" hex-column="1"></polygon>
<defs>
<pattern id="image1" x="0%" y="0%" height="100%" width="100%" viewBox="0 0 64 64">
<image x="0%" y="0%" width="64" height="64" xlink:href="https://cdn4.iconfinder.com/data/icons/imod/512/Software/labo.png"></image>
</pattern>
</defs>
<use xlink:href=".hexfield" fill="yellow"/>
<use xlink:href=".hexfield" fill="url(#image1)"/>
</svg>

First of all, be aware that xlink:href is deprecated.
Second, xlink:href value doesn't use CSS syntax (where # means ID and . means class).
So, for referring to a group of SVG's, you should point xlink:href to the id of a tag <g>. But If you want that only one SVG gets the definitions, point xlink:href to the SVG id (not class):
<svg tabindex="1" style="width: 175px; height: 216.506px;">
<g id="hexfield">
<polygon points="25,0 75,0 100,43 75,86 25,86 0,43"/>
<polygon points="100,44 150,44 175,87 150,130 100,130 75,87"/>
<polygon points="25,87 75,87 100,130 75,173 25,173 0,130" id="another"/>
<polygon points="100,130 150,130 175,173 150,216 100,216 75,173"/>
</g>
<defs>
<pattern id="image1" height="100%" width="100%" viewBox="0 0 64 64">
<image width="64" height="64" xlink:href="https://cdn4.iconfinder.com/data/icons/imod/512/Software/labo.png"/>
</pattern>
<pattern id="image2" height="100%" width="100%" viewBox="0 0 64 64">
<image width="64" height="64" xlink:href="https://cdn4.iconfinder.com/data/icons/imod/512/Software/iPhoto.png"/>
</pattern>
</defs>
<use xlink:href="#hexfield" fill="yellow"/>
<use xlink:href="#hexfield" fill="url(#image1)"/>
<use xlink:href="#another" fill="red"/>
<use xlink:href="#another" fill="url(#image2)"/>
</svg>

Related

How to animate SVG path polymorphing circle images?

SVG animation - for example
https://theplusaddons.com/widgets/morphing-sections/
How can I do such animation?
<div class="polymorphing">
<svg viewBox="0 0 200 200" height="600" width="600" xmlns="http://www.w3.org/2000/svg">
<clipPath id="myClip">
<path fill="#FF0066"
d="M42.3,-45.7C56.3,-38.7,70.1,-26.8,73.3,-12.4C76.5,2,69.1,18.8,58.1,29.6C47.1,40.4,32.7,45.1,17.7,51.9C2.8,58.7,-12.5,67.6,-28.1,66.5C-43.7,65.4,-59.5,54.5,-69.8,39.1C-80.2,23.7,-85.1,3.9,-80.7,-13.1C-76.4,-30.2,-62.9,-44.5,-47.9,-51.3C-32.9,-58.1,-16.4,-57.5,-1.1,-56.1C14.2,-54.8,28.4,-52.7,42.3,-45.7Z"
transform="translate(100 100)" />
</clipPath>
<g clip-path="url(#myClip)">
<image class="morph-image"
xlink:href="https://theplusaddons.com/wp-content/uploads/2019/04/digitalagency3.jpg" x="0" y="0"
height="100%" width="100%">
</image>
</g>
</svg>
</div>

SVG transforming polygon to rectangle

Is it possible to convert the following polygon svg to a rectangular shaped. The internal pattern should also be converted along too. Also since this is a cutout of a bigger pattern, I am using feMorphology filter to show where the clipPath and what shape the clipPath is in.
XML
<svg id="SvgjsSvg1008" width="550" height="650" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev/svgjs">
<defs id="SvgjsDefs1009">
<clipPath id="SvgjsClipPath1022">
<polygon id="SvgjsPolygon1015" points="131,55 131,218 90,280 5,235">
</polygon>
</clipPath>
<filter id="dilate_shape">
<feMorphology operator="dilate" in="SourceGraphic" radius="5" />
</filter>
</defs>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="550" height="650" viewBox="0 0 550 650" xml:space="preserve">
<g transform="matrix(1,0,0,1,0,0)" clip-path="url("#SvgjsClipPath1022")">
<g filter="url("#dilate_shape")">
<polygon points="131,55 131,218 90,280 5,235" fill="blue" fill-opacity="0.5" clip-path="url("#SvgjsClipPath1019")"></polygon>
</g>
<g transform="matrix(1,0,0,1,0,0)" clip-path="url("#SvgjsClipPath1022")">
<image xlink:href="https://www.dropbox.com/pri/get/3574%20%5BConverted%5D.svg?_subject_uid=360738345&raw=1&size=1280x960&size_mode=3&w=AADi5fkmMPJI2i6WvcO3faWWR_30_D8f5IdWsJhFarM2JA" x="-75" y="-75" width="150" height="150" transform="matrix(1,0,0,1,109,185)"></image>
</g>
</g>
</svg>
</svg>

Can I add a mask to an svg-element without using an id?

I want to assign a svg-mask to a svg-image. I can make this work using an id on the mask like this:
<svg id="svg1" width="5cm" height="5cm" viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<mask id="mask">
<circle cx="100" cy="100" r="100" fill="white"></circle>
</mask>
</defs>
<rect x="0" y="0" width="200" height="200" fill="red" mask="url(#mask)"></rect>
</svg>
However I want to load this svg multiple times, with a different id in the svg-tag. Therefore I will generate duplicates of the '#mask'-id. Using multiple id's is invalid code. So I want to use a class to refer to the appropriate mask. That means I cannot use the mask=url()-technique.
<svg id="svg2" width="5cm" height="5cm" viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<mask class="mask">
<circle cx="100" cy="100" r="100" fill="white"></circle>
</mask>
</defs>
<rect x="0" y="0" width="200" height="200" fill="red" mask="url(can't use this)"></rect>
</svg>
Is there a way I can apply a mask to the rect element if the mask has a class instead of id? Maybe using javaScript or some other way I didn't think of.
The full story/context:
I am actually making an svg image slider-module for Joomla with php. This php generates a module containing javascript, css and an svg. I use the javascript to animate the mask.
I do actually have it working with unique id's. I was just wondering if there is a way to assign a mask to an element without referring to id's. I may want to do this because my code is getting a bit more confusing to read, because I have to use some php in my javascript/svg and css for each unique id.
No. You can only reference masks via an id. You cannot reference SVG masks any other way.
According to your description I understand you have a identical grafical entity you want to mask with different forms, multiple times. Write that down DRY:
<!-- start with an invisible svg that only contains mask definitions -->
<svg width="0" height="0"
xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- first, you have a circular mask -->
<mask id="circle-mask">
<circle cx="100" cy="100" r="80" fill="white" />
</mask>
<!-- then, you have a different mask, lets say a diamond -->
<mask id="diamond-mask">
<polygon points="100,20 180,100 100,180 20,100" fill="white" />
</mask>
</defs>
</svg>
<!-- further into your document, you want to mask a rectangle -->
<svg id="svg1" width="5cm" height="5cm" viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<!-- reference the circle mask -->
<rect x="0" y="0" width="200" height="200" fill="red" mask="url(#circle-mask)" />
</svg>
<!-- with the circle again, as often as you want, nothing changes -->
<svg id="svg2" width="5cm" height="5cm" viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<!-- the mask is the same, so no difference to above -->
<rect x="0" y="0" width="200" height="200" fill="red" mask="url(#circle-mask)" />
</svg>
<!-- and now with the diamond; that one is different -->
<svg id="svg3" width="5cm" height="5cm" viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<!-- if the mask changes, you need to change the reference -->
<rect x="0" y="0" width="200" height="200" fill="red" mask="url(#diamond-mask)" />
</svg>
You could also reference the masks in a stylesheet and give your referencing elements a class according to the mask shape:
.masked.circular rect {
mask: url(#circle-mask);
}
.masked.diamond rect {
mask: url(#diamond-mask);
}
<svg width="0" height="0"
xmlns="http://www.w3.org/2000/svg">
<defs>
<mask id="circle-mask">
<circle cx="100" cy="100" r="80" fill="white" />
</mask>
<mask id="diamond-mask">
<polygon points="100,20 180,100 100,180 20,100" fill="white" />
</mask>
</defs>
</svg>
<svg id="svg1" class="masked circular" width="5cm" height="5cm" viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="200" height="200" fill="red" />
</svg>
<svg id="svg2" class="masked circular" width="5cm" height="5cm" viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="200" height="200" fill="red" />
</svg>
<svg id="svg1" class="masked diamond" width="5cm" height="5cm" viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="200" height="200" fill="red" />
</svg>

Include a png/svg inside a polygon?

I'm trying to think of the best way to include an image inside an SVG polygon element, like the below:
<svg id="graph" width="100%" height="400px">
<!-- pattern -->
<defs>
<pattern id="image" x="0%" y="0%" height="100%" width="100%"
viewBox="0 0 64 64">
<image x="0%" y="0%" width="64" height="64" xlink:href="https://cdn4.iconfinder.com/data/icons/imod/512/Software/labo.png"></image>
</pattern>
</defs>
<polygon stroke="red" stroke-width="2px" fill="url(#image)" points="300,150 225,280 75,280 0,150 75,20 225,20"></polygon>
</svg>
However, i also want to fill the polygon with a background colour fill, but as this is using the above pattern i'm not sure of the right approach.
Move your polygon into your defs, but take the fill out. Then make two copies with the use tag, the back one filled with your color and the front one filled with your image. You can also make multiple copies by including more images, changing the coordinates, etc.
<svg id="graph" width="100%" height="400px">
<!-- pattern -->
<defs>
<pattern id="image1" x="0%" y="0%" height="100%" width="100%" viewBox="0 0 64 64">
<image x="0%" y="0%" width="64" height="64" xlink:href="https://cdn4.iconfinder.com/data/icons/imod/512/Software/labo.png"></image>
</pattern>
<pattern id="image2" x="0%" y="0%" height="100%" width="100%" viewBox="0 0 64 64">
<image x="0%" y="0%" width="64" height="64" xlink:href="https://cdn4.iconfinder.com/data/icons/imod/512/Software/iPhoto.png"></image>
</pattern>
<polygon id="myShape" stroke="red" stroke-width="2px" points="300,150 225,280 75,280 0,150 75,20 225,20"></polygon>
</defs>
<use xlink:href="#myShape" fill="yellow"/>
<use xlink:href="#myShape" fill="url(#image1)"/>
<use xlink:href="#myShape" fill="orange" x="400"/>
<use xlink:href="#myShape" fill="url(#image2)" x="400"/>
</svg>

Resize image inside polygon point path(svg) and make it not clipped

I want to achive the following:
Resize the image inside the svg element to perfectly fit inside a polygon, and furthermore that it is fully viewable, and not clipped ( see jsfiddle).
I have gone through many stackoverflow questions but cannot figure it out:
Code:
<svg width="50%" height="50%" viewBox="0 0 25 10" preserveAspectRatio="none">
<defs>
<pattern id="im1" width="100%" height="100%" preserveAspectRatio="none">
<image preserveAspectRatio="none" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://dummyimage.com/600x400/abc" width="100%" height="100%"></image>
</pattern>
</defs>
<polygon points="0,10 29, 10 10, 0" x="0" y="0" style="fill:url(#im1);"></polygon>
</svg>
See https://jsfiddle.net/f8ktzyLw/
Can someone point me in the right direction ? is this achievable with svg only or do i need JavaScript/Canvas ?
Polygon size 29px horizontal is 4px larger than viewBox = "0 0 25 10"
I added a gray frame that shows the boundaries of the SVG canvas
<svg width="50%" height="50%" viewBox="0 0 25 10" preserveAspectRatio="none" style="border:1px solid gray">
<defs>
<pattern id="im1" width="100%" height="100%" preserveAspectRatio="none">
<image preserveAspectRatio="none" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://dummyimage.com/600x400/abc" width="100%" height="100%"></image>
</pattern>
</defs>
<polygon points="0,10 29, 10 10, 0" x="0" y="0" style="fill:url(#im1);"></polygon>
</svg>
To make the polygon fully fit inside the canvas of the SVG, it is necessary to increase the size of the SVG horizontally by 4px viewBox="0 0 29 10"
<svg width="50%" height="50%" viewBox="0 0 29 10" preserveAspectRatio="none" style="border:1px solid gray">
<defs>
<pattern id="im1" width="100%" height="100%" preserveAspectRatio="none">
<image preserveAspectRatio="none" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://dummyimage.com/600x400/abc" width="100%" height="100%"></image>
</pattern>
</defs>
<polygon points="0,10 29, 10 10, 0" x="0" y="0" style="fill:url(#im1);"></polygon>
</svg>
Or you can leave the dimensions of the viewBox="0 0 25 10 unchanged, but then you need to reduce the horizontal size of the polygon by the same 4px
<svg width="50%" height="50%" viewBox="0 0 25 10" preserveAspectRatio="none" style="border:1px solid gray">
<defs>
<pattern id="im1" width="100%" height="100%" preserveAspectRatio="none">
<image preserveAspectRatio="none" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://dummyimage.com/600x400/abc" width="100%" height="100%"></image>
</pattern>
</defs>
<polygon points="0,10 25, 10 10, 0" x="0" y="0" style="fill:url(#im1);"></polygon>
</svg>

Categories