How to make half the border of a circle transparent - javascript

I have a minigame that the user has 60 seconds to solve. To indicate the remaining time, I use a number that will start at 60 and start going down 1 per second until reaching 0. This number will be inside a transparent circular div with a border:
.circle {
width: 100px;
height: 100px;
border: 3px solid #2F4491;
border-radius: 100%;
}
I'm trying to make the border dissapear proportionally to the remaining time: The border will be fully visible at the beginning (60s remaining), only the left side visible when the user only has 30s remaining, and so on.
Any idea on how to achieve this?

Try this.
var time = 60;
var initialOffset = '440';
var i = 1
/* Need initial run as interval hasn't yet occured... */
$('.circle_animation').css('stroke-dashoffset', initialOffset-(1*(initialOffset/time)));
var interval = setInterval(function() {
$('h2').text(i);
if (i == time) {
clearInterval(interval);
return;
}
$('.circle_animation').css('stroke-dashoffset', initialOffset-((i+1)*(initialOffset/time)));
i++;
}, 1000);
.item {
position: relative;
float: left;
}
.item h2 {
text-align:center;
position: absolute;
line-height: 125px;
width: 100%;
}
svg {
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
}
.circle_animation {
stroke-dasharray: 440; /* this value is the pixel circumference of the circle */
stroke-dashoffset: 440;
transition: all 1s linear;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="item html">
<h2>0</h2>
<svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
<g>
<title>Layer 1</title>
<circle id="circle" class="circle_animation" r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#78cef1" fill="none"/>
</g>
</svg>
</div>

Set border-right-color and border-bottom-color to transparent when the time is below 30s. Also, you will have to rotate the object -45deg, so you will have it half-right and half-left.
When fade out, do the same with bottom and top.

Related

svg width in morphing animation

Hell0, I can't get my svg to take the whole width of the screen!
it doesn't matter if they are distorted or not because the idea of this use is a kind of morphing to change the background color of my page
here is my css:
.container {
height: 5000px; /* hauteur de la page */
}
.img {
width: 100%;
height: 100vh;
object-fit: fill;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
transition: opacity 0s ease-in-out;
opacity: 0;
}
.img.transition {
transition: opacity 0s ease-in-out;
}
.img.active {
opacity: 1;
}
the complete code is here : codepen
Thank you
I think adding viewBox parameter to your svg's might help. The 3th and 4th number give it a relative width and height. In the example below, giving it 100% w x h.
Check this out for more info -> https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox
Also you cannot use the same CSS properties for HTML nodes, also for SVG. Properties like object-fit, margin, position,etc... wil not work on SVG elements, unfortunately.
More info on that here -> https://css-tricks.com/svg-properties-and-css/
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50" />
</svg>

half circle text on the edges [duplicate]

I have 2 DIV's as shown below and I've been trying to get the text between the two circles to wrap around the inner circle as shown on the attacthed image. I have not been able to achieve the desired result.
HTML
<div id="outer-circle">
This is just a test logo name
<div id="inner-circle">
</div><!-- End Inner Circle -->
</div><!-- End Outer Circle -->
CSS
* {
margin: 0 auto;
}
#inner-circle {
width: 200px;
height: 200px;
border-radius: 100%;
background-color: green;
margin-top: 28px;
position: relative;
}
#outer-circle {
width: 300px;
height: 300px;
border-radius: 100%;
background-color: blue;
margin-top: 50px;
text-align center;
text-align: left;
}
Click here to see current but undesired result
Example of desired result
See this post by Chris Coyier in which he separates each character of text into <span>s and rotates each one in turn using CSS rotation:
.char1 {
-webkit-transform: rotate(6deg);
-moz-transform: rotate(6deg);
-ms-transform: rotate(6deg);
-o-transform: rotate(6deg);
transform: rotate(6deg);
}
.char2 {
-webkit-transform: rotate(12deg);
-moz-transform: rotate(12deg);
-ms-transform: rotate(12deg);
-o-transform: rotate(12deg);
transform: rotate(12deg);
}
...etc
Or use Dirk Weber's csswarp.js Service which pretty much does the same but uses javascript to generate the html and css for you. (csswarp.js on GitHub)
Or use SVG text on a path as in this example from useragentman.com
<svg id="myShape" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<path id="path1"
fill="none" stroke="black" stroke-width="1"
d="M 212,65
C 276,81 292,91 305,103 361,155
363,245 311,302 300,314 286,324
271,332 248,343 227,347 202,347
190,346 174,343 163,339 143,333">
</path>
</defs>
<text id="myText">
<textPath xlink:href="#path1" >
<tspan dy="0.3em">C is for Cookie, That's Good Enough For Me!</tspan>
</textPath>
</text>
</svg>
Or...
Use an image.
Use base info from https://css-tricks.com/set-text-on-a-circle/
BUT with a simplifications and without any additional libs.
And it will work with any text you type...
var lettering = function(node,text){
var str = typeof text=='undefined'
?node.textContent
:text;
node.innerHTML='';
var openTag = '<span>';
var closeTag = '</span>';
var newHTML = openTag;
var closeTags = closeTag;
for(var i=0,iCount=str.length;i<iCount;i++){
newHTML+=str[i]+openTag;
closeTags+=closeTag;
}
node.innerHTML = newHTML+closeTags;
}
lettering(
document.getElementById('text'),
Math.round(Math.random()*1000) + ' : Hello world!!!'
);
.badge {
position: relative;
width: 400px;
border-radius: 50%;
transform: rotate(-50deg);
}
h1 span {
font: 26px Monaco, MonoSpace;
height: 200px;
position: absolute;
width: 20px;
left: 0;
top: 0;
transform-origin: bottom center;
transform: rotate(10deg);
}
<div class='badge'>
<h1 id="text">Any custom text you type...</h1>
</div>

How can i link this to an event on leaflet?

I've find a beautiful button in html/css that I have add on my leaflet map. (Adding the lines to my previous code)
I am blocked because this is not a real <button> and i don't find anything on Stackoverflow which answer to my question :(
I would like to add any functions which use Javascript, even a simple like add a Pop up when click on the button or anything which related to adding a little bit of interactivity like when click on the button, the zoom go on a specific place of the map.
I just want to know how to link this button to JavaScript.
Find below the section of my code that i want be linked to a function.
#import url('https://fonts.googleapis.com/css?family=Poppins:900i');
* {
box-sizing: border-box;
}
body {
height: 100vh;
display: flex;
justify-content: right;
align-items: right;
}
.wrapper {
display: flex;
justify-content: center;
z-index: 10000;
}
.cta {
right: auto;
margin-left: 500px;
top: 520px;
position: relative;
left: 500px;
display: flex;
padding: 3px 31px;
text-decoration: none;
font-family: 'Poppins', sans-serif;
font-size: 30px;
color: white;
background: #ffa500;
transition: 1s;
box-shadow: 6px 6px 0 black;
transform: skewX(-15deg);
}
.cta:focus {
outline: none;
}
.cta:hover {
transition: 0.5s;
box-shadow: 10px 10px 0 #FBC638;
}
.cta span:nth-child(2) {
transition: 0.5s;
margin-right: 0px;
}
.cta:hover span:nth-child(2) {
transition: 0.5s;
margin-right: 45px;
}
span {
transform: skewX(15deg)
}
span:nth-child(2) {
width: 20px;
margin-left: 30px;
position: relative;
top: 12%;
}
/**************SVG****************/
path.one {
transition: 0.4s;
transform: translateX(-60%);
}
path.two {
transition: 0.5s;
transform: translateX(-30%);
}
.cta:hover path.three {
animation: color_anim 1s infinite 0.2s;
}
.cta:hover path.one {
transform: translateX(0%);
animation: color_anim 1s infinite 0.6s;
}
.cta:hover path.two {
transform: translateX(0%);
animation: color_anim 1s infinite 0.4s;
}
/* SVG animations */
#keyframes color_anim {
0% {
fill: white;
}
50% {
fill: #FBC638;
}
100% {
fill: white;
}
}
<div class="wrapper">
<a class="cta" href="#">
<span>Datacenter SG</span>
<span>
<svg width="66px" height="43px" viewBox="0 0 66 43" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="arrow" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path class="one" d="M40.1543933,3.89485454 L43.9763149,0.139296592 C44.1708311,-0.0518420739 44.4826329,-0.0518571125 44.6771675,0.139262789 L65.6916134,20.7848311 C66.0855801,21.1718824 66.0911863,21.8050225 65.704135,22.1989893 C65.7000188,22.2031791 65.6958657,22.2073326 65.6916762,22.2114492 L44.677098,42.8607841 C44.4825957,43.0519059 44.1708242,43.0519358 43.9762853,42.8608513 L40.1545186,39.1069479 C39.9575152,38.9134427 39.9546793,38.5968729 40.1481845,38.3998695 C40.1502893,38.3977268 40.1524132,38.395603 40.1545562,38.3934985 L56.9937789,21.8567812 C57.1908028,21.6632968 57.193672,21.3467273 57.0001876,21.1497035 C56.9980647,21.1475418 56.9959223,21.1453995 56.9937605,21.1432767 L40.1545208,4.60825197 C39.9574869,4.41477773 39.9546013,4.09820839 40.1480756,3.90117456 C40.1501626,3.89904911 40.1522686,3.89694235 40.1543933,3.89485454 Z" fill="#FFFFFF"></path>
<path class="two" d="M20.1543933,3.89485454 L23.9763149,0.139296592 C24.1708311,-0.0518420739 24.4826329,-0.0518571125 24.6771675,0.139262789 L45.6916134,20.7848311 C46.0855801,21.1718824 46.0911863,21.8050225 45.704135,22.1989893 C45.7000188,22.2031791 45.6958657,22.2073326 45.6916762,22.2114492 L24.677098,42.8607841 C24.4825957,43.0519059 24.1708242,43.0519358 23.9762853,42.8608513 L20.1545186,39.1069479 C19.9575152,38.9134427 19.9546793,38.5968729 20.1481845,38.3998695 C20.1502893,38.3977268 20.1524132,38.395603 20.1545562,38.3934985 L36.9937789,21.8567812 C37.1908028,21.6632968 37.193672,21.3467273 37.0001876,21.1497035 C36.9980647,21.1475418 36.9959223,21.1453995 36.9937605,21.1432767 L20.1545208,4.60825197 C19.9574869,4.41477773 19.9546013,4.09820839 20.1480756,3.90117456 C20.1501626,3.89904911 20.1522686,3.89694235 20.1543933,3.89485454 Z" fill="#FFFFFF"></path>
<path class="three" d="M0.154393339,3.89485454 L3.97631488,0.139296592 C4.17083111,-0.0518420739 4.48263286,-0.0518571125 4.67716753,0.139262789 L25.6916134,20.7848311 C26.0855801,21.1718824 26.0911863,21.8050225 25.704135,22.1989893 C25.7000188,22.2031791 25.6958657,22.2073326 25.6916762,22.2114492 L4.67709797,42.8607841 C4.48259567,43.0519059 4.17082418,43.0519358 3.97628526,42.8608513 L0.154518591,39.1069479 C-0.0424848215,38.9134427 -0.0453206733,38.5968729 0.148184538,38.3998695 C0.150289256,38.3977268 0.152413239,38.395603 0.154556228,38.3934985 L16.9937789,21.8567812 C17.1908028,21.6632968 17.193672,21.3467273 17.0001876,21.1497035 C16.9980647,21.1475418 16.9959223,21.1453995 16.9937605,21.1432767 L0.15452076,4.60825197 C-0.0425130651,4.41477773 -0.0453986756,4.09820839 0.148075568,3.90117456 C0.150162624,3.89904911 0.152268631,3.89694235 0.154393339,3.89485454 Z" fill="#FFFFFF"></path>
</g>
</svg>
</span>
</a>
</div>
When you want to display a popup or something on a leaflet map, your posted code should contain your leaflet code. Also it is very helpful when you create a live demo, for example on jsfiddle.
But now to your question:
You can add a event over the default way addEventListener or with the leaflet library to a element. Here I use it over the leaflet library:
But first add a id to your button <div class="wrapper" id='testId'>
var button = document.getElementById('testId')
L.DomEvent.on(button,'click',function(e){
console.log('Button clicked')
});
When you want to open a popup on a specific location call:
L.DomEvent.on(button,'click',function(){
var latlng = map.getCenter(); // or [47.478058, 9.720154]
L.popup().setContent('Test').setLatLng(latlng).openOn(map)
});
I think your next question would be "How can I zoom to a marker":
This is a little bit difficult, because we need to know to which marker you want to zoom. This means that you have to save your marker to a global variable, so it can used in the button click event.
var latlng = map.getCenter(); // or [47.478058, 9.720154]
var marker = L.marker(latlng).addTo(map);
L.DomEvent.on(button,'click',function(){
var zoomlvl = 16;
map.flyTo(marker.getLatLng(),zoomlvl)
});

Consistent filling of SVG's rectangles

How to make each of these squares filled with red colour consistently left to right; and when one filled with red, previous will have default colour?
#foo > rect {
height: 32px;
width: 32px;
}
<svg id=foo height=32 width=160>
<rect x=0 y=0 />
<rect x=64 y=0 />
<rect x=128 y=0 />
</svg>
This animation must be repeatable.
If you are open to a CSS solution you can simulate such effect using background animation where you can easily scale to any number of square but without fading:
.rect {
height: 32px;
width:calc(40px*10); /* 10 Squares*/
background:
/* This gradient will make the red color to fade from the first to the last*/
linear-gradient(red,red) 0 0/32px 100% no-repeat,
/* This gradient will create the squares (32px of black then 8px of transparent)*/
repeating-linear-gradient(to right,black 0 32px,transparent 32px 40px);
margin:0 5px;
animation:change 10s steps(10) infinite;
}
#keyframes change{
to {
background-position:calc(100% + 32px) 0,0 0;
}
}
<div class="rect"></div>
With CSS variable you can control the different values:
.rect {
--s: 32px; /* Square size */
--nb: 10; /* Square number */
--gap: 8px; /* gap between squares */
--c1:black;
--c2:red;
height: var(--s);
width:calc((var(--gap) + var(--s))*var(--nb));
background:
linear-gradient(var(--c2),var(--c2)) 0 0/var(--s) 100% no-repeat,
repeating-linear-gradient(to right,var(--c1) 0 var(--s),#fff var(--s) calc(var(--s) + var(--gap)));
margin:5px;
animation:change calc(var(--nb)*1s) steps(var(--nb)) infinite;
}
#keyframes change{
to {
background-position:calc(100% + var(--s)) 0,0 0;
}
}
<div class="rect"></div>
<div class="rect" style="--nb:8;--s:50px;--c1:green;--c2:yellow"></div>
<div class="rect" style="--nb:15;--s:10px;--c2:blue"></div>
Use CSS keyframes:
#foo > rect {
height: 32px;
width: 32px;
animation: anim 3s infinite;
}
#foo > rect:nth-of-type(1){
animation-delay: 0s;
}
#foo > rect:nth-of-type(2){
animation-delay: 1s;
}
#foo > rect:nth-of-type(3){
animation-delay: 2s;
}
#keyframes anim{
0% { fill: black; }
50% { fill: red; }
100% { fill: black; }
}
<svg id=foo height=32 width=160>
<rect x=0 y=0 />
<rect x=64 y=0 />
<rect x=128 y=0 />
</svg>

Vanilla JavaScript, interact with a single DOM element which is part of a class group without affecting the others of the group

I'm trying to create a number of items (clouds in this case) that once reached the rightmost side of the browser, thir position is reset to 0 (leftmost side of the screen) or less and the loop should continue.
Each cloud's position should be reset independently from the others, but in my case what is happening is that everytime a cloud reaches the target, they all get reset and I can't figure out why.
I have a series of DOM elements:
<div class="cloud" id="c1"></div>
<div class="cloud" id="c2"></div>
<div class="cloud" id="c3"></div>
In my JS file I have an array containing all 3 DOM elements:
var clouds = document.querySelectorAll(".cloud");
I have first loop to setup some css attributes:
for(let i=0; i < clouds.length; ++i){
setUp(clouds[i]);
}
function setUp(item){
item.style.transform = `translate3d(0px, 0px, 0px)`;
}
And then I loop through it running this method:
function increment(item){
let xVal = Number(item.style.transform.split('px')[0].split('(')[1]);
let newVal = xVal >= window.innerWidth ? 0 : xVal + 1;
item.style.transform = `translate3d(${newVal}px, 0px, 0px)`;
item.style.background = 'red';
}
setInterval(function(){
clouds.forEach(increment);
},700)
CORRECTION:
As pointed out by #AlexWayne, it was a minor issue that was solved by separating the positions of the items in the setUp function.
In the form of:
item.style.transform = `translate3d(${i * 100}px, 0px, 0px)`;
as shown here https://jsfiddle.net/36m1oatv/14/ .
Although it is strange the reason why a similar version as the following
https://jsfiddle.net/kwucnht9/1/ doesn't work.
Hello and welcome to stackoverflow!
I figured you might like a pure CSS solution since most things you are doing in your javascript was manipulating the css anyway.
Let me know if you need further assistance.
#keyframes example {
0% {
transform: translateX(0);
}
100% {
transform: translateX(100vh);
}
}
.cloud {
background-color: grey;
width: 50px;
height: 50px;
margin: 10px;
transition: transform .7s ease-in-out;
animation-name: example;
animation-duration: 4s;
animation-iteration-count: infinite;
}
.cloud:nth-child(1) {
background-color: tomato;
animation-delay: 0.5s;
}
.cloud:nth-child(2) {
background-color: hotpink;
animation-delay: 1s;
}
.cloud:nth-child(3) {
background-color: greenyellow;
animation-delay: 1.5s;
}
<div class="cloud" id="c1"></div>
<div class="cloud" id="c2"></div>
<div class="cloud" id="c3"></div>
The reason your clouds all reset at the same time is because each cloud is being transformed identically each time.
function setUp(item) {
item.style.transform = `translate3d(0px, 0px, 0px)`; // set all clouds to 0 on the x-axis.
}
setInterval(function(){
clouds.forEach(increment); // Every 700ms, shift each cloud along the x-axis by 1px.
},700)
Because your initial offset positioning is set identically by setUp, the translate3d(${newVal}px, 0px, 0px) is identical for all clouds. If you were to change setUp so that each cloud is transformed on the x-axis by a different initial amount then your routine would work.
(function() {
var clouds = document.querySelectorAll(".cloud");
for (let i = 0; i < clouds.length; ++i) {
setUp(clouds[i]);
}
function setUp(item) {
var rando = Math.random() * 250; // set a random spot between 0 and 250px.
item.style.transform = `translate3d(${rando}px, 0px, 0px)`;
}
function increment(item) {
let xVal = Number(item.style.transform.split('px')[0].split('(')[1]);
let newVal = xVal >= window.innerWidth/3 ? 0 : xVal + 5;
item.style.transform = `translate3d(${newVal}px, 0px, 0px)`;
item.style.background = 'red';
}
setInterval(function() {
clouds.forEach(increment);
}, 100)
})();
.cloud {
border: 1px solid black;
width: 200px;
height: 25px;
}
.cloud:nth-child(0){
position: absolute;
top: 280px;
left: 80px;
}
.cloud:nth-child(1){
position: absolute;
top: 75px;
left: 206px;
}
.cloud:nth-child(2){
position: absolute;
top: 150px;
left: -12px;
}
<div class="cloud" id="c1"></div>
<div class="cloud" id="c2"></div>
<div class="cloud" id="c3"></div>
The reason your clouds won't snap back to the left edge is because you have the left edge positioned absolutely, so they only reset to their normal, non-offset, positions.

Categories