animating round progress bars in jquery with numbers 0-10+decimals - javascript

please bear with me as i'm fairly new to jquery & js in general...
Here's what i have so far. http://jsfiddle.net/hqwxogqt/1/
$(function(){
var $ppc = $('.progress'),
percent = parseInt($ppc.data('percent')),
deg = 360*percent/5;
if (percent > 2.5) {
$ppc.addClass('gt-50');
}
$('.ss-progress-fill').css('transform','rotate('+ deg +'deg)');
$('.ss-percent span').html(percent);
});
I actually found this somewhere & was able to implement it but i don't know how to animate it.
the animation i want to do is similar to how to the round counter (counts from 1-10) works here: awwwards.com
basically just to have it move from 0 to the certain number obtained from the div element. the number needs to only be from 0-5 & i also want to include decimals to the count but i can't figure out how.
i tried using a while loop & anything i found online doesn't seem to work probably because i have no clue how to use it or it's just not applicable to what i want to do. i'm just out of options...
any help will be much appreciated.

This is the basic idea: If you want them to animate for a set time, calculate the step size so it is dynamic.
function updatePercentage () {
var elem = $(this);
var current = elem.data("percent-current") || 0;
var percent = parseFloat(current) + .1;
var max = parseFloat(elem.data("percent"));
if (percent > max) {
percent = max;
}
percent = percent.toFixed(1);
deg = 360*percent/5;
elem.data("percent-current", percent);
elem.toggleClass('gt-50', percent > 2.5);
elem.find('.ss-progress-fill').css('transform','rotate('+ deg +'deg)');
elem.find('.ss-percent span').html(percent);
if (percent != max) {
window.setTimeout( updatePercentage.bind(this), 100);
}
}
$(function(){
var $ppc = $('.progress');
$ppc.each(updatePercentage);
});
.progress {width: 200px; height: 200px; border-radius: 50%; background-color: #E5E5E5; position: relative;}
.progress.gt-50 {background-color: #81CE97;}
.ss-progress {content: ""; position: absolute; border-radius: 50%; left: calc(50% - 100px); top: calc(50% - 100px); width: 200px; height: 200px; clip: rect(0, 200px, 200px, 100px);}
.ss-progress .ss-progress-fill { content: ""; position: absolute; border-radius: 50%; left: calc(50% - 100px); top: calc(50% - 100px);
width: 200px; height: 200px; clip: rect(0, 100px, 200px, 0); background: #81CE97; transform: rotate(60deg);}
.gt-50 .ss-progress {clip: rect(0, 100px, 200px, 0);}
.gt-50 .ss-progress .ss-progress-fill {clip: rect(0, 200px, 200px, 100px); background: #E5E5E5;}
.ss-percent {content: ""; position: absolute; border-radius: 50%; left: calc(50% - 173.91304px/2); top: calc(50% - 173.91304px/2);
width: 173.91304px; height: 173.91304px; background: #fff; text-align: center; display: table;}
.ss-percent span {display: block; font-size: 2.6em; font-weight: bold; color: #81CE97;}
.ss-percent-wrapper {display: table-cell; vertical-align: middle;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="progress" data-percent="1">
<div class="ss-progress">
<div class="ss-progress-fill"></div>
</div>
<div class="ss-percent">
<div class="ss-percent-wrapper">
<span>%</span>
</div>
</div>
</div>
<div class="progress" data-percent="2.5">
<div class="ss-progress">
<div class="ss-progress-fill"></div>
</div>
<div class="ss-percent">
<div class="ss-percent-wrapper">
<span>%</span>
</div>
</div>
</div>
<div class="progress" data-percent="3">
<div class="ss-progress">
<div class="ss-progress-fill"></div>
</div>
<div class="ss-percent">
<div class="ss-percent-wrapper">
<span>%</span>
</div>
</div>
</div>
<div class="progress" data-percent="5">
<div class="ss-progress">
<div class="ss-progress-fill"></div>
</div>
<div class="ss-percent">
<div class="ss-percent-wrapper">
<span>%</span>
</div>
</div>
</div>

Related

Background reveal javascript not working properly

By following this tutorial :https://codepen.io/xaviDDB/pen/ExaKeeN I made a section in my website with this background reveal. here is the link:http://example.com/abra/
The code works fine if I do not have any other section in this page. But if I do, then it gets very strange. The reveal circle move away from the Mouse. See the page, I have added a horse image & the code gets messy. How do I solve this?
This is my current code:
(function() {
let magic = document.querySelector('.magic');
let magicWHalf = magic.offsetWidth / 2;
document.body.addEventListener('mousemove', function(e) {
magic.style.left = e.pageX - magicWHalf + 'px';
magic.style.top = e.pageY - magicWHalf + 'px';
});
document.body.addEventListener('mouseout', function(e) {
//magic.style.left = 'calc(50% - 10rem)';
//magic.style.top = 'calc(50% - 10rem)';
});
})();
.containers {
position: relative;
height: 100vh;
width: 100%;
background-color: #ffffff;
text-align: center;
overflow: hidden;
z-index: 1;
}
.containers:hover {
cursor: crosshair;
}
.text {
position: absolute;
font-size: 72px;
font-family: Arial, Helvetica, sans-serif;
color: #000000;
bottom: 20%;
left: 0;
right: 0;
z-index: 3;
}
.magic {
position: absolute;
top: calc(50% - 10rem);
left: calc(50% - 10rem);
width: 500px;
height: 500px;
background: center center no-repeat fixed;
background-size: cover;
border-radius: 50%;
z-index: 2;
}
<div class="containers">
<div class="text">Lorem Ipsum</div>
<div class="magic" style="background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/142996/hover-reveal.jpg')"></div>
</div>
You have to update your mouse-move function in javascript. It has to calculate the relative mouse position to its parent (.container)
and one more improvement: set the eventListener on the element you want to hover. Not the entire body.
(function() {
const container = document.querySelector('.container');
const magic = document.querySelector('.magic');
const magicWHalf = magic.offsetWidth / 2;
container.addEventListener('mousemove',function(e){
const rect = container.getBoundingClientRect(),
scrollLeft = window.pageXOffset || document.documentElement.scrollLeft,
scrollTop = window.pageYOffset || document.documentElement.scrollTop;
magic.style.left = (e.pageX - (rect.left + scrollLeft)) - magicWHalf+'px';
magic.style.top = (e.pageY - (rect.top + scrollTop)) - magicWHalf+'px';
});
container.addEventListener('mouseout',function(e){
//magic.style.left = 'calc(50% - 10rem)';
//magic.style.top = 'calc(50% - 10rem)';
});
})();
.container {
position: relative;
height: 100vh;
width: 100%;
background-color: #ffffff;
text-align: center;
overflow: hidden;
z-index: 1;
}
.container:hover {
cursor: crosshair;
}
.text {
position: absolute;
font-size: 72px;
font-family: Arial, Helvetica, sans-serif;
color: #000000;
bottom: 20%;
left: 0;
right: 0;
z-index: 3;
}
.magic {
--size: 20rem;
position: absolute;
top: calc(50% - var(--size));
left: calc(50% - var(--size));
width: var(--size);
height: var(--size);
background: center no-repeat fixed;
background-size: cover;
border-radius: 50%;
z-index: 2;
}
<h1>add</h1>
<h1>extra</h1>
<h1>space</h1>
<h1>at top</h1>
<div class="container">
<div class="text">Lorem Ipsum</div>
<div class="magic" style="background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/142996/hover-reveal.jpg')"></div>
</div>
You need to add the height of the previous element of your div.container
html
<div class="other">Other div </div>
<div class="container">
<div class="text">Lorem Ipsum</div>
<div class="magic" style="background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/142996/hover-reveal.jpg')"></div>
</div>
js
let magic = document.querySelector('.magic');
let magicWHalf = magic.offsetWidth / 2;
let heightPrevELm=document.querySelector('.other').offsetHeight;
document.body.addEventListener('mousemove',function(e){
magic.style.left = e.pageX - magicWHalf+'px';
magic.style.top = e.pageY - (magicWHalf+heightPrevELm)+'px';
});
You can see the result here :
https://codepen.io/bertyn99/pen/YzEwOpO
But i think if they are multiple element before we need to optimize the code

Resizing and scrolling issue (JS/HTML)

There are two containers: the first is a small viewport and the second is huge workspace. So, user scroll the viewport to move within the workspace. I want to implement a zoom in/out feature via CSS property tranform, but during the process I faced one difficulty and could not find a precise solution for it.
The issue is: when user zooms in/out, elements at the workspace are shifted. This happens actually because the workspace is resized, not they. But if I resize each element at the workspace, the distances between them (in terms of top/left CSS values) will be changed, what is not preferred.
I see the following solution: change scrolls values after resizing, but I do not know what ratios or numbers to use. Is there any formulae or another solution to overcome such a problem?
For resizing use Alt + MouseWheel
let workspace = document.getElementsByClassName('workspace')[0];
workspace.onwheel = resize;
let current_scale = 1;
function resize(E) {
E = E || window.event
if (E.altKey) {
E.preventDefault();
let new_scale = Math.max(0.1, current_scale - E.deltaY / 360);
workspace.style.setProperty('transform', 'scale(' + new_scale + ')');
current_scale = new_scale;
}
}
.viewport {
width: 80vw;
height: 80vh;
box-sizing: border-box;
overflow: scroll;
transform: scale(1);
}
.workspace {
position: relative;
width: 1000px;
height: 1000px;
overflow: hidden;
}
.element {
position: absolute;
width: 10px;
height: 10px;
}
<div class="viewport">
<div class="workspace">
<button class="element" style="top: 100px; left: 150px"></button>
<button class="element" style="top 80px; left: 100px"></button>
<button class="element" style="top: 230px; left: 130px"></button>
<button class="element" style="top: 100px; left: 250px"></button>
</div>
</div>
UPD: I attached some photos from the original project for clarification:
So, that's a look of the workspace with scale(1)
Then I resize it and get the following result:
But desirable result looks like this:
UPD2
I inserted <svg> element to show how lines are drawn and why resizing each button seems to me a not viable solution in my case
let workspace = document.getElementsByClassName('workspace')[0];
workspace.onwheel = resize;
let current_scale = 1;
function resize(E) {
E = E || window.event;
if (E.altKey) {
E.preventDefault();
let new_scale = Math.max(0.1, current_scale - E.deltaY / 360);
var btns = workspace.getElementsByClassName('element');
for(var i = 0; i <btns.length; i++) {
btns[i].style.setProperty('transform', 'scale(' + new_scale + ')');
}
current_scale = new_scale;
}
}
.viewport {
width: 80vw;
height: 80vh;
box-sizing: border-box;
overflow: scroll;
transform: scale(1);
transform-origin: 0 0;
}
.workspace {
position: relative;
width: 1000px;
height: 1000px;
overflow: hidden;
}
.element {
position: absolute;
width: 10px;
height: 10px;
}
.line-drawer
{
position:absolute;
height:1000px;
width:1000px;
}
<div class="viewport">
<div class="workspace">
<svg class="line-drawer">
<line x1="100px" x2="130px" y1="80px" y2="230px" style='stroke-width: 4px; stroke: black'></line>
</svg>
<button class="element" style="top: 100px; left: 150px"></button>
<button class="element" style="top: 80px; left: 100px"></button>
<button class="element" style="top: 230px; left: 130px"></button>
<button class="element" style="top: 100px; left: 250px"></button>
</div>
</div>
Scaling the individual elements like this will keep them in there position
let workspace = document.getElementsByClassName('workspace')[0];
workspace.onwheel = resize;
let current_scale = 1;
function resize(E) {
E = E || window.event
if (E.altKey) {
E.preventDefault();
let new_scale = Math.max(0.1, current_scale - E.deltaY / 360);
var btns = workspace.getElementsByClassName('element');
for(var i = 0; i <btns.length; i++) {
btns[i].style.setProperty('transform', 'scale(' + new_scale + ')');
}
current_scale = new_scale;
}
}
.viewport {
width: 80vw;
height: 80vh;
box-sizing: border-box;
overflow: scroll;
transform: scale(1);
}
.workspace {
position: relative;
width: 1000px;
height: 1000px;
overflow: hidden;
}
.element {
position: absolute;
width: 10px;
height: 10px;
}
<div class="viewport">
<div class="workspace">
<button class="element" style="top: 100px; left: 150px"></button>
<button class="element" style="top 80px; left: 100px"></button>
<button class="element" style="top: 230px; left: 130px"></button>
<button class="element" style="top: 100px; left: 250px"></button>
</div>
</div>

Change a value over a set amount of time with jQuery?

I'm working on a project that calls for a circular progress bar. I found one that will do the trick here:
http://codepen.io/shankarcabus/pen/GzAfb
But what I need to do is animate it on page load so that it will go up in value each time:
<div class="progress-pie-chart" data-percent="43">
So on "page1.htm", I need the data-percent value to automatically increase incrementally from 0-20. On "page2.htm" from 20-33, etc. I'm pretty new to jQuery, so I honestly have no idea where to begin on that.
How do I create a function that will increase the data-percent value over say, 500 milliseconds?
Using a setInterval we can produce something like. We also use some math to calculate the steps based on the fps to create a smooth animation. Decimals can also be used for the percent
var start = 0;
var end = 30;
var time = 800; //in ms
var fps = 30;
var increment = ((end-start)/time)*fps;
$('.progress-pie-chart')[0].dataset.percent = start;
var timer = setInterval(function() {
$('.progress-pie-chart')[0].dataset.percent = parseFloat($('.progress-pie-chart')[0].dataset.percent) + increment;
if (parseFloat($('.progress-pie-chart')[0].dataset.percent) >= end) {
clearInterval(timer);
}
var $ppc = $('.progress-pie-chart'),
percent = parseFloat($ppc[0].dataset.percent),
deg = 360 * percent / 100;
if (percent > 50) {
$ppc.addClass('gt-50');
}
$('.ppc-progress-fill').css('transform', 'rotate(' + deg + 'deg)');
$('.ppc-percents span').html(parseInt(percent, 10) + '%');
}, fps);
.progress-pie-chart {
width: 200px;
height: 200px;
border-radius: 50%;
background-color: #E5E5E5;
position: relative;
}
.progress-pie-chart.gt-50 {
background-color: #81CE97;
}
.ppc-progress {
content: "";
position: absolute;
border-radius: 50%;
left: calc(50% - 100px);
top: calc(50% - 100px);
width: 200px;
height: 200px;
clip: rect(0, 200px, 200px, 100px);
}
.ppc-progress .ppc-progress-fill {
content: "";
position: absolute;
border-radius: 50%;
left: calc(50% - 100px);
top: calc(50% - 100px);
width: 200px;
height: 200px;
clip: rect(0, 100px, 200px, 0);
background: #81CE97;
transform: rotate(60deg);
}
.gt-50 .ppc-progress {
clip: rect(0, 100px, 200px, 0);
}
.gt-50 .ppc-progress .ppc-progress-fill {
clip: rect(0, 200px, 200px, 100px);
background: #E5E5E5;
}
.ppc-percents {
content: "";
position: absolute;
border-radius: 50%;
left: calc(50% - 173.91304px/2);
top: calc(50% - 173.91304px/2);
width: 173.91304px;
height: 173.91304px;
background: #fff;
text-align: center;
display: table;
}
.ppc-percents span {
display: block;
font-size: 2.6em;
font-weight: bold;
color: #81CE97;
}
.pcc-percents-wrapper {
display: table-cell;
vertical-align: middle;
}
body {
font-family: Arial;
background: #f7f7f7;
}
.progress-pie-chart {
margin: 50px auto 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="progress-pie-chart" data-percent="0">
<div class="ppc-progress">
<div class="ppc-progress-fill"></div>
</div>
<div class="ppc-percents">
<div class="pcc-percents-wrapper">
<span>%</span>
</div>
</div>
</div>

Is it possible to skew HTML element by a number of pixels using CSS transform?

My problem is:
there's a block containing variable number of HTML elements. Something like this...
<ul class="list">
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
</ul>
This block must have a skew on the right side (the content must not be skewed). The horizontal size of this skew must be fixed. So adding CSS rules like...
.list {
position: relative;
background: #A0A0FF;
}
.list:after {
content: " ";
display: block;
position: absolute;
top: 0;
bottom: 0;
right: -10px;
width: 20px;
transform: skewX(-15deg);
background: #A0A0FF;
}
...won't do because in this case the skew will have variable horizontal size depending on the number of items in the list. The only solution that comes to my mind is to calculate the number of degrees in js. But this is kinda meh.
So my question is: is it possible to somehow skew an element by a number of pixels instead of degrees/radians using CSS?
You can achieve the same skew appearance by using a linear gradient on a pseudo-element.
*,
::after,
::before {
box-sizing: border-box;
margin: 0;
padding: 0;
}
ul {
width: 200px;
background: #663399;
margin: 25px auto;
list-style-type: none;
position: relative;
}
ul::after {
position: absolute;
content: "";
top: 0;
left: 100%;
background: linear-gradient(to bottom right, #663399 0%, #663399 50%, transparent 50%, transparent 100%);
width: 16px;
height: 100%;
}
<ul class="list">
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
</ul>
<ul class="list">
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
</ul>
Sorry if my message is irrelevant to this exact case, but once I searched for "CSS skew in pixels" and although neither this question is about what I tried to find (provide the exact width in px to skew), nor the accepted answer solves my problem, I still believe this can help someone someday.
As we know, transform: skew() receives only angles as a parameter.
In order to get the exact width when the angle is unknown, one should calculate the angle using arctangent. Luckily, JavaScript 1.0 Math provides atan2() method to return the arctangent (in radians) by given X and Y coordinates.
Thus, calculating the skew angle has the solution on JS.
The example below draws diagonal lines (via border-bottom/border-left) based on the dimensions of the underlying elements.
let prevY = null;
document.querySelectorAll('.a').forEach(el => {
const top = el.style.top;
const left = el.style.left;
const width = el.style.width;
const height = el.style.height;
const xEl = document.querySelector('#x' + el.id.substr(1));
xEl.style.top = top;
xEl.style.left = left;
xEl.style.width = width;
xEl.style.height = height;
applySkew(el);
});
window.addEventListener('resize', function(e) {
prevY = null;
document.querySelectorAll('.a').forEach(el => {
applySkew(el);
});
});
function applySkew(el) {
const xEl = document.querySelector('#x' + el.id.substr(1));
const top = el.style.top;
const w = el.offsetWidth;
const h = el.offsetHeight;
const directionUp = prevY && prevY != top;
prevY = top;
if(w < h) {
xEl.style.borderBottom = 'none';
xEl.style.borderLeft = 'black 1px solid';
xEl.style.transform = 'skewX(' + Math.atan2((directionUp ? -1 : 1) * w, h) + 'rad) translateX(' + (w / 2) + 'px)';
} else {
xEl.style.borderLeft = 'none';
xEl.style.borderBottom = 'black 1px solid';
xEl.style.transform = 'skewY(' + Math.atan2((directionUp ? -1 : 1) * h, w) + 'rad) translateY(-' + (h / 2) + 'px)';
}
}
html, body {
margin: 0;
height: 100%;
}
body > div {
margin: 5% 0 0 5%;
background: yellow;
position: relative;
height: 40%;
width: 90%;
}
body > div > div {
position: absolute;
box-sizing: border-box;
}
<div>
<div id="a0" class="a" style="
top: 0;
left: 0;
width: 7.5%;
height: 70%;
background-color: rgba(0,255,255,.5);
"></div>
<div id="a1" class="a" style="
top: 40%;
left: 7.5%;
width: 17.5%;
height: 30%;
background-color: rgba(0,255,255,.2);
"></div>
<div id="a2" class="a" style="
top: 40%;
left: 25%;
width: 37%;
height: 55%;
background-color: rgba(0,255,255,.4);
"></div>
<div id="a3" class="a" style="
top: 25%;
left: 62%;
width: 3%;
height: 70%;
background-color: rgba(0,255,255,.1);
"></div>
<div id="a4" class="a" style="
top: 25%;
left: 65%;
width: 35%;
height: 50%;
background-color: rgba(0,255,255,.6);
"></div>
<div id="x0"></div>
<div id="x1"></div>
<div id="x2"></div>
<div id="x3"></div>
<div id="x4"></div>
</div>
I don't know what you are after, But is this what you are searching for?
.list {
position: relative;
background-color: yellow;
}
.list:after {
content: " ";
display: block;
position: absolute;
background-color: blue;
top: 0;
bottom: 0;
right: 10px;
width: 20px;
transform: skewX(-15deg);
}
<ul class="list">
<li class="item">...</li>
<li class="item">...</li>
<li class="item">...</li>
</ul>

How to create circles around a circle with css, javascript?

I would like to create a circle (without any animation) which is surrounded by other circles, like this:
but i would like to build in a phonegap app, so i don't want to increase the file size to big.
somebody know a plugin/method or any other solution?
I searched on the internet, but the methods i found are increase the size of my files too big.
No one addressed the javascript aspect of this question. Below is a complete (albeit quick and dirty) web page that will draw 6 perfectly spaced circles around a parent circle's center using html, css3, and javascript; it uses pure javascript so no need to reference a jquery library. You should be able to see how you could easily extract methods from the code to control the number of satellite circles, their distance from the center of the parent, parent and satellite radii, satellite offset, etc:
var div = 360 / 6;
var radius = 150;
var parentdiv = document.getElementById('parentdiv');
var offsetToParentCenter = parseInt(parentdiv.offsetWidth / 2); //assumes parent is square
var offsetToChildCenter = 20;
var totalOffset = offsetToParentCenter - offsetToChildCenter;
for (var i = 1; i <= 6; ++i) {
var childdiv = document.createElement('div');
childdiv.className = 'div2';
childdiv.style.position = 'absolute';
var y = Math.sin((div * i) * (Math.PI / 180)) * radius;
var x = Math.cos((div * i) * (Math.PI / 180)) * radius;
childdiv.style.top = (y + totalOffset).toString() + "px";
childdiv.style.left = (x + totalOffset).toString() + "px";
parentdiv.appendChild(childdiv);
}
#parentdiv {
position: relative;
width: 150px;
height: 150px;
background-color: #ac5;
border-radius: 150px;
margin: 150px;
}
.div2 {
position: absolute;
width: 40px;
height: 40px;
background-color: #ac5;
border-radius: 100px;
}
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<div id="parentdiv"></div>
</body>
</html>
To make a circle, use border-radius: 50%. Then just position 6 circular divs with position: absolute around the larger circle.
Kind of like this: http://jsfiddle.net/yxVkk/
<div id="big-circle" class="circle big">
<div class="circle one"></div>
<div class="circle two"></div>
<div class="circle three"></div>
<div class="circle four"></div>
<div class="circle five"></div>
<div class="circle six"></div>
</div>
<style>
.circle {
border-radius: 50%;
width: 50px;
height: 50px;
background-color: red;
display: inline-block;
position: absolute;
}
.circle.big {
width: 150px;
height: 150px;
background-color: blue;
margin: 100px;
}
.one {
left: -25px;
top: -25px;
}
.two {
top: -60px;
left: 50px;
}
.three {
right: -25px;
top: -25px;
}
.four {
left: -25px;
bottom: -25px;
}
.five {
bottom: -60px;
left: 50px;
}
.six {
right: -25px;
bottom: -25px;
}
</style>
Using css you can try something like that. but use circle tag of HTML5 will give you a better result.
http://jsbin.com/etuzis/1/
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body>
<div class=div2 style='top:12px; left:45px;'></div>
<div class=div2 style='top:4px; left:160px;'></div>
<div class=div2 style='top:94px; left:210px;'></div>
<div class=div1></div>
</body>
</html>
CSS
.div1{
margin:40px 10px 10px 50px;
position:relative;
width:150px;
height:150px;
background-color:#ac5;
border-radius:100px;
}
.div2{
position:absolute;
width:40px;
height:40px;
background-color:#ac5;
border-radius:100px;
}
Adding border-radius:50% to a <div> that has an equal with and height then putting a background-color on it will make a circle out of CSS (light load).
.big_circle {
width:10em;
height:10em;
border-radius:50%;
background-color:blue;
}
You can then absolutely position the circle directly in the middle of the screen by using the position:absolute and negative margin trick.
.big_circle {
width:10em;
height:10em;
border-radius:50%;
background-color:blue;
position:absolute;
top:50%;
left:50%;
margin-left:-5em;
margin-top:-5em;
}
Create a class to take care of the styling for the smaller circles.
.little_circle {
width:3em;
height:3em;
border-radius:50%;
background-color:green;
position:relative;
}
Then add IDs (or any other way of identifying them) to position the relatively compared to the big circle.
#little_one {
bottom:1em;
right:2em;
}
#little_two {
bottom:6.5em;
left:3.5em;
}
#little_three {
bottom:7em;
left:9em;
}
// etc...
Here's a CodePen with a sample.
As somebody said in the comments, you have to set border-radius:50% and then, positioning absolutely. I've made a dummy jsfiddle for illustrate link:
circle{
width : 50px;
height : 50px;
border-radius : 50%;
background: red;
position : absolute;
top : 50px;
left : 150px;
}
.small_circle_1{
width : 20px;
height : 20px;
border-radius : 50%;
background: blue;
position : absolute;
top : -25px;
left : 15px;
}
.small_circle_2{
width : 20px;
height : 20px;
border-radius : 50%;
background: blue;
position : absolute;
top : 15px;
left : -25px;
}
.small_circle_3{
width : 20px;
height : 20px;
border-radius : 50%;
background: blue;
position : absolute;
top : 55px;
left : 15px;
}
.small_circle_4{
width : 20px;
height : 20px;
border-radius : 50%;
background: blue;
position : absolute;
top : 15px;
left : 55px;
}
To display a radial array of items, center them and use trigonometry to rotate them around the center. This assumes all the items share the same width and height.
Notes about this approach:
Multiple radials can reuse the JS function in a wide variety of configurations
There should only be one .radial_center (though the code could be updated to allow multiple layered centers, taking the diameter of the largest for calculations)
There can be multiple .radial_edge items, and the function automatically adjusts the angle of rotation
Trig functions and coefficients are adjusted so the first edge is always on top
data fields in the .radial wrapper can manually set diameters for the center and edge items, as well as the percentage gap between them, which calculates to the radius for the edge items from the center item
The center item can be hidden to create a "ring only" effect, though the center still needs to exist
Yes, any code written in jQuery or any other lib can be re-written in vanilla (or asm or binary). I just used jQuery for my own convenience :)
const ns = {
radial: (r) => {
//capture radial edges
let el = $(r),
e = el.children('.radial_edge');
//avoid div zero
if (e.length) {
//calc orbital angle and radius
let c = el.children('.radial_center'),
sa = -360 / e.length, //-360 rotates clockwise, 360 rotates counter
i = 0, //0 sets first child at top
cw = el.data('center') || c.width() || 100,
ew = el.data('edge'),
gap = el.data('gap') || .2;
//calc x,y and reposition each edge
e.each(function() {
let re = $(this),
ewa = ew || re.width() || 50,
rad = (cw + ewa) * (1 + gap),
x = Math.cos((sa * i) * (Math.PI / 180)) * rad * -1, //-1 flips vertically
y = Math.sin((sa * i) * (Math.PI / 180)) * rad * -1;
re.css({
inset: x + 'px 0 0 ' + y + 'px'
});
i++;
});
}
}
}
$(document).ready(() => {
//parse each radial group
$('.radial').each(function() {
ns.radial(this);
});
});
:root {
/* decorative */
--bs: 1px 1px 3px 0px grey;
--b-soft: thin solid silver;
font-family: monospace;
color: gray;
}
img {
display: block;
}
.hidden {
display: none;
}
.examples {
display: flex;
flex-wrap: wrap;
}
.radial {
/* required */
position: relative;
/* dev only */
margin: 1em auto;
border: 1px solid lightgray;
width: 350px;
aspect-ratio: 1/1;
border-radius: 50%;
}
.radial_center {
/* required */
width: fit-content;
aspect-ratio: 1/1;
position: absolute;
inset: 50%;
transform: translate(-50%, -50%);
/* decorative */
border-radius: 50%;
box-shadow: var(--bs);
border: var(--b-soft);
}
.radial_edge {
/* required */
position: absolute;
width: 50px;
aspect-ratio: 1/1;
margin: auto;
/* decorative */
border-radius: 50%;
box-shadow: var(--bs);
border: var(--b-soft);
opacity: .7;
display: flex;
justify-content: center;
align-items: center;
font-weight: 500;
font-size: 2em;
}
.bigger .radial_center {
width: 150px;
}
.bigger .radial_edge {
width: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="examples">
<div class="radial" data-gap=".3">
<img class="radial_center" src="https://picsum.photos/100" alt="center image" />
<div class="radial_edge">1</div>
<div class="radial_edge">2</div>
<div class="radial_edge">3</div>
<div class="radial_edge">4</div>
<div class="radial_edge">5</div>
</div>
<div class="radial bigger" data-gap=".05">
<img class="radial_center" src="https://picsum.photos/150" alt="center image" />
<img class="radial_edge" src="https://picsum.photos/100" alt="satellite image" />
<img class="radial_edge" src="https://picsum.photos/100" alt="satellite image" />
<img class="radial_edge" src="https://picsum.photos/100" alt="satellite image" />
</div>
<div class="radial" data-center="75" data-edge="75">
<div class="radial_center hidden"></div>
<div class="radial_edge">1</div>
<img class="radial_edge" src="https://picsum.photos/50" alt="satellite image" data-pos="1" />
<div class="radial_edge">3</div>
<img class="radial_edge" src="https://picsum.photos/50" alt="satellite image" data-pos="2" />
<div class="radial_edge">5</div>
<img class="radial_edge" src="https://picsum.photos/50" alt="satellite image" data-pos="3" />
</div>
</div>

Categories

Resources