I am a beginner when it comes to SVG creation and have been researching this for quite a while. I've found some good resources, but I am still a bit hazy on the best way to accomplish what I am trying to do (and maybe SVG isn't the right answer - maybe jQuery or CSS3 is better).
Info
I want to have a series of equilateral SVG triangles, I plan on using them as an image thumbnails for a gallery. When you hover over them it will give you a "title" and then you can click to see the entire project (still working on getting a title to show up on hover too).
Some images will be upright, others will be inverted (upside down) - although I haven't figured out how to do this yet either.
Anyway, I have a fiddle with the triangle, image, and hover effect. All the images that will be placed within the triangles will be square. I want to do something similar to if I was using background-size: cover. Ultimately my question is, how do I center the image and fill it within the triangle.
I saw this question but I'm not sure how to integrate this within my code. Also my code thus far is based off of this question
Question
So any help with this would be greatly appreciated. My primary concern is centering and filling the image within the triage. Secondary concerns are getting some text to show up on hover and "flipping" the triangles.
Code
HTML
<svg id="svg-1" class="clip-svg">
<image id="img-1" class='svg-image' width="300" height="300" xlink:href="img/tshirt.jpg" />
<rect class='svg-describe' width="300" height="300" fill="#cccccc" />
</svg>
<svg id="svg-defs">
<defs>
<clipPath id="clip-triangle">
<polygon points="0, 200 100, 0 200, 200"/>
</clipPath>
</defs>
</svg>
CSS
.svg-describe, .svg-image {
clip-path: url(#clip-triangle);
}
.svg-describe {
opacity: 0;
transition: all 0.5s ease 0.2s;
-moz-transition: all 0.5s ease 0.2s;
-webkit-transition: all 0.5s ease 0.2s;
}
.clip-svg .svg-describe:hover {
opacity: 1;
}
jsfiddle
edit...
I was able to do a hack to center the image within the triangle by adding x="-50" y="-40" to my image tag. Although the image doesn't fill the triangle completely. I'm sure there is a better way to accomplish this though...
If you use appropriate sizes for the triangles and background images, then I think this problem will go away.
The maths is quite straightforward — if your images are all 300×300 px squares, then your equilateral triangles should be 300 px wide and 260 px tall (because 300×(√3)/2 = 260).
That means the SVG dimensions should be 300×260 px, and the embedded image should be offset vertically by 20 pixels to keep it centred.
<svg id="svg-1" class="clip-svg" width="300" height="260">
<image id="img-1" class="svg-image" width="300" height="300"
x="0" y="-20" xlink:href="http://goo.gl/l477XT" />
<rect class="svg-describe" width="300" height="260" fill="#000" />
<defs>
<clipPath id="clip-triangle">
<polygon points="0, 260 150, 0 300, 260" />
</clipPath>
</defs>
</svg>
Here's a JSFiddle
Related
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>
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.
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>
Okay, once again this is for a school project for which I am not allowed to use java (b/c idk, it is too advanced and would actually make this a lot more fun...) So basically I have this rectangle inside this gigantic massive svg file. Now I want this rectangle to change size when I hover over it. I know there is a way with getbox to determine the center and make it bigger when you hover over it. since getbox is java I can't use it.
So I thought I'd put two rectangles on top of each other, one slightly bigger than the other, set the biggers opacity to 0 and then put a style over it that says that the bigger ones opacity changes to 1 when I hover over it, so that it looks like the rectangle is changing size when really it just switches from one rectangle to the other. Only problem is it doesn't work. Now I don't know if it doesn't work b/c you cannot put two rectangles on top of each other or if it doesn't work b/c it is just plain wrong.
<g
inkscape:groupmode="layer"
id="layer12"
inkscape:label="Hobitton Cityicon"
style="display:inline"
sodipodi:insensitive="true"
transform="translate(0,-4.0044824)">
<style type="text/css">
<![CDATA[
#rect10023:hover {opacity: 1!important}
]]>
</style>
<a xlink:href="" onclick="window.open('print.html', 'newwindow', 'width=300, height=250'); return false;">
<rect
style="fill:#8f1212;fill-opacity:0;stroke:#000000;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect10023"
width="15"
height="15"
x="266.97247"
y="201.43393" />
<rect
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect10023b"
width="8.2568808"
height="6.880734"
x="266.97247"
y="201.43393" ><animate attributeName="fill" begin="2s" dur="2s" values="black;#660000" fill="freeze" />
</rect></a>
etc
There's the set element that can do the job.
<svg width="400" height="200">
<rect width="300" height="100"
>
<set attributeName="width" to="400" begin="mouseenter" end="mouseout"/>
<set attributeName="height" to="200" begin="mouseenter" end="mouseout"/>
</rect>
</svg>
I'm not certain about its support though.
Doc: http://www.w3.org/TR/SVG/animate.html#SetElement
OR, you could use CSS transform.
rect {
transition-duration: 0.7s;
}
rect:hover {
-webkit-transform: scale(0.6);
-moz-transform: scale(0.6);
-ms-transform: scale(0.6);
-o-transform: scale(0.6);
transform: scale(0.6);
}
<svg width="400" height="200">
<rect width="300" height="100">
</rect>
</svg>
rect10023b is on top of rect10023 so you can never hover over rect10023 and yet the hover CSS applies only to rect10023.
You need to give the rect at the bottom opacity 1 and on hover set the top rect to opacity 0.
Alternatively make the top rect pointer-events="none" so it is ignored for event processing so that the bottom rect can pick up the hover.
On my HTML page I have to render a shadowed and rotated polygon containing an image.
If I assign the shadow to the DIV, I get a pixelated border and a blurry image.
<div style="-webkit-transform:rotate(-15deg); -webkit-filter:drop-shadow(2px 2px 1.2px rgba(26, 25, 24, 0.50)); -webkit-transform:rotate(-30deg);">
<svg>
If I add "transform:translateZ(0);" to the SVG, I get a good border, a good shadow and a blurry image.
<div style="-webkit-transform:rotate(-30deg); -webkit-filter:drop-shadow(0.73px 2.73px 1.2px rgba(26, 25, 24, 0.50));">
<svg style="-webkit-transform:translate3D(0,0,0);">
At the end I found the best way is to assign an -webkit-svg-shadow to the SVG. This gives a good shadow, a good border and a net image. Cool.
<div style="left:58.99px ; top:90.18px; width:146.5px; height:146.5px; -webkit-transform:rotate(-30deg);">
<svg width="146.5px" height="146.5px" style="-webkit-svg-shadow:2px 2px 1.2px rgba(26, 25, 24, 0.50); ">
<defs>
<clipPath id="clipPath_1">
<polygon id="poly_1" points="70,8.19 7.56,55.88 31.53,133.44 108.5,133.5 132.44,56 "/>
</clipPath>
<pattern id="pattern_1" width="1" height="1" preserveAspectRatio="none">
<image xlink:href="image_1.png" x="6.500000" y="6.500000" width="114" height="114" preserveAspectRatio="yes"></image>
</pattern>
</defs>
<use xlink:href="#poly_1" x="0" y="0" fill="url(#pattern_1)" stroke="rgb(103, 103, 103)" stroke-width="13" />
</svg>
</div>
The problem comes now. Somewhere on the HTML page, I add a shadowed and rotated rectangle containing an image.
<div style="left:58.99px ; top:90.18px; width:114px; height:114px; -webkit-filter:drop-shadow(2px 2px 1.2px rgba(26, 25, 24, 0.50)); -webkit-transform:rotate(-15deg);">
<img src="image_1.png" alt="" style="width:114px; height:114px; "/>
The image within the rectangle looks blurry. The previous image within the SVG still looks ok.
If I add the following code to the CSS file
img{
-webkit-transform:translate3D(0,0,0); /* or even -webkit-transform:translateZ(0); */
}
the image within the rectangle looks good. BUT, the previous image within the SVG looks now blurry!
I'm really puzzled. As I understand, transform:translateZ(0) turns the GPU acceleration on, and it re-blurs the SVG's image a second time.
So, how can I get the 2 images look well? Or how to turn on/off the GPU acceleration? Should I use SVG rectangles all the time? I mean, should I use SVG for any shape? I come from Cocoa and OpenGL and I am new to HTML and CSS. At the first look it seems to be buggy and not so reliable. Is it true?