How to alter how svg pattern fill is displayed - svg

So I have a webpage here. Under "frame background" there are patterns. When clicked they display in the photo frame. The problem is that some of them seem really blocky. Particularly the last one.
My code for this.
jquery:
$(" #borders #pattern1").click (function() {
$(".border").css("fill", "url(#patt1)");
});
svg:
<defs>
<pattern id="patt1" patternUnits="userSpaceOnUse" width="400" height="500">
<image xlink:href="Images/pattern1.jpg" x="0" y="0" width="542" height="774" />
</pattern>
</defs>
I hope this makes sense. If down voting for some reason please give me feedback as to why.

Related

How to include SVG within an SVG document which has JavaScript code?

Please understand this question properly before marking as duplicate.
There are many questions like this one in StackOverflow, but my question is slightly different from those.
I have a chakra.svg file, whose code is this:
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" id="b">
<circle cx="50" cy="50" r="45" stroke-width="2" stroke="blue" fill="none"/>
<script>
<![CDATA[
for(i=0;i<24;i++)
{
var l=document.createElementNS("http://www.w3.org/2000/svg","line");
l.setAttributeNS(null,"x1","50");
l.setAttributeNS(null,"y1","50");
l.setAttributeNS(null,"x2","5");
l.setAttributeNS(null,"y2","50");
l.setAttributeNS(null,"stroke-width",2);
l.setAttributeNS(null,"stroke","blue");
l.setAttributeNS(null,"transform","rotate("+(i/24*360)+",50,50)");
document.querySelector("#b").appendChild(l);
}
]]>
</script>
</svg>
The output is rendered as expected, like this:
I have another file, India_flag.svg whose code is this:
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="170" height="100">
<rect x="0" y="0" height="33" width="180" fill="#f93"/>
<rect x="0" y="33" height="34" width="180" fill="white"/>
<rect x="0" y="67" height="33" width="180" fill="green"/>
</svg>
The output of this file is also rendered as expected:
But, now the problem is, when I am trying to insert the chakra.svg file inside the India_flag.svg file using the image tag like this:
<image xlink:href="chakra.svg" x="70" y="35" height="30" width="30"/>
The output should have been that the wheel is placed at the centre of the flag, but I am getting this output:
The chakra.svg file is rendered, but the JavaScript code in that file did not run, only the circle is rendered. What am I doing wrong and how to achieve my objective?
SVG documents when loaded inside an <image> tag (or HTML <img> for that matter) are sand-boxed and won't allow the execution of scripts, nor will they be interactive (i.e no user-event).
To circumvent that, you need an other way to append you svg. The simple solution would be to copy its markup directly in the main one:
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="170" height="100">
<rect x="0" y="0" height="33" width="180" fill="#f93"/>
<rect x="0" y="33" height="34" width="180" fill="white"/>
<rect x="0" y="67" height="33" width="180" fill="green"/>
<svg x="70" y="35" height="30" width="30" id="b" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="45" stroke-width="2" stroke="blue" fill="none"/>
<script>
<![CDATA[
for(i=0;i<24;i++) {
var l=document.createElementNS("http://www.w3.org/2000/svg","line");
l.setAttribute("x1","50");
l.setAttribute("y1","50");
l.setAttribute("x2","5");
l.setAttribute("y2","50");
l.setAttribute("stroke-width",2);
l.setAttribute("stroke","blue");
l.setAttribute("transform","rotate("+(i/24*360)+",50,50)");
document.querySelector("#b").appendChild(l);
}
]]>
</script>
</svg>
</svg>
An other solution, would have been to do the inverse: load your flag image from the one with the script: plnkr.

making different parts of an SVG image clickable

I have searched through the net and have come to discover that images are made clickable when they are converted to SVG format, however I am still not sure how to do this.
the image below for example, I need every box to be clickable, how do you go about doing this and is there any app that can help me, thank you in advance
enter image description here
You could do this with an SVG. But you would probably find it much easier to do with an HTML image map.
If you're able to edit the SVG itself you can wrap each element with an anchor tag.
<svg>
<a href="www.link1.com">
<rect x="10" y="10" width="60" height="50" fill="#ddd">
</a>
<a href="www.link2.com">
<rect x="75" y="10" width="60" height="50" fill="#ddd">
</a>
</svg>
Otherwise you can use Javascript to add a click handler to each element.
document.getElementById("rect1").addEventListener("click", function() {
window.open('www.link1.com')
});
document.getElementById("rect2").addEventListener("click", function() {
window.open('www.link2.com')
});
<svg>
<rect id="rect1" x="10" y="10" width="60" height="50" fill="#ddd"/>
<rect id="rect2" x="75" y="10" width="60" height="50" fill="#ddd"/>
</svg>

Using SVG logo as mask

I'm basing my exercise on the accepted answer in: Creating transparent text to show gradient color of underlying div
Here's my rendition in jsfiddle: http://jsfiddle.net/skrln/zSjgL/
The svg code of my logo:
<svg width="190" height="121">
<mask id="cutouttext">
<rect width="190" height="121" x="0" y="0" fill="white" />
<path id="number-two" d="M75.3,56.1c7.3-3,14.2-12.5,14.2-24c0-17.7-15.1-32.1-36.8-32.1H0v121.5h52.4c30,0,43.4-16.5,43.4-36.8
C95.8,72.3,87,59.8,75.3,56.1z M66.5,94.6h-49V79.7h0.1l27-22.1c3.5-2.8,5.3-6.1,5.3-9c0-4-3.2-7.6-8.4-7.6c-6.4,0-9.1,5.7-10.2,9
l-14.6-3.9c2.9-10.8,11.8-19.1,25.2-19.1c14.4,0,24.5,9.4,24.5,21.5c0,12.4-9,18.1-17.1,23.8l-10.4,7.3h27.6V94.6z" />
<polygon id="filler" points="190,33.9 190,0 101.6,0 101.6,121.5 190,121.5 190,87.6 141.4,87.6 141.4,74.7 177.1,74.7 177.1,46.6
141.4,46.6 141.4,33.9 " />
</mask>
<rect width="190" height="121" x="0" y="0" fill="white" mask="url(#cutouttext)" />
</svg>
The result so far:
Issue:
The mask isn't behaving the way I want to; I want the inner parts of the "B" and "E" to mask out the gray underlying div so you can see the background image like the image below:
I'm having trouble knowing what part of the logo is the and which one is the . Also I can't seem to figure out the logic behind the <mask> in the SVG.
There's nothing wrong with your SVG. You placed it on a grey background, so the bits that are masked out are grey.
What you want to do is remove the grey background from below the SVG image. There may be neater ways of doing this, but one approach is to use a table layout with the logo in one cell and the grey background in another.
Here's a JSFiddle link
HTML
<div class="gray">
<svg width="190" height="121">
<mask id="cutouttext">
<rect width="190" height="121" x="0" y="0" fill="white" />
<path d="M75.3,56.1c7.3-3,14.2-12.5,14.2-24c0-17.7-15.1-32.1-36.8-32.1H0v121.5h52.4c30,0,43.4-16.5,43.4-36.8
C95.8,72.3,87,59.8,75.3,56.1z M66.5,94.6h-49V79.7h0.1l27-22.1c3.5-2.8,5.3-6.1,5.3-9c0-4-3.2-7.6-8.4-7.6c-6.4,0-9.1,5.7-10.2,9
l-14.6-3.9c2.9-10.8,11.8-19.1,25.2-19.1c14.4,0,24.5,9.4,24.5,21.5c0,12.4-9,18.1-17.1,23.8l-10.4,7.3h27.6V94.6z" />
<polygon points="190,33.9 190,0 101.6,0 101.6,121.5 190,121.5 190,87.6 141.4,87.6 141.4,74.7 177.1,74.7 177.1,46.6
141.4,46.6 141.4,33.9 " />
</mask>
<rect width="190" height="121" x="0" y="0" fill="white" mask="url(#cutouttext)" />
</svg>
<div></div>
</div>
CSS
.body {
background: #550000 url('http://sciencelakes.com/data_images/out/7/8788677-red-background-wallpaper.jpg');
display: block;
height: 500px;
margin: 0;
}
.gray {
display:table-row;
width:100%;
height:121px;
}
.gray div, .gray svg {
display:table-cell;
}
.gray div {
background:gray;
width:100%;
}

Simple fill pattern in svg : diagonal hatching

How would I fill an SVG shape, not with a single colour, an image or a gradient, but with a hatching pattern, diagonal if possible.
It's been 2 hours and I've found nothing (at least after 2005).
I figure a possible hack would be a hatched PNG that would serve as fill, but that is not ideal.
I did not find anything for diagonal hatching on the internet either, so I'll share my solution here:
<pattern id="diagonalHatch" patternUnits="userSpaceOnUse" width="4" height="4">
<path d="M-1,1 l2,-2
M0,4 l4,-4
M3,5 l2,-2"
style="stroke:black; stroke-width:1" />
</pattern>
(note the lower case "l" in the path expression)
The above creates a hatch with diagonal lines from the lower left to the upper right that are 4 pixels apart. Besides the diagonal line (M0,4 l4,-4) you also have to stroke the upper left and the lower right edges of the pattern area, since the line will otherwise be "constricted" due to clipping where it intersects the edges of the square.
To fill a rectangle with this pattern, do:
<rect x="0" y="0" width="100%" height="100%" fill="url(#diagonalHatch)"/>
Use the patternTransform attribute to rotate a vertical (or horizontal) line segment. This method tiles seamlessly and uses the simplest possible path. The pattern width attribute controls how close parallel hatches are.
<pattern id="diagonalHatch" width="10" height="10" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse">
<line x1="0" y1="0" x2="0" y2="10" style="stroke:black; stroke-width:1" />
</pattern>
This code from http://bl.ocks.org/jfsiii/7772281 seems very clean and reusable:
svg {
width: 500px;
height: 500px;
}
rect.hbar {
mask: url(#mask-stripe)
}
.thing-1 {
fill: blue;
}
.thing-2 {
fill: green;
}
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>SVG colored patterns via mask</title>
</head>
<body>
<svg>
<defs>
<pattern id="pattern-stripe"
width="4" height="4"
patternUnits="userSpaceOnUse"
patternTransform="rotate(45)">
<rect width="2" height="4" transform="translate(0,0)" fill="white"></rect>
</pattern>
<mask id="mask-stripe">
<rect x="0" y="0" width="100%" height="100%" fill="url(#pattern-stripe)" />
</mask>
</defs>
<!-- bar chart -->
<rect class="hbar thing-2" x="0" y="0" width="50" height="100"></rect>
<rect class="hbar thing-2" x="51" y="50" width="50" height="50"></rect>
<rect class="hbar thing-2" x="102" y="25" width="50" height="75"></rect>
<!-- horizontal bar chart -->
<rect class="hbar thing-1" x="0" y="200" width="10" height="50"></rect>
<rect class="hbar thing-1" x="0" y="251" width="123" height="50"></rect>
<rect class="hbar thing-1" x="0" y="302" width="41" height="50"></rect>
</svg>
</body>
</html>
You may be able to create, what you want using a <pattern> tag.
As a starting point you might take this example of the respective MDN docu:
<?xml version="1.0"?>
<svg width="120" height="120" viewBox="0 0 120 120"
xmlns="http://www.w3.org/2000/svg" version="1.1"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<pattern id="Triangle"
width="10" height="10"
patternUnits="userSpaceOnUse">
<polygon points="5,0 10,10 0,10"/>
</pattern>
</defs>
<circle cx="60" cy="60" r="50"
fill="url(#Triangle)"/>
</svg>
One problem with drawing a diagonal line within a pattern is that when the pattern is tiled the lines won't always line up - especially at high zooms. (It depends on the SVG rendering engine you happen to be using).
#Ingo's answer above attempts to resolve this by drawing in the triangles at the top-left and bottom-right corners - but again, using some rendering engines and high zooms, it doesn't always look best - and sometimes the line ends up looking a bit like a string of sausages.
Another approach is to draw a horizontal line in the pattern and rotate the pattern, e.g.
<svg:svg viewBox="0 0 100 100" version="1.1"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<svg:defs>
<svg:pattern id="diagonalHatch" patternUnits="userSpaceOnUse" width="4" height="4" patternTransform="rotate(45 2 2)">
<svg:path d="M -1,2 l 6,0" stroke="#000000" stroke-width="1"/>
</svg:pattern>
</svg:defs>
<svg:rect x="0" y="0" height="100" width="100" fill="url(#diagonalHatch)"/>
These two resources are very helpful:
https://bocoup.com/weblog/using-svg-patterns-as-fills
https://github.com/iros/patternfills/blob/master/public/patterns.css
For example:
<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'>
<rect width='10' height='10' fill='red'/>
<path d='M-1,1 l2,-2
M0,10 l10,-10
M9,11 l2,-2' stroke='orange' stroke-width='2'/>
</svg>
This is a solution for diagonal lines using circle in pattern. You can change angle as per your requirements.
<svg width="500" height="500">
<defs>
<pattern id="transformedPattern"
x="0" y="0" width="2" height="20"
patternUnits="userSpaceOnUse"
patternTransform="rotate(45)">
<circle cx="1" cy="1" r="2" style="stroke: none; fill: #0000ff" />
</pattern>
</defs>
<rect x="10" y="10" width="100" height="100"
style="stroke: #000000; fill: url(#transformedPattern);" />
</svg>
I tried with this sample. Hopefully, It can help you much.
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>SVG colored patterns via mask</title>
</head>
<body>
<svg viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="stripes" viewBox="0,0,8,8" width="16" height="16" patternUnits="userSpaceOnUse">
<polygon points="0,0 4,0 0,4" fill="yellow"></polygon>
<polygon points="0,8 8,0 8,4 4,8" fill="yellow"></polygon>
<polygon points="0,4 0,8 8,0 4,0" fill="green"></polygon>
<polygon points="4,8 8,8 8,4" fill="green"></polygon>
</pattern>
</defs>
<rect fill="url(#stripes)" x="150" y="20" width="100" height="50" />
<circle cx="50" cy="50" r="50" fill="url(#stripes)"/>
</svg>
</body>
</html>
Regards,
Vu Phan
SVG 2 has a hatch entity for specifically this purpose. From that page's example section:
<hatch hatchUnits="userSpaceOnUse" pitch="5" rotate="135">
<hatchpath stroke="#a080ff" stroke-width="2"/>
</hatch>
This is a very easily configurable way to create hatches:
Furthermore the hatch path can also be customised:
<hatchpath stroke-width="1" d="C 0,4 8,6 8,10 8,14 0,16 0,20"/>
For React Native use can use this component, for making background lines pattern.
You should add to your project react-native-svg
import PropTypes from 'prop-types';
import React, { PureComponent } from "react";
import { View } from "react-native";
import Svg, { Defs, Line, Pattern, Rect } from 'react-native-svg';
export default class PatternLineView extends PureComponent {
static propTypes = {
pattern: PropTypes.func.isRequired,
space: PropTypes.number,
backgroundColor: PropTypes.string,
lineColor: PropTypes.string,
lineWidth: PropTypes.number,
rotation: PropTypes.number
}
static defaultProps = {
pattern: () => { },
space: 8,
lineColor: "#D2D9E5",
lineWidth: 3,
rotation: 45
}
render() {
const transform = `rotate(${this.props.rotation})`
return <View style={{
flex: 1,
flexDirection: "row",
height: "100%",
width: "100%",
position: "absolute",
top: 0,
start: 0,
backgroundColor: this.props.backgroundColor
}}>
<Svg width="100%" height="100%">
<Defs>
<Pattern
id="linePattern"
patternUnits="userSpaceOnUse"
patternTransform={transform}
width={this.props.space}
height={this.props.space}>
<Line
x1="0"
y1="0"
x2="0"
y2="100%"
stroke={this.props.lineColor}
strokeWidth={this.props.lineWidth}
/>
</Pattern>
</Defs>
<Rect
fill="url(#linePattern)"
x="0"
y="0"
width="100%"
height="100%"
/>
</Svg>
</View>
}
}
I've adapted Ingo's answer here.
<defs>
<pattern id="diagonalHatch" patternUnits="userSpaceOnUse" width="4" height="4">
<!-- background -->
<path id="background"
d="M-1,3 L3,-1
M1,5 L5,1" style="stroke:pink; stroke-width:10" />
<!-- hatches -->
<path id="hatches"
d="M-2,2 L2,-2
M0,4 L4,0
M2,6 L6,2" style="stroke:red; stroke-width:1" />
</pattern>
</defs>
This pattern includes two paths, one for the background, and other for the hatches. The background color is addressable vs JS such as:
const hatchPath = document.querySelector("path#hatches");
hatchPath.setAttribute('style', "stroke:blue; stroke-width:1")
The background path is overly-wide on purpose, so that there's no part of the pattern not at least covered by the background. Meanwhile, the hatches can have their width tuned to change how thick the lines are.
Some great points got lost in the comments, so I wanted to aggregate that knowledge with some simpler inline examples. As far as I can tell, what method you choose to use is entirely up to preference since the heavy lifting is being done by patternTransform + rotate either way, but personally I think the <rect> method is easier to digest at-a-glance even if it might make more semantic sense to use <line>.
SVG Non-Scaling Pattern with <rect>
Define the spacing between your lines with the <pattern>'s width, and the width of the lines themselves via the nested <rect>'s width.
Codepen example as full-size background.
<svg height="100%" width="100%" xmlns="http://www.w3.org/2000/svg">
<pattern id="diaHatch" width="9" height="1" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
<rect x="0" y="0" width="3" height="1" fill="red" />
</pattern>
<rect x="0" y="0" width="100%" height="100%" fill="url(#diaHatch)" />
</svg>
SVG Non-Scaling Pattern with <line>
Define the spacing between the <line>s with the pattern height, and use stroke-width for the <line> itself.
Codepen example as full-size background.
<svg height="100%" width="100%" xmlns="http://www.w3.org/2000/svg">
<pattern id="diaHatch" width="1" height="9" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
<line x1="0" x2="100%" y1="0" y2="0" stroke-width="9" stroke="black" />
</pattern>
<rect x="0" y="0" width="100%" height="100%" fill="url(#diaHatch)" />
</svg>
On SVG 2 & Hatches [as of October 2022]
While the above examples solve the issue, SVG 2's Hatches (Candidate Recommendation 2016) are a documented method of tackling this exact issue. Inkscape happens to implement them because one of its developers, Tavmjong Bah, was an Invited Expert at the time, but browsers are still tackling them. To note, the latest Editor's Draft (2018) doesn't include hatch, which doesn't necessarily mean anything, but might be why it hasn't yet been prioritized by browser vendors.
Tracking SVG 2 Features for the Browser
Each major engine has an ongoing thread for feature implementations:
SVG 2 in Gecko
SVG 2 in Blink
SVG 2 in Webkit

Background image fills Raphael SVG to Canvas via canvg are black

I have found the info on converting a raphael SVG into a canvas element here very helpful. But I'm a little stuck - I have a Raphael SVG drawn (it's a little ugly, sorry, but it works), and I can almost recreate it on canvas via canvg, except my fill patterns are all black. Is there something wrong in the SVG code rendered?
Here is an example of the svg code (innerHTML) of my raphael drawing:
<svg height="530" version="1.1" width="530" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="overflow-x: hidden; overflow-y: hidden; position: relative; "><desc>Created with Raphaƫl 2.0.0</desc><defs><pattern id="BDC4C7DB-1FF9-4BE5-B868-C7B68C6A7B8B" x="0" y="0" patternUnits="userSpaceOnUse" height="1" width="1" patternTransform="matrix(1,0,0,1,0,0) translate(535.9612108001184,76)"><image x="0" y="0" href="assets/img/crush_gloss/coral_bell_gloss.jpg"></image></pattern><pattern id="75CC740F-C521-4E46-BE6F-2CE15E4CD6D4" x="0" y="0" patternUnits="userSpaceOnUse" height="1" width="1" patternTransform="matrix(1,0,0,1,0,0) translate(-31.03878919988169,426)"><image x="0" y="0" href="assets/img/crush_gloss/coral_bell_gloss.jpg"></image></pattern><pattern id="70CBF480-046A-4F7D-8B41-FD642EC8109B" x="0" y="0" patternUnits="userSpaceOnUse" height="1" width="1" patternTransform="matrix(1,0,0,1,0,0) translate(265.9612108001183,76)"><image x="0" y="0" href="assets/img/crush_gloss/habenero_gloss.jpg"></image></pattern><pattern id="146B2DC3-E4B5-4959-BFCD-6A6CF69E3300" x="0" y="0" patternUnits="userSpaceOnUse" height="1" width="1" patternTransform="matrix(1,0,0,1,0,0) translate(238.96121080011827,26)"><image x="0" y="0" href="assets/img/crush_gloss/coral_bell_gloss.jpg"></image></pattern> ... AND ON ... </defs></svg>
I am using the following to try to recreate my SVG in canvas:
innerSVG=document.getElementById('app_display').innerHTML;
//alert (innerSVG);
// load svg snippet in the canvas
canvg('canv', innerSVG);
My patterns draw fine, my background fill color is fine, it's just the image fill on the patterns I've drawn that's not okay; they're always black. I have tried referencing them by full url, relative, it makes no difference. There is no base meta tag on this page. Thoughts on where I'm wrong?
Try replacing your href with xlink:href
<image x="0" y="0" xlink:href="assets/img/crush_gloss/coral_bell_gloss.jpg"></image>
Or...
canvg('canv', innerSVG.replace("href","xlink:href"));

Resources