Centered text in a transparent circle? - javascript

I have a percentage animation which the number counts up while the outer stroke completes. This animation works perfectly but I need to have the text centered both vertically and horizontally, also the inner circle transparent. Any idea how I could do this?
function perCirc($el, end, i) {
if (end < 0)
end = 0;
else if (end > 100)
end = 100;
if (typeof i === 'undefined')
i = 0;
var curr = (100 * i) / 360;
$el.find(".perCircStat").html(Math.round(curr) + "%");
if (i <= 180) {
$el.css('background-image', 'linear-gradient(' + (90 + i) + 'deg, transparent 50%, #ccc 50%),linear-gradient(90deg, #ccc 50%, transparent 50%)');
} else {
$el.css('background-image', 'linear-gradient(' + (i - 90) + 'deg, transparent 50%, #00cc00 50%),linear-gradient(90deg, #ccc 50%, transparent 50%)');
}
if (curr < end) {
setTimeout(function() {
perCirc($el, end, ++i);
}, 1);
}
}
.perCirc {
position: relative;
text-align: center;
width: 240px;
height: 240px;
border-radius: 100%;
background-color: #00cc00;
/* the color of the percent */
}
.perCirc .perCircInner {
position: relative;
top: 10px;
left: 10px;
text-align: center;
width: 220px;
height: 220px;
border-radius: 100%;
background-color: hsla(0, 0%, 73%, 1.00);
/* the color of the inner circel */
}
.perCirc .perCircInner div {
position: relative;
color: #4E1414;
}
.perCirc .perCircStat {
font-size: 30px;
margin: 0 auto;
}
<div id="sellPerCirc" class="perCirc">
<div class="perCircInner">
<div class="perCircStat">0%</div>
<div>Complete</div>
</div>
</div>

Add these attributes to your perCircInner class
display: flex;
flex-direction: column;
justify-content: center;

Related

How to rotate and scale cards while swiping

As I'm trying to make a carousel that rotates I wonder how to move the cards rotated and it scales from a minimum of 0.8(left and right cards) and a maximum scale of 1(center card) when the user keeps swiping
Scale:
left = 0.8
center = 1
right = 0.8
I'm trying to solve on how to rotate them using transform and z-index properties. The cards will also rotate however I'm still trying to make a formula on how to make a function that makes the cards rotate
Any alternative solutions are accepted The animation is
similar to this carousel from codepen however it doesn't swipe Carousel Rotate
const CONTAINER_FLEX = document.querySelector('.container-flex');
const items = document.querySelectorAll('.item');
let touchStartX = 0;
let touchMoveX = 0;
let count = 0;
let current_translate = 0;
let previous_translate = 0;
CONTAINER_FLEX.addEventListener('touchstart', (event) => {
touchStartX = event.touches[0].pageX;
});
CONTAINER_FLEX.addEventListener('touchmove', (event) => {
touchMoveX = event.touches[0].pageX;
current_translate = previous_translate + (touchMoveX - touchStartX);
console.log(current_translate);
items[1].style.transform = `translateX(${current_translate}px)`;
});
CONTAINER_FLEX.addEventListener('touchend', () => {
current_translate = touchMoveX - touchStartX;
previous_translate = current_translate;
});
*,
::before,
::after {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
font-family: Arial, Helvetica, sans-serif;
line-height: 1.5;
background-color: #131b24;
}
.main-container {
padding: 30px 0;
height: 300px;
width: 900px;
border-top: 1px solid #444;
border-bottom: 1px solid #444;
overflow: hidden;
background-color: white;
}
.container-flex {
height: 100%;
display: flex;
transition: transform 400ms cubic-bezier(0.165, 0.84, 0.44, 1);
}
.item {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
min-width: 300px;
max-width: 300px;
}
.item h1 {
font-size: 40px;
color: white;
}
/* ITEMS */
.item-1 {
background-color: #2c3e50;
transform: translateX(100px);
z-index: 1;
}
.item-2 {
background-color: #3498db;
z-index: 2;
}
.item-3 {
background-color: #1abc9c;
transform: translateX(-100px);
z-index: 1;
}
<div class="main-container">
<div class="container-flex" id="container-flex">
<div class="item item-1">
<h1>1</h1>
</div>
<div class="item item-2">
<h1>2</h1>
</div>
<div class="item item-3">
<h1>3</h1>
</div>
</div>
</div>
Here is a working example https://jsfiddle.net/4ue5sgm9/3/
I wonder how to move the cards when it goes from 0 to 200 however
Have all your cards in an array.
var cards = [ thing1, thing2, thing3];
Use % - modulus operator, it's the secret for cycling back to the beginning
cardIndex = (cardIndex + 1) % cards.length
Copied from the chat. I made it verbose for clarity
scrollLeft() {
nextIndex = items.indexOf(displayed[2])
nextIndex = ++nextIndex % items.length-1
displayed = items[nextIndex]
nextIndex = ++nextIndex % items.length-1;
displayed.push( items[nextIndex] );
nextIndex = ++nextIndex % items.length-1;
displayed.push( items[nextIndex] )
}
P.S. Write and iterator for items array. An iterator stops after the last item. An iterator is why "for (x in thisArray)" works. BUT write the next() function to return "% this.length-1" instead => now you have a never-ending looper. All that code just above goes away.

Loop not overriding style of a div

function lineComplete() {
let line = document.getElementById("line");
for (let percentage = 0; percentage <= 100; percentage++) {
setTimeout(function() {
line.style.width = `${percentage}%`;
}, percentage * 25);
if (percentage === 100) {
undo();
}
}
function undo() {
for (let percent = 100; percent >= 0; percent--) {
setTimeout(function() {
line.style.width = `${percent}%`;
}, percent * 25);
}
}
}
#outLine {
width: 60%;
height: 20px;
margin: 10px 0px;
background-image: linear-gradient(to right, #f12711, #f12711);
border-radius: 20px;
}
#line {
background-image: linear-gradient(to right, #f12711, #f5af19);
height: 100%;
width: 100%;
border-radius: 20px;
}
<body onload="lineComplete()">
<div id="outLine">
<div id="line"></div>
</div>
</body>
In the above snippet, I am trying to show a loader-like effect which I am able to achieve. The problem is that when the width of line is 100%, I am trying to fire the function undo. This also works fine. There is a loop in undo which decreases the width of line and gradually bring its width to 0%. The loop also works fine as I have tried to run it after replacing its contents with alert() and it worked fine. But with the present situation, the loop is not resizing the line. I think that it is not able to override the styles.
You can simplify your code like this. No forloop and setTimeout needed.
function lineComplete() {
let line = document.getElementById("line");
line.classList.add("active");
line.addEventListener("transitionend", () => {
line.classList.remove("active");
});
}
#outLine {
width: 60%;
height: 20px;
margin: 10px 0px;
background-image: linear-gradient(to right, #f12711, #f12711);
border-radius: 20px;
overflow: hidden;
}
#line {
background-image: linear-gradient(to right, #f12711, #f5af19);
height: 100%;
width: 0%;
border-radius: 20px;
transition: 2s linear;
}
#line.active {
width: 100%;
}
<body onload="lineComplete()">
<div id="outLine">
<div id="line"></div>
</div>
</body>
Also can be done with only animations:
#outLine {
width: 60%;
height: 20px;
margin: 10px 0px;
background-image: linear-gradient(to right, #f12711, #f12711);
border-radius: 20px;
overflow: hidden;
}
#line {
background-image: linear-gradient(to right, #f12711, #f5af19);
height: 100%;
width: 0%;
border-radius: 20px;
transition: 4s linear;
}
#line.active {
animation: linecomplete 2s linear forwards;
/* you can use "infinite" instead of "forwards" if you want */
}
#keyframes linecomplete {
50% {
width: 100%;
}
}
<div id="outLine">
<div id="line" class="active"></div>
</div>
function lineComplete() {
let line = document.getElementById("line");
for (let percentage = 0; percentage <= 100; percentage++) {
setTimeout(function() {
line.style.width = `${percentage}%`;
if (line.style.width === "100%") {
undo();
}
}, percentage * 25);
}
function undo() {
for (let percent = 100; percent >= 0; percent--) {
setTimeout(function() {
line.style.width = `${100 - percent}%`;
}, percent * 25);
}
}
}
#outLine {
width: 60%;
height: 20px;
margin: 10px 0px;
background-image: linear-gradient(to right, #f12711, #f12711);
border-radius: 20px;
}
#line {
background-image: linear-gradient(to right, #f12711, #f5af19);
height: 100%;
width: 100%;
border-radius: 20px;
}
<body onload="lineComplete()">
<div id="outLine">
<div id="line"></div>
</div>
</body>
The problem was that when you decrease, the later iterations are scheduled to run earlier than the earlier iterations. Let's negate percentage (100 - percentage) and it will work.

Box-shadow positioned based on window scroll algorithm

I have this amateur function that changes the box-shadow on a group of elements based on the window.scrollTop position and element offset. When the user scrolls up or down from the photos, the box-shadow will move down or up respectively. So it gives the illusion of perspective. When these photo elements are in the center of the screen, the box-shadow is centered.
Right now it's not ideal and by that I mean it isn't very symmetrical and doesn't feel right. I know it because my "golden-ratio" (Not the actual Phy golden ratio, i just used this as a variable name) is just a random number. I know there is a way to use my variables to set this up properly I just can't come up with it. Looking for golden ratio (box-shadow vertical offset) to be from about -20 to 20, 0 when centered, seems to look okay.
So my question is can anyone optimize my algorithm so that the box-shadow changes as described above but more realistic?
This should only happen inside a certain vertical scroll window so
that this function isn't running while the photos are off the screen (already pretty much implemented)
The box-shadow change is subtle so there is not a HUGE shadow above or below it.
In my real code I have another function that changes the photos to be the same height as the width on window resize. Here I just have a fixed height of 160px.
Here is my code (modified to give a barebones example). Feel free to redo my function from scratch if that is cleaner.
var halfHeight;
var eleHalfHeight;
var scrollTop;
var photosOffset;
var profOffset
var distPhotos;
var goldenRatio;
$(window).scroll(function() {
halfHeight = $(window).height() / 2;
eleHalfHeight = $('.photo').height() / 2;
scrollTop = $(window).scrollTop();
photosOffset = $('.photos').offset().top - halfHeight + eleHalfHeight;
distPhotos = (photosOffset - scrollTop);
if (distPhotos < photosOffset && distPhotos > -photosOffset) {
goldenRatio = distPhotos / 25;
$('.photo-frame').css('box-shadow', '0px ' + (goldenRatio + 6) + 'px 4px 2px #c9c9c9');
};
});
* {
box-sizing: border-box;
}
body {
margin: 0;
}
.wrapper {
display: flex;
align-items: center;
min-height: 500vh;
background-color: #fff;
}
.photos {
display: flex;
width: 100%;
justify-content: space-around;
margin-bottom: 60px;
background-color: #fff;
}
.photos .photo-frame {
width: 25%;
height: 160px;
border: 20px solid whitesmoke;
box-shadow: 0px 0px 4px 2px gray;
background-color: #000;
}
.photos .photo-frame .photo {
width: 100%;
background-color: #000;
z-index: 1;
position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<section class="photos">
<div class="photo-frame">
<div class="photo"></div>
</div>
<div class="photo-frame">
<div class="photo"></div>
</div>
<div class="photo-frame">
<div class="photo"></div>
</div>
</section>
</div>
Is it perfectâ„¢?
Nope.
Do I like it better than yours?
A little bit.
Will it help you?
I hope so, since I think it's easier to tweak — at least this was my intention. You tell me.
let wH = $(window).height(),
sO = 210, // shadowOffset (px); 50 => from -25 to +25
tO = 4, // topOffset (px) 0 => vertical symmetry,
lO = 4, // leftOffset (px) 0 => horizontal symmetry
moveshadow = function() {
let diff = $(window).scrollTop() - $(this).offset().top,
tOH = $(this)[0].offsetHeight,
should = (-diff < wH) && (diff < tOH),
factor = should ?
-((diff / wH + 1) / (1 + tOH / wH) - .5) * sO + tO :
0;
if (should) {
$(this).css({
"box-shadow": lO +"px " +
factor +
"px 8px -2px rgba(0,0,0,.1), " + lO + "px " +
(factor + sO / 20) +
"px 17px 4px rgba(0,0,0,.07), " + lO + "px " +
(factor - sO / 20) +
"px 22px 8px rgba(0,0,0,.06), " + lO/2 + "px " +
factor / 20 +
"px 21px 1px rgba(0,0,0,.12)"
})
}
};
$(window)
.on('resize', function() {
wH = $(window).height()
})
.on('scroll resize', function() {
$('.photo-frame').each(moveshadow)
})
body {
background-color: #fff;
text-align: center;
}
.wrapper {
padding: 120vh 30px;
}
.photos {
display: flex;
align-items: center;
justify-content: space-between;
}
.photo {
width: 20vw;
height: 32.36vw;
background-color: #eee;
}
.photo-frame {
padding: 20px;
border: 1px solid #eee;
box-sizing: border-box;
}
#media(min-width: 1000px) {
.wrapper {
width: 900px;
display: inline-block;
}
.photo {
width: 200px;
height: 323.6px;
background-color: #eee;
}
}
#media(min-width: 641px) {
.photo-frame:first-child { transform: translateY(-10vw) }
.photo-frame:last-child { transform: translateY(10vw) }
}
#media(max-width: 640px) {
.photos {
flex-direction: column;
}
.photo {
width: 60vw;
height: 37.08vw;
background-color: #eee;
}
.photo-frame {
margin: 7.5vw 0;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<section class="photos">
<div class="photo-frame">
<div class="photo"></div>
</div>
<div class="photo-frame">
<div class="photo"></div>
</div>
<div class="photo-frame">
<div class="photo"></div>
</div>
</section>
</div>
playground
:: }<(((*> ::)

How to create this range bar using JavaScript?

.range {-moz-box-sizing: border-box;box-sizing: border-box;-webkit-background-clip: padding-box;background-clip: padding-box;vertical-align: top;outline: none;line-height: 1;-webkit-appearance: none;-webkit-border-radius: 4px;border-radius: 4px;border: none;height: 2px;-webkit-border-radius: 0;border-radius: 0;-webkit-border-radius: 3px;border-radius: 3px;background-image: -webkit-gradient(linear, left top, left bottom, from(#ddd), to(#ddd));background-image: -webkit-linear-gradient(#ddd, #ddd);background-image: -moz-linear-gradient(#50b1f9, #50b1f9);background-image: -o-linear-gradient(#ddd, #ddd);background-image: linear-gradient(#50b1f9,#50b1f9);background-position: left center;-webkit-background-size: 100% 2px;background-size: 100% 2px;background-repeat: no-repeat;overflow: hidden;height: 31px;}
.range::-moz-range-track {position: relative;border: none;background-color: #50b1f9;height: 2px;border-radius: 30px;box-shadow: none;top: 0;margin: 0;padding: 0;}
.range::-webkit-slider-thumb {cursor: pointer;-webkit-appearance: none;position: relative;height: 29px;width: 29px;background-color: #fff;border: 1px solid #ddd;-webkit-border-radius: 30px;border-radius: 30px;-webkit-box-shadow: none;box-shadow: none;top: 0;margin: 0;padding: 0;}
.range::-moz-range-thumb {cursor: pointer;position: relative;height: 15px;width: 15px;background-color:#fff;border: 1px solid #ddd;border-radius: 30px;box-shadow: none;margin: 0;padding: 0}
.range::-webkit-slider-thumb:before {position: absolute;top: 13px;right: 0px;left: -1024px;width: 1024px;height: 2px;background-color: #50b1f9;;content: '';margin: 0;padding: 0;}
.range:disabled {opacity: 0.3;cursor: default;pointer-events: none;}
<input type="range" class="range">
I have to make this range bar and when I slide the months will also change accordingly. I tried making it into css but for changing range I would need JavaScript.
var range = document.getElementById("range"),
progress = document.getElementById("progress"),
handle = document.getElementById("handle"),
valueBox = document.getElementById("value"),
movable = false,
offsetX = range.offsetLeft,
rangeWidth = range.offsetWidth,
handleWidth = handle.offsetWidth,
max = 100, left, mouseX, value;
function move(e) {
if ( movable === true ) {
left = e.clientX - offsetX;
handle.style.left = left - ( handleWidth / 2 ) + "px";
progress.style.width = left + "px";
if ( left >= rangeWidth ) {
handle.style.left = rangeWidth - ( handleWidth / 2 ) + "px";
progress.style.width = rangeWidth + "px";
} if ( left <= 0 ) {
handle.style.left = "-" + handleWidth / 2 + "px";
progress.style.width = "0px";
}
value = Number(parseFloat(progress.style.width) / ( rangeWidth / max )).toFixed(0);
valueBox.textContent = value;
}
};
function on(e) {
movable = true;
mouseX = e.clientX;
};
function off() {
movable = false;
};
handle.addEventListener("mousedown", on, false);
window.addEventListener("mousemove", move, false);
window.addEventListener("mouseup", off, false);
* { margin: 0; padding: 0; border: 0; outline: 0; }
body { background-color: #FF0000; }
#range {
width: 350px;
height: 14px;
background-color: #242424;
margin: 100px auto 15px;
border-radius: 50px;
position: relative;
}
#progress {
position: absolute;
top: 0;
left: 0;
height: 100%;
background-color: #00A79D;
border-radius: 50px;
}
#handle {
position: absolute;
top: -3px;
height: 20px;
width: 20px;
background-color: #eee;
border-radius: 50px;
cursor: pointer;
}
#handle:hover, #handle:active {
background-color: #ddd;
}
#value-box {
text-align: center;
font: 14px arial;
line-height: 35px;
color: #eee;
width: 170px;
height: 35px;
background-color: rgba(0, 0, 0, .2);
margin: auto;
border-radius: 2px;
}
<div id="range">
<div id="progress"></div>
<div id="handle"></div>
</div>
<div id="value-box">Range bar Value : <span id="value">0</span></div>
Check output in Snippet Also.
Finally Output :

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>

Categories

Resources