Replace one rectangle with the other (html/css) - html

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.

Related

Html position svg image with variable height

I want to place an image to a position.
<svg width="100%" height="100%">
<image x="100" y="100" width="50" href="..."></image>
... other elements
</svg>
The origin of an image is the top left corner, thus images are placed like the red on in the example below. However, I want the bottom center to be at that position.
The width is fix, so I can easly retrieve half of it to the x coordinate, having the image horizontaly aligned. But the height can vary. I tried
transform: translate(0, -100%)
But this result in translating 100% of the parent svg height, and not it own height.
I'm thinking about opening the file and reading it height, but it is quite expensive. Is there other solutions ?
Actual result (Red) and goal (Green)
Add transform-box: fill-box; as a CSS property to the image.
<svg width="100%" height="100%">
<style>
image {
transform-box: fill-box;
}
</style>
<image x="100" y="100" width="50" href="..."></image>
... other elements
</svg>
That changes the transfom co-ordinate system from the default viewBox (view-box as a CSS value) to the bounding box of the image which would appear to be what you want. Once you do that, translate percentages will work as you wish them to.

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>

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>

How to change SVG path's pivot point?

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

SVG triangle with centered image

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