I'm trying to figure out a possible solution on how to create a radar scanner effect using jQuery and CSS. Essentially, a semi-transparent triangle beam would rotate around the middle point of a div. Is this possible with jQuery or should I resort to some other means?
I prefer to not use animated gifs.
I'm trying to figure out a possible solution on how to create a radar scanner effect using jQuery and CSS. Essentially, a semi-transparent triangle beam would rotate around the middle point of a div. Is this possible with jQuery or should I resort to some other means?
I prefer to not use animated gifs.
- 1 is CSS3 an option? This can't be done in IE8 and should be fairly easy in pure CSS in other browsers. – John Dvorak Commented Aug 21, 2013 at 9:01
- 2 You should explain what you already tried to do... it is possible using a combination of jQuery/SVG animation techniques... this might help: stackoverflow.com/questions/2995643/… – Joum Commented Aug 21, 2013 at 9:03
- And yeah, jQuery can control CSS3 transformations if you really want to. – John Dvorak Commented Aug 21, 2013 at 9:03
- Anything is an option. – Johann Commented Aug 21, 2013 at 9:05
2 Answers
Reset to default 29You don't need jQuery in order to achieve a radar scanner
- For the infinite radar beam rotation use just CSS
animation
and CSSrotate
one full turn1turn
aslinear
andinfinite
timing. - Inside JavaScript, handle the dots opacity with requestAnimationFrame to continually get the current beam rotation angle, convert the dots x, y to angle, and calculate the opacity delta given the normalized differences in the two angles
const getCSSVal = (e, v) => e.style.getPropertyValue(v);
const mod = (n, m) => ((n % m) + m) % m; // Fix negative Modulo
const PI = Math.PI;
const TAU = PI * 2;
const radar = (elRadar) => {
const elBeam = elRadar.querySelector(".beam");
const elsDot = elRadar.querySelectorAll(".dot");
const update = () => {
const beamAngle = parseFloat(getComputedStyle(elBeam).getPropertyValue("rotate")) * PI / 180 || 0;
elsDot.forEach(elDot => {
const x = getCSSVal(elDot, "--x") - 0.5;
const y = getCSSVal(elDot, "--y") - 0.5;
const dotAngle = mod(Math.atan2(y, x), TAU);
const opacity = mod(dotAngle - beamAngle, TAU) / TAU;
elDot.style.opacity = opacity;
});
requestAnimationFrame(update);
};
update();
};
document.querySelectorAll(".radar").forEach(radar);
.radar {
position: relative;
overflow: hidden;
width: 300px;
aspect-ratio: 1;
background: #000 url(https://i.sstatic.net/vY6Tl.png) center / cover;
border-radius: 50%;
}
.beam {
position: absolute;
top: 0;
left: 0;
width: inherit;
aspect-ratio: inherit;
background: url(https://i.sstatic.net/GCbf1.png) center / cover;
animation: 5s rotate linear infinite;
}
@keyframes rotate {
100% {
rotate: 1turn;
}
}
.dot {
position: absolute;
left: calc(var(--x) * 100%);
top: calc(var(--y) * 100%);
border-radius: 50%;
width: 4px;
height: 4px;
margin: -2px;
background: #cf5;
box-shadow: 0 0 10px 5px rgba(100, 255, 0, 0.5);
opacity: 0;
}
<div class="radar">
<div class="beam"></div>
<div class="dot" style="--x:0.7; --y:0.2"></div>
<div class="dot" style="--x:0.2; --y:0.3"></div>
<div class="dot" style="--x:0.6; --y:0.1"></div>
<div class="dot" style="--x:0.4; --y:0.6"></div>
<div class="dot" style="--x:0.9; --y:0.7"></div>
</div>
CSS only demonstration
HTML:
<div id="radar">
<div class="beacon" id="beacon"></div>
<div class="beacon" id="beacon-75"></div>
<div class="beacon" id="beacon-50"></div>
<div class="beacon" id="beacon-25"></div>
<div class="circle" id="circle-big"></div>
<div class="circle" id="circle-medium"></div>
<div class="circle" id="circle-small"></div>
<div class="circle" id="dot"></div>
<div id="vertical"></div>
<div id="horizontal"></div>
</div>
CSS:
#radar {
position:relative;
width:400px;
height:400px;
margin:20px auto;
border:3px solid #0c0;
background-color:#020;
border-radius:50%;
}
#radar>* {position:absolute}
.beacon {
left:50%;
top:50%;
border-style:solid;
border-width:8px 200px 8px 0;
border-color:transparent;
margin-top:-8px;
transform-origin:0 50%;
}
#beacon {border-right-color:#0c0;animation:spin 2s 0s linear infinite}
#beacon-75 {border-right-color:rgba(0,204,0,0.75);animation:spin 2s 0.03s linear infinite}
#beacon-50 {border-right-color:rgba(0,204,0,0.5);animation:spin 2s 0.06s linear infinite}
#beacon-25 {border-right-color:rgba(0,204,0,0.25);animation:spin 2s 0.09s linear infinite}
.circle {
left:50%;
top:50%;
border:1px solid #0c0;
border-radius:50%;
}
#circle-big {
width:300px;
height:300px;
margin:-150px;
}
#circle-medium {
width:200px;
height:200px;
margin:-100px;
}
#circle-small {
width:100px;
height:100px;
margin:-50px;
}
#dot {
width:8px;
height:8px;
margin:-4px;
background-color:#0c0;
}
#vertical {
left:50%;
top:0;
bottom:0;
border-left:1px solid #0c0;
}
#horizontal {
top:50%;
left:0;
right:0;
border-top:1px solid #0c0;
}
@keyframes spin {
from {transform:rotate(0)}
to {transform:rotate(360deg)}
}
Please note that to support some browsers you will need to add vendor prefixes, but this by itself works in IE10 and Firefox.