How to change SVG path's pivot point? - html

I am trying to rotate my svg path from it's top most point, but it's always rotating from it's top left corner, unable to change the pivot point.
I also tried to change it from transform-origin property, but didn't work out.
If there is any idea please share..
Here is my codes ::
<!-- CSS -->
<style>
.pivot {transform: rotate(60deg);}
</style>
<!-- html -->
<div>
<svg style="width:30px; overflow: visible; margin-left: 200px; margin-top: 100px;" x="0px" y="0px" viewBox="0 0 38.1 102">
<polygon class="pivot" fill="#3F964E" stroke="#000000" stroke-miterlimit="10" points="19.6,0.6 0.6,10.6 19.6,99.6 37.6,11.6 "/>
</svg>
</div>

transform:origin will work...although different browsers (I believe) have different interpretations of the origin point.
For Chrome (in this instance) because the top point of the path is actually at the top/center:
.pivot {
transform: rotate(45deg);
transform-origin:top center;
}
JSfiddle Demo
Note that this is Chrome only...FF has a different result.

You should use the svg transform attribute to rotate.
As said is the svg documentation :
The rotate(<a> [<x> <y>]) transform function specifies a rotation by a degrees about a given point. If optional parameters x and y are not supplied, the rotation is about the origin of the current user coordinate system. If optional parameters x and y are supplied, the rotate is about the point (x, y).
example :
<rect width="10" height="10" fill="red" transform="rotate(-10 50 100)" />
See: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform

Related

is there a way to reference svg from page in the css?

I see that you can reference the svg by id in some css/svg properties, as in:
<!-- the logo svg -->
<svg id="rect-container" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- left squares -->
<rect fill="url(#rect-fill)"/>
</svg>
does anyone know if we can use a svg from the page, in a css bg for example? to avoid encoding it on the css.
Something like this, which I already tried but did not seem to work the same way.
.myel {
background-image: url(#rect-svg-image);
}
First, there is a misconception to clear up.
fill: url(#source);
does not reference arbitrary SVG content, but a paint server, namely a gradient or pattern. Other uses of the CSS url() notation in SVG include the clip-path, mask and marker-start|mid|end properties that all also can only reference specific elements.
Currently, background-image needs an actual self-contained image resource or a CSS gradient. Referencing a SVG paint server with url() does not work.
But the CSS Images Module Level 4 also defines a element() functional notation that can reference fragments inside the page.
If you look at the text of the specification, there are still a lot of open questions listed to solve before this can become mainstream. There currently is only a Firefox implementation with vendor prefix, -moz-element(). You can point it to paint servers; that means you can (mis)use a <pattern> element. Although experimenting, I found there are some tradeoffs to make:
patternContentUnits="objectBoundingBox" needs all content drawn into a 1px*1px square, but makes the content scalable. Preserving the aspect ratio is not supported.
patternContentUnits="userSpaceOnUse" gives you preservation of the aspect ratio, but scaling is not supported.
svg {
display: block;
width: 0;
height: 0;
}
div {
width: 200px;
height: 150px;
border: 1px solid black;
background-image: -moz-element(#image);
background-size: cover;
}
<svg>
<pattern patternContentUnits="objectBoundingBox"
preserveAspectRatio="xMidYMid meet"
width="100%" height="100%" id="image">
<rect width=".5" height=".5" fill="red"/>
<rect width=".5" height=".5" x=".5" fill="yellow"/>
<rect width=".5" height=".5" y=".5" fill="green"/>
<rect width=".5" height=".5" x=".5" y=".5" fill="blue"/>
<circle r=".5" cx=".5" cy=".5" fill="white" opacity=".5"/>
</pattern>
</svg>
<div>

Clipping/Masking Sub-Parts of SVG Linked Image

I have a massive image of a map embedded in an SVG, which is much larger than the browser window and centered on the screen.
<svg id='map' width='7192' height='3912' viewBox='0 0 7192 3912' version='1.1'>
<image width='7192' height='3912' x='0' y='0' preserveAspectRatio='none'
xlink:href='map.jpg' />
<!-------------------->
<!-- paths are here -->
<!-------------------->
</svg>
There are two paths. One path outlines a building. The other path outlines a sub-region on the map.
The user can click on these paths, at which point that specific path will gradually be centered in the middle of the screen using a transition.
Once the path is centered, what I would like to do is clip or mask everything outside of that path, so that the only visible part of the image/map is the path that was selected and centered.
Does anybody know how to do this?
I've tried using clipPath natively in HTML and also applying it to the SVG in CSS, both of which don't seem to work. Either that or I'm doing something wrong.
Here is a working demo of the project.
The building can be located near the top middle section of the map. The sub-region, which is easier to locate considering its size, is located in the bottom right hand corner of the map. If you mouseenter them, the paths will fill. If you click on them, they will be centered on the screen.
You can re-use the clip path content as a target area for pointer events if you combine sibling selectors with the right value for pointer-events. Setting this property will both define when CSS pseudo-classes apply and which mouse events will be captured. Your centering code could be triggered by a click event.
document.querySelectorAll('.highlight').forEach(use => {
use.addEventListener('click', e => {
alert(use.id + " was clicked.");
});
});
.highlight {
fill: none;
pointer-events: fill;
}
image {
pointer-events: none;
}
#h1:hover ~ image {
clip-path: url(#clip1);
}
#h2:hover ~ image {
clip-path: url(#clip2);
}
<svg width="500" height="331">
<clipPath id="clip1">
<rect id="path1" x="20" y="20" width="80" height="80" />
</clipPath>
<clipPath id="clip2">
<circle id="path2" cx="400" cy="200" r="80" />
</clipPath>
<!-- use elements must be direct siblings preceding the image -->
<use class="highlight" id="h1" xlink:href="#path1" />
<use class="highlight" id="h2" xlink:href="#path2" />
<image xlink:href="https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" width="500" height="331" />
</svg>

Scale an SVG element using a transform origin

<html lang="en-US">
<head>
<link rel="stylesheet" href="https://codepen.io/basement/pen/oepKxY.css">
</head>
<body>
<iframe src="https://s.codepen.io/basement/debug/zdpVyV/PNAvYLZmJRQr"></iframe>
<div class="wrp">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"
width="100" height="100"
class="canvas"
>
<defs>
<style type="text/css">
polygon { fill: none; stroke-width: 0.5; stroke: #f00; }
</style>
</defs>
<g transform="translate( 0 12.5 ) scale( 1 )">
<polygon
points="
75,6.7
75,93.3
0,50
"
transform="rotate( -30 50 50 )"
/>
</g>
</svg>
</div>
<script src="origin.js"></script>
</body>
</html>
I want to make the red triangle in the snippet above scale larger while defining a specific transform origin. With the rotate attribute in SVG we can do this:
transform="rotate( -30 50 50 )"
The first value: -30 rotates element counter-clockwise. The 50 50 defines the transform origin ( x and y respectively ). Can I do this with scale?. I want my red triangle to scale up but keep it's origin centered.
Note: I know about transform-origin in CSS but I'm assuming the coordinate system that CSS uses will be relative to the whole web page or it's closest positioned element like it usually is... I want to define it in SVG coordinate terms like done with the rotate property.
You can translate --> scale --> translate_back
e.g.
<g transform="translate( 0 12.5 ) translate( 50 50) scale( 1.5 ) translate( -50 -50)">
Explanation: Assuming you would like to use (50 50) as the scale origin, this will first translate your shape by (-50, -50) so that your desired scale origin will now be at (0, 0). Then you scale, and finally you reverse the translation to put the shape back where it were.
I think this may be what you're looking for:
<style>
#<Some id> {
transform-box:fill-box; transform-origin: left; transform:scale(0.3,1);
fill:green;
}
</style>
This will scale with referencepoint on the left side of the bouding box of your SVG element.

how to make the positions of lines in svg responsive

I have a text and an image side by side with a little margin in the middle. I want to draw an arrow to a specific point on the image.
So for this I trying to use svg however, the position of the line is somehow not responsive. After reading a couple of questions here (like this) and blog posts (like this) I changed all the values to % and also added the viewBox attribute But for some reason the arrow is only in the correct position with my current browser screen 1920x1200. If I resize the browser window the arrow is at an incorrect position. My code:
html:
<div id="a">
This is the nose
</div><svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 2000 2000" preserveAspectRatio="none">
<line x1="9%" y1="9.5%" x2="23%" y2="6%" marker-end="url(#triangle)" stroke="black" stroke-width="0.2%"/>
</svg>
<img src="http://www.hickerphoto.com/images/200/little-polar-bear_29287.jpg" />
css:
#a{
position: absolute;
margin-top: 8%;
}
svg{
position: absolute;
z-index:2;
}
img{
margin-left: 20%;
position:relative;
z-index:1;
}
Here is a fiddle
Anyone an idea why this is not working?
Is svg the even the right attempt here or should I use something else?
SVG viewBox
Making SVGs Responsive with CSS - Tympanus
SVG text and Small, Scalable, Accessible Typographic Designs
SVG image element
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 2000 2000" preserveAspectRatio="none">
<image x="20" y="20" width="132" height="200" xlink:href="http://www.hickerphoto.com/images/200/little-polar-bear_29287.jpg" />
<text x="25" y="55" font-family="'Lucida Grande', sans-serif" font-size="32">This is the nose </text>
<line x1="9%" y1="9.5%" x2="23%" y2="6%" marker-end="url(#triangle)" stroke="black" stroke-width="0.2%"/>
</svg>
I found one solution, not sure if this is a good one, please correct me.
First of all I removed the viewBox attribute. Then I made the image also responsive by giving it a relative width and height: auto;. Lastly I also made the font-size responsive in the css through:
body{
font-size: 12pt;
}
a{
font-size: 1.5vh;
}
Works when I resize the browser. Here the fiddle . Please correct me if I'm wrong.

Is it possible to use an image in place of the stroke of an SVG path?

First off, I know this question is very similar to this question, but I tried implementing that solution with an SVG PATH and it did not work.
I also know that another solution would be to loop the PATH and set the FILL of the PATH as mentioned here and elsewhere on the web.
However, I have animated the STROKE-DASHOFFSET of the PATH so that the stroke of the PATH, which is simply an irregular line, appears as if it is being drawn onto the page; This is the effect that I want to achieve without using a color as the STROKE but instead an image. In other words, it would appear to the user as if the image (and not a solid color) is being drawn onto the page as an irregular line.
As per requested, below is the HTML of the PATH that I am using and its corresponding CSS, an image of that PATH, and also the CSS of the animation itself:
<div id="container">
<svg>
<path d="
M0,5
L184,5
C202,5 202,5 202,36
L202,86
L327,85
L421,166
L460,166
L499,132
L588,211
L617,211
L712,134
L748,165
L780,165
L830,111
L913,212
L938,212
L1028,140
L1078,184
L1107,184
L1152,140
L1263,249
L1263,248"
/>
</svg>
</div>
Image of PATH
#container {
width:1263px; height:255px;
position:absolute;
}
#container svg {
width:100%; height:100%;
fill:none;
stroke:#008066; stroke-width:8;
stroke-dasharray:1628; stroke-dashoffset:1628.1;
stroke-linecap:square;
animation:polyline 3.15s linear 0.5s forwards;
}
#keyframes polyline {
to {
stroke-dashoffset:0;
}
}
Is this possible?
Is this possible by using the CLIPPATH element and then somehow animating it?
TIA
Update
Below is the code with the PATTERN and IMAGE element, and the corresponding CSS, which doesn't seem to produce a stroke.
<defs>
<pattern id="pattern" width="1600" height="800" patternUnits="userSpaceOnUse">
<image xlink:href="http://lorempixel.com/1600/800/nature" width="1600" height="800" />
</pattern>
</defs>
#container svg {
stroke:url(#pattern);
}
That's a Chrome/Safari bug you're relying on.
stroke:url(#pattern);
is actually shorthand for
stroke:url(<this file>#pattern);
but there's no pattern in the css file. Chrome gets this wrong, Firefox gets it right. If you fix the reference Firefox will work but unfortunately Chrome won't any longer. The most compatible solution would therefore be to move your CSS (at least the bit that references the pattern) into the SVG file itself within <style> tags.
It works fine on firefox. I am not sure what the problem is that you are having.
#container svg {
fill: none;
stroke-width: 10px;
stroke: url(#pattern);
stroke-dasharray:1628;
stroke-dashoffset:1628.1;
animation:polyline 3.15s linear 0.5s forwards;
}
#keyframes polyline {
to {
stroke-dashoffset:0;
}
}
<div id="container">
<svg>
<defs>
<pattern id="pattern" width="1600" height="800" patternUnits="userSpaceOnUse">
<image xlink:href="http://lorempixel.com/1600/800/nature" width="1600" height="800" />
</pattern>
</defs>
<path d="M0,5
L184,5
C202,5 202,5 202,36
L202,86
L327,85
L421,166
L460,166
L499,132
L588,211
L617,211
L712,134
L748,165
L780,165
L830,111
L913,212
L938,212
L1028,140
L1078,184
L1107,184
L1152,140
L1263,249
L1263,248"
/>
</svg>
</div>