SVG Gradient "Pie Slice" - javascript

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.

Related

Center elements inside SVG relative to each other-

Couldn't find it anywhere else to I might ask here :
I have svg rectangle which inside has other rectangles.
What I want to achieve is to center each of these rectangles in the centre of it's parent and in relation to each other.
If I drag rectangle 1 down I want the other one to move up to keep both of them centered - and same thing happening if I drag the other element down (should push upper one up).
Problem here is that I might have different width/heights and there would be 2 or more elements. Is there any mathematical equationfor that? Or a name that I can look for?
I would put the 3 rects inside a group and use the group as in the following example
svg{
border:1px solid;
width: 30vh;
}
<svg viewBox="0 0 100 280">
<defs>
<g id="rects">
<rect width="80" height="80" />
<rect width="60" height="25" x="10" y="10" />
<rect width="60" height="25" x="10" y="45" />
</g>
</defs>
<use xlink:href="#rects" x="10" y="10" stroke="black" fill="none" />
<use xlink:href="#rects" x="10" y="100" stroke="black" fill="none" />
<use xlink:href="#rects" x="10" y="190" stroke="black" fill="none" />
</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.

Having real images on top of svg

I am working on svg rectangles which represent a farmer's field. Is it possible to have an image of a field on it, just to give it a true sense and view.
Here's a sample code of one of the rectangles
<!DOCTYPE html>
<html>
<body>
<svg width="400" height="110">
<rect width="300" height="100" style="fill:green; stroke: black; stroke-width:3;" />
</svg>
</body>
</html>
I used clipPath to cut and place the picture in a rectangle.
<svg width="600" height="200" viewBox="0 0 600 200" >
<defs>
<clipPath id="field">
<rect x="25" y="5" width="550" height="190" rx="25" ry="25" style="fill:none; stroke: black; stroke-width:1;" />
</clipPath>
</defs>
<image xlink:href=" https://i.stack.imgur.com/MJkK0.jpg" width="600" height="200" clip-path="url(#field)" />
</svg>
If you want to use a different border form instead of a rectangle, for example a circle, then this will be easy to do, replacing the rectangle with a circle in the clipPath.
Option, as suggested by Paulie_D, but it needs a little refinement
If you need a frame around the picture, you will need to add a second transparent rectangle with a border
<rect width="300" height="100" style="fill:none; stroke: black; stroke-width:3;" />
<svg width="400" height="110">
<defs>
<pattern id="field" patternUnits="userSpaceOnUse" width="300" height="100">
<image xlink:href=" https://i.stack.imgur.com/MJkK0.jpg" x="-20" y="0" width="350" height="130" />
</pattern>
</defs>
<rect width="300" height="100" fill="url(#field)" />
<rect width="300" height="100" style="fill:none; stroke: black; stroke-width:3;" />
</svg>
UPDATE
With a black frame looks grim, let's replace it with a shadow.
To create a shadow, the Gauss filter is used, blurring the edges of the bottom rectangle
<filter id="filtershadow" width="120%" height="120%">
<feGaussianBlur in="SourceAlpha" stdDeviation="4"/>
</filter>
<body>
<svg width="400" height="110">
<defs>
<filter id="filtershadow" width="120%" height="120%">
<feGaussianBlur in="SourceAlpha" stdDeviation="4"/>
</filter>
<pattern id="field" patternUnits="userSpaceOnUse" width="300" height="100">
<image xlink:href=" https://i.stack.imgur.com/MJkK0.jpg" x="0" y="0" width="350" height="130" />
</pattern>
</defs>
<rect class="rect-shadow" x="10" y="14" width="290" height="90" filter="url(#filtershadow)" style="fill:black; " />
<rect width="300" height="100" fill="url(#field)" />
</svg>
</body>

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>

Changing SVG colors

I'm starting to learn JS and i have this (probably very easy) task that I'm having problems with.
So the main task is to make the lower green triangle change it's color depending on which color i click on upper object.
I made something like this:
<!DOCTYPE html>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>SVG, JavaScript</title>
<script type="text/javascript">
function changeColor("triangle"){
document.getElementById("group").getAttributeNS("fill");
evt.target.setAttributeNS("fill");
}
</script>
</head>
<body>
<svg height="500" width="500">
<g id="group">
<rect x="0" y="0" width="200" height="200" style="fill:gray;stroke:none;stroke-width:0"/>
<rect id="red_triangle" x="0" y="0" width="100" height="100" style="fill:red;stroke:none;stroke-width:0"/>
<rect id="yellow_triangle"x="100" y="0" width="100" height="100" style="fill:yellow;stroke:none;stroke-width:0"/>
<rect id="blue_triangle"x="0" y="100" width="100" height="100" style="fill:blue;stroke:none;stroke-width:0v"/>
<rect id="green_triangle"x="100" y="100" width="100" height="100" style="fill:lime;stroke:none;stroke-width:0"/>
<ellipse cx="100" cy="100" rx="100" ry="100" style="fill:gray;stroke:none;stroke-width:0"/>
<polygon id="triangle" points="100,225 150,300 50,300" style="fill:lime;stroke:none;stroke-width:0" onclick="changeColor("triangle")"/>
</g>
</svg>
</body>
</html>
but obviously it's not working. Could somebody help me with some suggestion?
// the string instead of argument name raises Error: unexpected string
function changeColor("triangle"){
// you get the attribute but don't do anything with it.
// and the group doesn't even have a fill attribute
document.getElementById("group").getAttributeNS("fill");
// here you try to set an attribute but setAttributeNS requires 3 arguments: namespace, attribute and value
// simpler setAttribute would be enough, but the value would still be overwriten by style="fill:whatever"
// and evt.target is undefined, there's no evt object
evt.target.setAttributeNS("fill");
}
then in your SVG:
// the quotes are broken,
// and here you pass a string which I'd assume to be the ID of an element you want to change
onclick="changeColor("triangle")"
So, all in all:
The onclick should be on the source rectangles, not the target triangle: <rect onclick="changeColor('triangle', this)" /> where 'triangle' is the ID of element you want to change, and this is a reference to the clicked rectangle.
SVG:
<svg height="500" width="500">
<g id="group">
<rect x="0" y="0" width="200" height="200" style="fill:gray;stroke:none;stroke-width:0"/>
<rect id="red_triangle" x="0" y="0" width="100" height="100" style="fill:red;stroke:none;stroke-width:0" onclick="changeColor('triangle', this)"/>
<rect id="yellow_triangle"x="100" y="0" width="100" height="100" style="fill:yellow;stroke:none;stroke-width:0" onclick="changeColor('triangle', this)"/>
<rect id="blue_triangle"x="0" y="100" width="100" height="100" style="fill:blue;stroke:none;stroke-width:0v" onclick="changeColor('triangle', this)"/>
<rect id="green_triangle"x="100" y="100" width="100" height="100" style="fill:lime;stroke:none;stroke-width:0" onclick="changeColor('triangle', this)"/>
<ellipse cx="100" cy="100" rx="100" ry="100" style="fill:gray;stroke:none;stroke-width:0"/>
<polygon id="triangle" points="100,225 150,300 50,300" style="fill:lime;stroke:none;stroke-width:0" />
</g>
</svg>
JS:
function changeColor( target, source ){
var color = source.style.fill;
document.getElementById( target ).style["fill"] = color;
}
Fiddle: http://jsfiddle.net/harg5kyz/1/

Categories