How to make array with SVG's - javascript

I am trying to make an Icon component that loads in a js file that contains an array of objects with the svg values inside it.
My Icon component looks like this:
<template>
<div class="icon"></div>
</template>
<script>
import icons from "~/assets/icons.js"
export default {
mounted() {
console.log(icons)
}
}
</script>
My icons.js looks like this:
[
{
circle: `<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 50 50">
<circle id="Ellipse_1" data-name="Ellipse 1" cx="25" cy="25" r="25" fill="red"/>
</svg>`,
},
{
square: `<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 50 50">
<rect id="Rectangle_1" data-name="Rectangle 1" width="50" height="50" fill="#02f"/>
</svg>`,
},
{
triangle: `<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 50 50">
<path id="Polygon_1" data-name="Polygon 1" d="M25,0,50,50H0Z" fill="#00ff3c"/>
</svg>`,
},
]
When I try to read the icons with the console.log it returns an empty object. I've tried changing my icons.js to see if it was because of these things: ``
But even when I change it to this it returns an empty object:
[
{name: "foo"},
{name: "bar"}
]
My project has been newly made and has no other content besides this, could it be possible i selected a wrong setting while creating the nuxt project? Or am I looking at this all wrong?

You need to export your data. BTW, I don't see any reason for using an array in your case. It seems like your data should be an object like this:
export default {
circle: `<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 50 50">
<circle id="Ellipse_1" data-name="Ellipse 1" cx="25" cy="25" r="25" fill="red"/>
</svg>`,
square: `<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 50 50">
<rect id="Rectangle_1" data-name="Rectangle 1" width="50" height="50" fill="#02f"/>
</svg>`,
}
//Then import like
import icons from "~/assets/icons.js"
// use it like
icons.circle

Related

SVG Mask Path is cropped

I am trying to build a javascript experiment of a dynamic chain which follows the mouse cursor.
Therefore I am useing a SVG wwith the following path:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 240">
<defs>
<path id="a" d="M143 158q-31-139 9-99" fill="none" stroke-linecap="round"/>
<mask id="b">
<rect x="0%" y="0%" width="100%" height="100%" fill="#fff"/>
<use href="#a" stroke-width="4" stroke-dasharray="6 14" stroke-dashoffset="7" stroke="#000"/>
</mask>
</defs>
<use href="#a" stroke-width="8" stroke-dasharray="6 14" stroke-dashoffset="7" stroke="#333" stroke-opacity=".8" mask="url(#b)"/>
<use href="#a" stroke-width="2" stroke-dasharray="12 8" stroke="#333" stroke-opacity=".8"/>
</svg>
Unfortunately the chain is cropped:
Why is this happening?
You can see the full experiment here (desktop only).
Long story short: A mask works within an object's bounding box, but the bounding box of any element doesn't include the stroke width.
Therefore, the default mask adds 10% padding around the bounding box with its x, y, width, height and maskUnits attributes. This works in most cases, but fails when an element is slim and almost horizontal or vertical.
See the below image: The blue rectangle is your path's bounding box, and the green is the area where the mask does its job. You can see that some of the path sticks out to the left and right.
So you must change the mask attributes to work for you. For example, make it cover the whole image:
<mask id="b" maskUnits="userSpaceOnUse" x="0" y="0" width="100%" height="100%">
I fixed it by adding maskUnits="userSpaceOnUse"
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/maskUnits
(changed the viewBox to better display it in an SO snippet)
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 40 300 240">
<defs>
<path id="a" d="M143 158q-31-139 9-99" fill="none" stroke-linecap="round"/>
<mask id="b" maskUnits="userSpaceOnUse">
<rect x="0%" y="0%" width="100%" height="100%" fill="#fff"/>
<use href="#a" stroke-width="4" stroke-dasharray="6 14" stroke-dashoffset="7" stroke="#000"/>
</mask>
</defs>
<use href="#a" stroke-width="8" stroke-dasharray="6 14" stroke-dashoffset="7" stroke="#333" stroke-opacity=".8" mask="url(#b)"/>
<use href="#a" stroke-width="2" stroke-dasharray="12 8" stroke="#333" stroke-opacity=".8"/>
</svg>

How to fill a polygon with an image?

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>

Satisfying Chrome deprecation of # in url but breaking svg mask

svg {
width: 500px;
height: 500px;
}
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ev="http://www.w3.org/2001/xml-events" version="1.1"
viewBox="0 0 100 100"
>
<!-- MASK DEFINITION -->
<defs>
<mask id="mask" x="0" y="0" width="100" height="100">
<rect x="0" y="0" width="100" height="100" fill="#fff"/>
<rect class="rect"
x="10"
y="10"
width="20"
height="20"
>
</rect>
</mask>
</defs>
<!-- MASK DEF -->
<rect x="0" y="0" width="100" height="100" mask="url(%23mask)"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ev="http://www.w3.org/2001/xml-events" version="1.1"
viewBox="0 0 100 100"
>
<!-- MASK DEFINITION -->
<defs>
<mask id="mask" x="0" y="0" width="100" height="100">
<rect x="0" y="0" width="100" height="100" fill="#fff"/>
<rect class="rect"
x="10"
y="10"
width="20"
height="20"
>
</rect>
</mask>
</defs>
<!-- MASK DEF -->
<rect x="0" y="0" width="100" height="100" mask="url(#mask)"/>
</svg>
I have an svg with a mask. Another element uses the mask as such:
mask="url(#mask)"
While trying to satisfy this: Treat '#' as ending data URI body content
I changed my svg mask to "url(%23mask)", but that totally breaks the mask.
Does anyone know a solution to this issue? Is there a way to satisfy both chrome and the mask?
Code snippet below contains two identical svg's; the only difference is that one uses a # and the other uses %23 when defining their urls.

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>

SVG Gradient "Pie Slice"

Is it possible to shade in a corner of a shape using only gradients?
Below is an image of what I am trying to do, but had to use a circle and a path.
I know using a path is probably a better method, but I am curious if it can be accomplished with gradients.
Thank you.
Path is not the only method. Sometimes a 5 year old can outsmart me with basic shapes:-
<svg class="sheet" xmlns="http://www.w3.org/2000/svg"
xlink="http://www.w3.org/1999/xlink" version="1.1" width="200" height="200">
<pattern id="my_pattern" patternUnits="userSpaceOnUse"
width="200" height="200" viewbox="0 0 200 200">
<rect x="0" y="0" fill="#33ff33" width="200" height="200" />
<rect x="50" y="0" fill="red" width="50" height="50" />
</pattern>
<circle cx="50" cy="50" r="40" style="stroke:black; stroke-width: 2;
fill: URL(#my_pattern)"/>
</svg>
Not with a single gradient. No.

Categories