Make a div that go somewhat curved - javascript

This question have been asked a billion times I think, but just another case.
How to make this with HTML / CSS (and, if no other option, JS - I'm thinking of canvas or SVG) :
Notes : the div should be able to contain a scrolling background image on the whole green part. And this should work on IE9+ and common mobile devices (default browser). Also, the space around the shape needs to stay transparent (no white element to create the rounded shape can be used)
What's the better option ?

CSS Implementation
You can create a border shape within a container and hide the unwanted parts. I have used view port sized units to be scalable. It can be further improved to your requirement by manipulating with the values.
body {
background: #F5F5F5;
}
.container {
height: 70vh;
overflow: hidden;
display: inline-block;
width: 30vh;
background: white;
margin: 0 10px;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
}
.curve {
background: transparent;
border: 20vh solid #7cc576;
border-radius: 35%;
height: 100vh;
transform: translateY(-20vh);
width: 50vh;
}
.container-left-curved {
transform: rotateY(180deg);
}
.container-right-curved {
transform: rotateY(0deg);
}
<div class="container container-left-curved">
<div class="curve">
</div>
</div>
<div class="container container-right-curved">
<div class="curve">
</div>
</div>
SVG Implementation
I saved your image and generated the optimized SVG code through Inkscape editor. This looks a lot better than a pure CSS solution.
body {
background: lightgray;
}
<svg height="300px" width="200px" version="1.1" viewBox="0 0 492 746.00001" fill="#000">
<g id="layer1" transform="translate(-119.71 -187.93)">
<path id="path3349" d="m189.71 620.93c0-206.67-0.33548-311-1-311-0.55 0-1-2.25-1-5s-0.45-5-1-5-1-1.9984-1-4.441c0-2.4425-0.45-4.7191-1-5.059-0.55-0.33992-1-1.9415-1-3.559s-0.45-2.941-1-2.941-1-1.0984-1-2.441c0-1.3425-0.45-2.7191-1-3.059-0.55-0.33992-1-1.9415-1-3.559s-0.45-2.941-1-2.941-1-0.88631-1-1.9696-0.9-3.572-2-5.5304c-1.1-1.9585-2-4.2222-2-5.0304 0-0.80827-0.45-1.4696-1-1.4696s-1-0.9-1-2-0.45-2-1-2-1-0.9-1-2-0.45-2-1-2-1-0.9-1-2-0.45-2-1-2-1-0.9-1-2-0.45-2-1-2-1-0.59015-1-1.3114c0-0.72129-0.9-2.2775-2-3.4582s-2-2.7323-2-3.448-0.9-1.8633-2-2.5503c-1.1-0.68696-2-2.0459-2-3.0198 0-0.97393-0.9-2.4195-2-3.2123-1.1-0.79284-2.0021-1.9047-2.0046-2.4708-0.002-0.56608-1.3525-2.4673-3-4.225-1.6474-1.7577-3-3.5577-3.0056-4-0.006-0.44232-2.2557-3.1613-5-6.0422-2.7444-2.8809-4.9897-5.6545-4.9897-6.1636 0-0.50907-2.534-3.4395-5.6312-6.512l-5.6312-5.5864h207.31 207.31l11.311 11.25c6.2212 6.1875 11.317 11.7 11.325 12.25 0.007 0.55 1.788 2.8 3.9571 5s3.9659 4.7875 3.9929 5.75 0.52562 1.75 1.1081 1.75c0.58246 0 0.73793 0.51953 0.34549 1.1545-0.39555 0.64-0.27852 0.88566 0.2626 0.55123 0.98336-0.60775 4.3329 2.601 4.3329 4.1507 0 0.45847 0.9 1.6481 2 2.6436 1.1 0.99549 2 2.6402 2 3.655s0.45 1.845 1 1.845 1 0.59015 1 1.3114c0 0.72129 0.9 2.2775 2 3.4582s2 2.8406 2 3.6886c0 0.84799 0.45 1.5418 1 1.5418s1 0.9 1 2 0.45 2 1 2 1 0.9 1 2 0.45 2 1 2 1 0.9 1 2 0.47656 2 1.059 2c0.58246 0 0.81241 0.39901 0.51101 0.88669-0.30141 0.48768 0.12204 1.4428 0.94098 2.1224 0.81894 0.67966 1.489 2.0806 1.489 3.1133s0.45 1.8776 1 1.8776 1 1.35 1 3 0.45 3 1 3 1 1.1516 1 2.559c0 1.4514 0.43284 2.2915 1 1.941 0.58342-0.36057 1 0.65628 1 2.441 0 1.6825 0.45 3.059 1 3.059s1 1.8 1 4 0.45 4 1 4 1 1.8 1 4 0.45 4 1 4 1 2.25 1 5 0.45 5 1 5c0.66452 0 1 104 1 310v310h-210-210v-311z"
fill="#7ac474" />
</g>
</svg>

Finally, after looking for the good way to achieve that, here's my notes:
1. RaphaelJS
I think RaphaelJS makes it easy and offers extended compatibility (I tested on IE8 and IE7, it works, even if I don't need it) and easier manipulation.
Here's a live example : http://jsfiddle.net/bkfssykp/
As you can see, this is somewhat a SVG based solution :
paper.path("M0,0h259.478c0,0,42.939,36.419,42.939,88.694 c0,132.905,0,368.306,0,368.306H42.939c0,0,0-235.587,0-368.464C42.939,36.345,0,0,0,0z");
I just pasted the code of my svg shape directly into it. Now, I can play with it : animation, modification, etc.
2. SVG clip-path
My first attempt was an SVG image with a SVG clip-path, as said in the article mentionned by #Deepak : https://css-tricks.com/clipping-masking-css/
Here's a live example : http://jsfiddle.net/xptycnkg/3/
Still SVG : this looks like CSS clip-path, but applied on SVG element. Works on IE9.

Related

When using Reverse Selector Pattern on styled-components props doesn`t work?

When referring to parent components and using props the props doesn't work as expected.
I edited the example code in the docs of the link below to have 3 Link components with an Icon component inside that changes its color when hovering the parent (Link). It should change to red if Icon has a red prop or yellow if it hasn't, but all 3 Icons always change to the same color.
And they also behavior in a strange way, if none of the Icons have a red prop or if the first one have a red prop they all change to yellow on hover but if the first one doesn't have a red prop and at least one of the other Icon has they all change to red on hover.
That last part probably wasn't clear but you can test it pasting the code below over the code in the docs and adding or removing the red prop on the Icons and seeing the results.
I want to understand why it is behaving that way and if it is my logic or the way I am implementing that is wrong.
https://styled-components.com/docs/advanced#referring-to-other-components
const Link = styled.a`
display: flex;
align-items: center;
padding: 5px 10px;
background: papayawhip;
color: palevioletred;
`;
const Icon = styled.svg`
flex: none;
transition: fill 0.25s;
width: 48px;
height: 48px;
${Link}:hover & {
fill: ${props => props.red ? "red" : "yellow"};
}
`;
const Label = styled.span`
display: flex;
align-items: center;
line-height: 1.2;
&::before {
content: '◀';
margin: 0 10px;
}
`;
render(
<div>
<Link href="#">
<Icon viewBox="0 0 20 20">
<path d="M10 15h8c1 0 2-1 2-2V3c0-1-1-2-2-2H2C1 1 0 2 0 3v10c0 1 1 2 2 2h4v4l4-4zM5 7h2v2H5V7zm4 0h2v2H9V7zm4 0h2v2h-2V7z"/>
</Icon>
<Label>Hovering my parent changes my style!</Label>
</Link>
<Link href="#">
<Icon red viewBox="0 0 20 20">
<path d="M10 15h8c1 0 2-1 2-2V3c0-1-1-2-2-2H2C1 1 0 2 0 3v10c0 1 1 2 2 2h4v4l4-4zM5 7h2v2H5V7zm4 0h2v2H9V7zm4 0h2v2h-2V7z"/>
</Icon>
<Label>Hovering my parent changes my style!</Label>
</Link>
<Link href="#">
<Icon red viewBox="0 0 20 20">
<path d="M10 15h8c1 0 2-1 2-2V3c0-1-1-2-2-2H2C1 1 0 2 0 3v10c0 1 1 2 2 2h4v4l4-4zM5 7h2v2H5V7zm4 0h2v2H9V7zm4 0h2v2h-2V7z"/>
</Icon>
<Label>Hovering my parent changes my style!</Label>
</Link>
</div>
);

Using icons in Bootstrap 4.5

I'm trying to figure out how to use the icons in Bootstrap 4.5 via CSS. Are there any code examples you can point me to? Ideally I'd like to know what CSS declarations are needed to be able to use them like Font Awesome e.g.
<i class="fas fa-info-circle"></i>.
The documentation at bootstrap https://icons.getbootstrap.com/#usage is not sufficient for me to figure out how to use them in a similar fashion. In other words, I'd like to be able to use jquery to set a class on an object to add an icon dynamically but I don't understand the CSS I need to do this.
CSS:
.bi-headphones::before {
display: inline-block;
content: "";
background-image: url("data:image/svg+xml,%3Csvg width='1em' height='1em' viewBox='0 0 16 16' class='bi bi-headphones' fill='currentColor' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' d='M8 3a5 5 0 0 0-5 5v4.5H2V8a6 6 0 1 1 12 0v4.5h-1V8a5 5 0 0 0-5-5z'/%3E%3Cpath d='M11 10a1 1 0 0 1 1-1h2v4a1 1 0 0 1-1 1h-1a1 1 0 0 1-1-1v-3zm-6 0a1 1 0 0 0-1-1H2v4a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1v-3z'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-size: 1rem 1rem;
width:1rem; height:1rem;
}
Usage:
<i class="bi-headphones"></i>
I use URl SVG encoder to prepare svg for css: https://yoksel.github.io/url-encoder/
i cant find in the doc that bootstrap icon is fontawesome icon
after you install it you use it as a svg like this one
<svg class="bi bi-app" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M11 2H5a3 3 0 0 0-3 3v6a3 3 0 0 0 3 3h6a3 3 0 0 0 3-3V5a3 3 0 0 0-3-3zM5 1a4 4 0 0 0-4 4v6a4 4 0 0 0 4 4h6a4 4 0 0 0 4-4V5a4 4 0 0 0-4-4H5z"/>
</svg>
or you can use it this way after you download the svg to you project
<img src="/assets/img/bootstrap.svg" alt="" width="32" height="32" title="Bootstrap">
or on your css
.bi::before {
display: inline-block;
content: "";
background-image: url("data:image/svg+xml,<svg viewBox='0 0 16 16' fill='%23333' xmlns='http://www.w3.org/2000/svg'><path fill-rule='evenodd' d='M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z' clip-rule='evenodd'/></svg>");
background-repeat: no-repeat;
background-size: 1rem 1rem;
}

How to draw link line between two path elements in d3.js

I am constructing tree structure diagram with path elements as nodes. The reason I am using path is to create rounded rectangles, all I need is to connect the those paths with line.
I have tried with getBBox(), getTotalLength() and followed too, to get x, y co-ordinates of the path and render the line accordingly, but I didn't get the solution which will solve my problem.
d3.select('#node1').node().getBBox() is returning width and height of my node as "SVGRect {x: -50, y: -30, width: 100, height: 60}".
d3.select('#node1').node().getTotalLength() is returning length of the path as "311.42041015625".
d3.select('#node1').node().getBoundingClientRect() is returning the client position, I could able to get x, y coords butwhen we scroll the screen x, y values are getting changed. Because its taking the coords from the screen I think as far as I gone through.
Here is my "svg" with "path" elements:
<g class="wrapper">
<path d="M-45,-30h90a5,5 0 0 1 5,5v50a5,5 0 0 1 -5,5h-90a5,5 0 0 1 -5,-5v-50a5,5 0 0 1 5,-5z" id="node1" style="fill: #ffffff; transform: translate(200px, 100px); stroke: #696969; stroke-width: 2;"></path>
<path d="M-45,-30h90a5,5 0 0 1 5,5v50a5,5 0 0 1 -5,5h-90a5,5 0 0 1 -5,-5v-50a5,5 0 0 1 5,-5z" id="node2" style="fill: #ffffff; transform: translate(400px, 100px); stroke: #696969; stroke-width: 2;"></path>
</g>
Now I should draw line between '#node1' and '#node2' to connect them.
I am new to d3.js, help will be highly appreciated

Dynamically create one or more borders around image

Need to have an unknown number of borders around an image, already made a solution, just want to know whether there are better possibilities.
I have a website with many photo shows. Each show is a JSON file in which each photo is an array entry in that file, e.g.
{
"filename": "02.jpg",
"short": "text under thumbnail",
"title": "A description or explanation above the photo"
}
Normally the photos get a small white border, but sometimes I want to show the location of that photo so in the JSON file I have this additional info for that photo:
"latitude": "51 02 39.73 N",
"longitude": "114 03 47.37 W",
I put a yellow border around the photo as indication that there is location info, so a click on the photo or one of the coordinates (or keyboard M) opens googleMaps to show the location.
Recently I added some videos to some of the photos, so double click the photo (or keyboard V) to start that video. I put a turquoise border around the photo to indicate that there is a video.
In the JSON file it looks like this:
"video": "myvideo.mp4",
Of course all of a sudden I had a photo with location info AND a video, so now I needed 2 borders: a yellow one and a turquoise one...
To complicate matters, I once in a while have a photo with a soundclip and a green border, defined in the JSON file as:
"sound": "myclip.mp3",
thus a photo with 3 different colored borders could also happen.
After reading some stackoverflow box-shadow articles, I came up with the following solution in Javascript to create 1,2,3 or even more borders:
var borderStyle = "";
if (elt.longitude) {
borderStyle = "coordbrdr";
}
if (elt.sound) {
borderStyle += "soundbrdr";
}
if (elt.video) {
borderStyle += "videobrdr";
}
if (borderStyle == "") {borderStyle = "normalbrdr";}
$(elt.imgHTML).attr('class', borderStyle);
and the accompanying css:
.normalbrdr {border:6px solid white;}
.coordbrdr {border:6px solid yellow; cursor:pointer;}
.soundbrdr {border:6px solid lightgreen; cursor:pointer;}
.videobrdr {border:6px solid turquoise; cursor:pointer;}
.coordbrdrsoundbrdr {box-shadow: 0 0 0 6px yellow, 0 0 0 12px green; cursor:pointer}
.coordbrdrvideobrdr {box-shadow: 0 0 0 6px yellow, 0 0 0 12px turquoise; cursor:pointer}
.coordbrdrsoundbrdrvideobrdr {box-shadow: 0 0 0 6px yellow, 0 0 0 12px green, 0 0 0 18px turquoise; cursor:pointer}
.soundbrdrvideobrdr {box-shadow: 0 0 0 6px green, 0 0 0 12px turquoise; cursor:pointer}
So in this way I managed to build the various class values.
My question: Would there be a shorter, or better method to dynamically create different borders ??

Animated Ripples using jquery

I would like to create an animated visualisation (responsive if possible) where the ripples are originating from a central point and when those ripples reach outer nodes in a circle, those nodes create similar ripples of variable size.
So far, I have found these libraries:
https://github.com/mbostock/d3/wiki/Gallery
http://flare.prefuse.org/
But none of them seem to have exactly what I am after and they also seem like an overkill.
What is be the best approach to achieve this?
P.S: I am open to using Adobe's Edge Animate if it offers an easy solution since I create a lot of data visualisations for the new company I am working with.
I think the best approach would be either to use some CSS animations or possibly to use HTML5 canvas and JavaScript with requestAnimationFrame
here is an example of creating a ripple effect with CSS animations on CodePen
.ripple:before,.ripple:after {
content:'';
position:absolute;
}
.ripple:before {
-webkit-animation-delay:.2s;-moz-animation-delay:.2s;top:5px;left:25px;
}
.ripple:after {
-webkit-animation-delay:.8s;-moz-animation-delay:.8s;top:25px;left:0;
}
#-webkit-keyframes rip
{
0% {
box-shadow:0 0 0 0 transparent,
0 0 0 0 transparent,
0 0 0 0 transparent,
0 0 0 0 transparent;
}
5% {
box-shadow:0 0 0 0 #45c2c5,
0 0 0 0 rgba(255,255,255,0.4),
0 0 0 0 #45c2c5,
0 0 0 0 rgba(0,0,0,0.08);
}
100% {
box-shadow:0 0 40px 200px #45c2c5,
0 0 10px 210px transparent,
0 0 30px 220px #45c2c5,
0 0 5px 230px transparent;
}
}

Categories