Bootstrap 3 align elements into circle - javascript

I have a question about forming elements to form a circle, or align elements to form a circle, depending how you like it to be pronounce, now back to question:
There are couple of examples here on stackoverflow and on the internet regarding this question but any off these examples do not cover Bootstrap 3 responsive align elements to form a circle, I would like if someone can make an example out of mine working JSFiddle example (text needs to be a center of the circle, because I need to animate it), and make this using bootstrap grid system.
Is this possible, can you please explain to me how you do this so I can learn something out of this.

TL;DR; http://jsfiddle.net/k7yxtpc7/
Edit with (very long?) explanation:
So we start off with a bootstrap's hierarchy:
<div class="container-fluid">
<div class="row">
<div class="circle_container col-md-6 col-md-offset-3 col-sm-8 col-sm-offset-2 col-xs-12">
</div>
</div>
</div>
The planetary of images will be put inside .circle_container. Our aim is to make sure the whole circle will respond to .circle_container's width changes and adapt correctly. This way any change Boostrap makes to the container will be reflected on the circle itself, making it Bootstrap-compliant.
First we have to prepare .circle_container a bit. Since it's a whole circle the container must be square-ish. We must find a way to make .circle_container's height to be always equal to its width. I do this by putting a square img inside .circle_container, then scale the img's size according to the container's width:
<div class="circle_container ...">
<img class="transparent_square" src="http://i.stack.imgur.com/5Y4F4.jpg" width="2" height="2" />
</div>
.transparent_square{
width: 100%;
height: auto;
}
Note: I couldn't find a transparent square image on the web, so I had to make do with a white square. In your product a 2pxx2px transparent image is best.
Great, now we have a square container. But we've put a limiter on ourselves too. From now on, the img must be the only child of .circle_container that have a static (default) or relative position, because any further child will extend the container, destroying the square shape. Not a big deal though, since we'll position other children absolute anyway.
Next up is the central text bubble:
<div class="central_text text-center">
<h3>Special for you</h3>
<h5>Lorem ipsum</h5>
</div>
.central_text{
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
position: absolute;
}
The translate trick make use of the fact that percentile value in css transform use the element's pre-render width & height, while all other positioning rule use its parent's width & height instead. By giving the element left: 50%; top: 50% we put its top left corner at the center of its parent, then we translate it up and to the left by 50% of its own width and height, effectively centering the element within its parent. This is only 1 of several methods to center an element within a container, but it fits our situation best because the element is absolutely positioned.
Finally we reach the part where we create the circle. To sum up the trick here: we put the actual image inside a container, which has a pivot point at the center of the container, and position the image off to 1 side of the container equal to the radius of the circle. This way when we rotate the image's container, the image will be moved in a circle around the center of the container, like a drawing compass. After the image has reached our desired position, we rotate the image itself by the same degree in the other direction to compensate for the tilt in orientation, making the image upright again.
The container and image:
<div class="moon_container moon1"><img class="moon moon1" src="http://letscode.ghost.io/content/images/2015/09/stackoverflow.png"></div>
.moon_container{
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 20%; /* This is the final width of the image */
}
I set the width for .moon_container as 20% of .circle_container's width. This will be the width of the images in our final circle. Increasing or decreasing this number simply change the size of the image to your desire.
Now to offset the image from its container:
.moon{
width: 100%;
height: auto;
/* The image can be relative positioned without breaking anything because its parent is absolute */
position: relative;
/* The radius of the circle. This is equal to 175%*20% = 35% of .circle_container's width */
left: 175%;
}
Note that CSS's left use an element's direct parent's width as base unit. If you changed .moon_container's width in the previous part, the actual distance of the images will change as well.
Finally, rotations (I use moon2 as the example here because moon1 doesn't need to rotate):
/* Container rotate 45deg clockwise... */
.moon_container.moon2{
/* 360/8 (the number of images) = 45deg */
transform: translate(-50%, -50%) rotate(45deg);
}
/* ... while the image rotate 45deg counter-clockwise */
.moon.moon2{
transform: rotate(-45deg);
}
Why transform: translate(-50%, -50%) rotate(45deg); and not transform: rotate(45deg);? Because we declared transform: translate(-50%, -50%); earlier for the .moon_container (the centering trick). If we only write transform: rotate(45deg); here, the CSS parser will override the previous rule with the new one, losing the translate part. So we have to append manually.
Repeat the process to all 8 images and we're done!
If you have undetermined number of images, simply use javascript to calculate this rotation part for each image.
I hope my explanation was useful for you. I've always been bad at explanation...
Edit 2: http://jsfiddle.net/k7yxtpc7/3/ Text change on hover version as per OP's request. There's only 1 thing to note in this part, that is
$("body").on({
mouseenter : function(event){
...
},
mouseleave : function(event){
...
}
}, ".moon");
It is good habit to bind all events on either 'body' or document, instead of binding them on the actual elements itself (the .moon). This way you:
Always use only 1 event listener for the hover event, instead of 8 (you can imagine how the number scale up on an actual product).
When you add more images later, you don't have to bind the event on the new .moon again.
Original Answer:
As the requirement is rather vague, I couldn't know if my solution would satisfy you. My solution is based on 3 assumptions:
The entire planetary of images are only based on view port width, similar to how Bootstrap handle its responsive design. If you want to take view port height into consideration maybe I can conjure up another version.
The images are scaled based on the Bootstrap container's width, in order to make sure there's enough space to display all images.
Typography uses Bootstrap's defaults.
The solution avoid using javascript at the cost of not being able to add/remove images on-the-fly. If a dynamic number of images is your intention, I will put calculations in.
Sexy animations compatible.
Unfortunately Bootstrap's center-block only center a block horizontally, I had to make use of the translate trick to center the pivot point.
.central_text{
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
position: absolute;
}
This is only an answer placeholder. I will write detailed explanation once we have a satisfactory solution.

Related

How to smoothly animate position & size of an rounded rectangle?

I am implementing a "pane" view component. Similar to IntelliJ or VSCode, where each pane can be rearranged into different rows and columns. The drag-and-drop rearrange action requires a preview animation: a box that animates around the screen, showing where the new pane would be inserted if the action was finished.
Basically, I need an absolutely-positioned rounded rectangle that can smoothly animate around the screen. Ideally this would be GPU-accelerated.
My attempts:
Attempt no. 1
I simply created a <div> element and animated the height, width, top and left values. This works, and allows all other CSS effects to work on the rectangle, like borders and rounded edges. However, it's not very fast. Animating the position and size directly is recommended against because it forces a reflow on each frame.
Attempt no. 2
Instead, I created 1px by 1px colored <div>, and set its size and position by editing it's transform CSS property. This is super smooth because it uses the GPU-accelerated transform property. However, it comes with a downside: I cannot style the <div>. I cannot use border or border-radius, otherwise they become distorted by the scale transformation.
Ideas
Since a rectangle is a simple shape, could we generate an svg and interpolate between different positions? If this happens within the viewBox, would it be smooth? I'm unsure about this, because I don't have much experience with SVGs.
My question – how can I smoothly animate a div around the screen, which is styled with a border or border-radius?
I could live without the border, but the border-radius is strongly desired.
I am not entirely sure I have fully understood the problem as I am unable to recreate it in this situation:
This snippet uses transform scale and transform translate to animate an element. Evertyhing is calculated with vmin used as the basic unit just so you'll see the same aspect ratios whatever device/viewport you are using.
On my laptop the GPU usage is a pretty consistent 13%, the transforms are smooth and I can't see any distortion. So is there perhaps in the original code some absolutely defined unit used that doesn't for example scale correctly?
* {
margin: 0;
padding: 0;
}
body {
width: 100vw;
height: 100vh;
}
.container {
--containerw: 80vmin;
--containerh: 60vmin;
width: var(--containerw);
height: var(--containerh);
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
position: relative;
background-color: pink;
}
.test {
--startleft: 10;
/* where it starts (within the container as a %) */
--starttop: 10;
--endleft: 70;
/* where you want it to go to (within the container as a %) */
--endtop: 70;
--scalex: 4;
/* how much you want it to grow */
--scaley: 2;
--w: 10%;
/* its width */
--h: 10%;
/* its height */
width: var(--w);
height: var(--h);
border-radius: 1vmin;
border-width: 0.2vmin;
border-style: solid;
background-color: cyan;
animation: move 10s infinite linear;
position: absolute;
box-sizing: border-box;
}
#keyframes move {
0%,
100% {
transform: scale(1, 1) translate(calc(var(--startleft) * var(--containerw) / 100), calc(var(--starttop) * var(--containerh) / 100));
}
50% {
transform: scale(var(--scalex), var(--scaley)) translate(calc(var(--endleft) * var(--containerw) / 100 / var(--scalex)), calc(var(--endtop) * var(--containerh) / 100 / var(--scaley)));
}
}
<div class="container">
<div class="test"></div>
</div>
I figured out a fix! This allows smooth animations (using GPU-accelerated transformations) for a <div/> with rounded corners and a border, without any stretching.
It's based on the "border image" concept. Instead of animating one <div/>, we can animate 9 different divs, each representing a slice of the rectangle.
Top left corner
Top center rectangle
Top right corner
Middle left rectangle
Middle center rectangle
Middle right rectangle
Bottom left corner
Bottom center rectangle
Bottom right corner
The corners don't need to be scaled, only translated. This prevents any stretching. The rectangle edges are scaled in line with the border, and so it doesn't stretch a solid border.

Mix two .png images with alpha border with CSS

Is there a way to blend two PNG images to make perfect match when they both have border with alpha on it?
This is an example of the issue that I have:
img {
position: absolute;
left: 0px;
top: 0px;
}
.container {
height: 512px;
width: 512px;
}
<div class="container">
<img src="https://image.prntscr.com/image/VmxphMVDQSu-OXXnHQm1Tg.png" alt="Sphere">
<img src="https://image.prntscr.com/image/n0cbaO-4QVOk_PQ8ESQRqQ.png" alt="Cube">
</div>
Or a link to CodePen
The situation is that I have two 3D renders that are saved as PNG's, and both have alpha border with 50% transparency that will do a perfect match if you merge them in Photoshop and/or After Effects.
But when creating the same situation in HTML/CSS we got a white line between the elements.
After doing some reading about mix-blending-mode and background-blending-mode and do some testing with them it doesn't seems to help. We think that both of the images (their alpha channels) pre-multiplies with the background and that is why you would get semi transparent line between them (where the border is).
Is there a way to achieve this with CSS, or even maybe JavaScript/jQuery?
Edit: So we won't get into more comments on images moving and css tricks on that. It is not an option to remove that 1px, or to hide it since the big picture would not have the same look.
This isn't a matter of premultiplying with the background -- it's that along the border you have partially-transparent pixels from both images in the same position, which lets the background bleed through. 50% transparency plus 50% transparency doesn't equal 100% opaque.
Rather than fiddling with dropshadows or pixel-adjustments to patch over the problem after the fact, I think you'll need to adjust the image masks themselves. (I don't believe there will be a CSS or JS solution to this because there's no programmatic way to determine what the intended result is.)
If you're only stacking two images, this is easy -- don't put any alpha channel on the "bottom" image, put one only on the "top" image, and you're done.
If you need to stack more than two (or if you need a mask on the background image to allow the page background to show through), you'll have a few options:
wherever the border between images would cause this bleed-through, use a 1-bit alpha channel on the "bottom" image in the stack. So if you were stacking the "sphere" image above the "cube" image, the cube would have no partial transparency along the border between sphere and cube, all the pixels along the border would be 100% opaque. The sphere's partial transparency would smooth out the border so you don't see a pixelated fringe.
Make the masks on the bottom images one pixel bigger than they currently are. This is the lazy way of accomplishing (1).
pre-multiply the color within the images themselves - not with the background but with the other images that would otherwise overlap. The colors along the border darken to make up for the white color that would otherwise bleed through. (As is probably obvious this one's a little outside my area of expertise so I can't suggest exactly how to calculate the precise colors...)
There is a minor pixel difference. shift you cube by 1px to the top and tothe left and you are good to go.
img {
position: absolute;
left: 0px;
top: 0px;
}
#cube{
top:-1px;
left:-1px;
}
.container {
height: 512px;
width: 512px;
}
<div class="container">
<img src="https://image.prntscr.com/image/VmxphMVDQSu-OXXnHQm1Tg.png" alt="Sphere">
<img src="https://image.prntscr.com/image/n0cbaO-4QVOk_PQ8ESQRqQ.png" id="cube" alt="Cube">
</div>
Try it help full solution
i have add only some css .container img:last-child{ left: -1px; top:-1px; position:absolute }
img {
position: absolute;
left: 0px;
top: 0px;
}
.container img:last-child{ left: -1px; top:-1px; position:absolute }
.container {
height: 512px;
width: 512px;
}
<div class="container">
<img src="https://image.prntscr.com/image/VmxphMVDQSu-OXXnHQm1Tg.png" alt="Sphere">
<img src="https://image.prntscr.com/image/n0cbaO-4QVOk_PQ8ESQRqQ.png" alt="Cube">
</div>
Unfortunately, there's no way of removing that gap without actually moving the elements around or modifying the actual images. However you, can fake it by applying a drop shadow to each of the images to hide it. Kind of like applying makeup to remove blemishes. This does add a slight blur on the edges of the images, though, so it's not a perfect solution.
img {
position: absolute;
left: 0px;
top: 0px;
filter: drop-shadow(0 0 1px #000);
}
.container {
height: 512px;
width: 512px;
}
<div class="container">
<img src="https://image.prntscr.com/image/VmxphMVDQSu-OXXnHQm1Tg.png" alt="Sphere">
<img src="https://image.prntscr.com/image/n0cbaO-4QVOk_PQ8ESQRqQ.png" alt="Cube">
</div>

How to make a CSS element extend beyond all borders of containing div?

I have a JS Fiddle going of something that I am trying to do here. As you can see I have a circle sitting in the center of a div. When you run the script it expends evenly in all directions until it hits the left and top of the screen. What I want to happen is the circle to expand evenly in all directions (through all of the containing divs borders) so that it fills the screen with red, but I am at a loss on how to get it to overflow left and top.
here is the fiddle:
http://jsfiddle.net/dkarasinski/UxtJV/711/
HTML
<div class="outerwrapper">
<div class="test">
<div class="circle"></div>
</div>
</div>
jquery
$(document).ready(function() {
setTimeout(function() {
$('.circle').addClass('open');
}, 2000);
});
Any help would be appreciated!
I think it's more to do with your top and left absolute on the .open css class style.
Here's a fork of your fiddle with -200px on both top and left: http://jsfiddle.net/ghopkins/3eybkrz1/
Change in code:
div.open {
top: -200px;
left: -200px;
width: 1000px;
height: 1000px;
}
Your version is pinning the top left 'corner' of the circle and expanding down and right.
You're explicitly putting the <div> at (0, 0) on the page.
Instead of trying to figure out the position, you can just take advantage of the transform property:
div.open {
transform: scale(50, 50);
}
That makes the circle 50 times bigger in both the X and Y axes. The element won't change position; it'll just get bigger.
you can use this
transform: translate(-25%, -25%);
demo - http://jsfiddle.net/UxtJV/714/

Responsively position an image at specific target over background image

I have a responsive background image with a smaller image positioned over it. I am trying to keep the smaller image at a specific location when the window is resized.
Both images scale properly, and the left position works so far, but not the top position.
img {
max-width:100%;
}
#dot {
position: absolute;
top: 17%;
left: 66.5%;
width: 10%;
height: 0;
padding-bottom: 10%;
}
I have found some questions with answers that suggest:
Vertical Alignment or Positioning with Javascript
I've also looked into .position() and .offset(), not sure if either would work.
I think my best solution would be to calculate the Y offset using the current window height as a reference but I am not sure what my JS or Jquery code should look like.
Here is my jsfiddle:
http://jsfiddle.net/melissadpelletier/xBu79/21/
I'm not sure exactly what you're trying to do with your images, but you could create a new smaller image (green dot) with the same aspect ratio as your background image, and have the dot placed where it needs to be within that aspect ratio. Then stretch the width of that to be 100% and the two images are basically overlapping, but the top image (smaller image) has a transparent background. Not sure if that all makes sense, but I made a new image and did the fiddle thing, which I'm new to: http://jsfiddle.net/ydack/
img
{
width:100%;
}
#dot
{
width: 100%;
position: absolute;
top:0;
left:0;
}
#dotImg
{
top: 0;
left: 0;
width: 100%;
}
I mistakenly placed the green dot's position based on the black outline, not the full background image, so the dot is slightly up and right of where it needs to be. BUT, the position is maintained while re-sizing the window. Hacky, but it could work!
You are definitely gonna need some javascript for this. What you can do is calculate the height and width of the image whenever you resize your browser window. Then simply use some math to calculate the position of the dot relative to those dimensions.
var height = $('#image').height();
var width = $('#image').width();
/* change the fractions here according to your desired percentages */
$('#dot').css({left: width/2, top: height/2});
$(window).resize(function() {
height = $('#image').height();
width = $('#image').width();
/* change the fractions here according to your desired percentages */
$('#dot').css({left: width/2, top: height/2});
});
Try this code: http://jsfiddle.net/LimitedWard/FFQt2/3/
Note that you will need to also resize the dot according to the height/width of the image if you want it to always fit inside that box.
Edit: after further investigation, it is possible to do this in CSS; however, it's a lot sloppier because the dot doesn't follow the image if the window is too wide. This jQuery solves that problem by using pixel-based positioning.
http://jsfiddle.net/sajrashid/xBu79/24/
plenty of errors mainly not closing tags
<div id='background'>
<img src='http://i.imgur.com/57fZEOt.png'/>
<div id='dot'>
<img src='http://i.imgur.com/yhngPvm.png'/>
</div>
</div>

How to keep text over a huge image in proper position on all resolutions?

In my intro page I have a really big image in height and width to fit all the resolutions (more than 4000px in width) and I set it as below:
#source-image {
width: 100%;
position: absolute;
top: 0;
left: 0;
}
Then, I added some text over that image with these style properties:
.description {
position:absolute;
top:510px;
left:23px;
width:340px
}
And it looks properly (and as I want it to be shown) on my 15.6 inch laptop with 1366x768 resolution.
However when my roommate saw it on his high resolution monitor the description was not on the “right” position. Of course, I understand why this is happening.
My question is how can I keep dynamically the proper position of the description text in all resolutions?
Thank you very much.
Set the distance from the bottom, not from the top. Or set it in %.
EDIT: I've adapted one of my experiments into an example: http://dabblet.com/gist/2787061
The position of the description is set relative to the bottom and the left of the image container (the image is filling its entire container).
In the first case, the distances to the left and the bottom of the image container are fixed, in px.
In the second case, they are in % and change on resizing the browser window.
Basically, the rules that do the trick are
figcaption {
bottom: 5px;
left: 23px;
/* more rules here */
}
in the fist case (fixed distances, in px) and
figcaption.perc {
left: 10%;
bottom: 17%;
}
in the second case (percentage).
Also, please note that you don't need position: absolute or to set the top and the left properties for the image.
However, you do need to set position:relative on the parent of the description box.
For the image to fill the screen horizontally, you need to have margin:0; and padding:0; on the body element and width: 100%; and margin: 0; on the figure element. I've edited my example to reflect these changes http://dabblet.com/gist/2787061
For the image to fill the screen both horizontally and vertically, the easiest way is to not even use an img tag, but simply set the image as a background image for the body and set the height for both the html and the body elements to 100% - example http://dabblet.com/gist/2792929
Be careful for two reasons: one, this will really distort the image and can make it look ugly when resizing the browser window and two, if you need some content below the image you will need to give the the outer element position: absolute and set its top: 100%. Both these two aspects can be seen in the example I've linked to. You can simply remove the content below the image if you don't need it.
use position:relative; for the div that wraps the image, and position:absolute; for the text div
please set percentage
check the example- description box set in horizontal center,
first set position relative into wraper div
.description {
position:absolute;
top:510px;
left:50%;
width:340px;
margin:0 0 0 -170px
}

Categories

Resources