How do I make the eyes follow the object? - javascript

Im not entirely sure what's wrong with my code. The eyes (iris) seem to be locked on the bottom right corner of the eyes and are rotating around on that fixed position. I've looked at tutorials online and tried variety of codes, but none seem to work. The end goal that I would like to achieve is to have the eyes follow the given block.
Thank you in advance!
window.addEventListener('mousemove', eyeball);
function eyeball() {
const eye = document.querySelectorAll('.eye');
eye.forEach(function(eye){
let x = (eye.getBoundingClientRect().left) + (eye.clientWidth / 2);
let y = (eye.getBoundingClientRect().top) + (eye.clientHeight / 2);
let radian = Math.atan2(event.pageX - x, event.pageY - y);
let rotation = (radian * (180 / Math.PI) * -1) + 270;
eye.style.transform = "rotate("+rotation+"deg)";
});
}
.eye-container {
position: absolute;
display: flex;
justify-content: center;
width: 100%;
margin-top: 20px;
background: pink;
}
.eyeball{
position: relative;
width: 100px;
height: 90px;
border-radius: 50%;
background: white;
margin-right: 20px;
box-shadow: inset 0 0 5px black;
overflow: hidden;
}
.pupil{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 50px;
height: 45px;
border-radius: 50%;
background: black;
border: 10px solid purple;
box-sizing: border-box;
}
.block{
position: absolute;
top: 50%;
width: 100px;
height: 100px;
background: red;
}
<section class="eye-container">
<div class="eyelids eyelid-left"></div>
<div class="eyelids eyelid-right"></div>
<div class=" eyeball left-eye">
<div class=" eye pupil left-pupil"></div>
</div>
<div class="eyeball right-eye">
<div class="eye pupil right-pupil"></div>
</div>
</section>
<div class="block"></div>

What you want is probably something more like this. This will translate the pupils into place, giving it that "following look".
function eyeball(target_x, target_y) {
const eye = document.querySelectorAll('.eye');
eye.forEach(function(eye){
let x = (eye.getBoundingClientRect().left) + (eye.clientWidth / 2);
let y = (eye.getBoundingClientRect().top) + (eye.clientHeight / 2);
let radian = Math.atan2(target_x - x, target_y - y);
let transform_x = Math.round(Math.sin(radian) * 100);
let transform_y = Math.round(Math.cos(radian) * 100);
eye.style.transform = "translate(" + transform_x + "%, " + transform_y + "%)";
});
}
You will also need to change the initial style of the pupils to get a correct offset for the position change.
.pupil{
margin-left: 25px;
margin-top: 25px;
width: 50px;
height: 45px;
border-radius: 50%;
background: black;
border: 10px solid purple;
box-sizing: border-box;
}

Related

Making a Javascript music app based on tutorial, hit roadblock

I am currently trying to create a music app based on the following video: https://youtu.be/OafpiyPa63I?t=13127
I am at the linked timestamp, and I have written the code exactly as shown in the video, but for some reason, when I try to seek, the input is set back to 0 and therefore so is the song. My code for this part:
let currentStart = document.getElementById('currentStart');
let currentEnd = document.getElementById('currentEnd');
let seek = document.getElementById('seek');
let bar2 = document.getElementById('bar2');
let dot = document.getElementsByClassName('dot')[0];
music.addEventListener('timeupdate', () => {
let music_curr = music.currentTime;
let music_dur = music.duration;
let min1 = Math.floor(music_dur / 60);
let sec1 = Math.floor(music_dur % 60);
if (sec1 < 10) {
sec1 = `0${sec1}`;
};
currentEnd.innerText = `${min1}:${sec1}`;
let min2 = Math.floor(music_curr / 60);
let sec2 = Math.floor(music_curr % 60);
if (sec2 < 10) {
sec2 = `0${sec2}`;
};
currentStart.innerText = `${min2}:${sec2}`;
let progressBar = parseInt((music_curr / music_dur) * 100);
seek.value = progressBar;
let seekbar = seek.value;
bar2.style.width = `${seekbar}%`;
dot.style.left = `${seekbar}%`;
});
seek.addEventListener('change', () => {
music.currentTime = seek.value * music.duration / 100;
});
<div class="bar">
<input type="range" id="seek" min="0" max="100">
<div class="bar2" id="bar2"></div>
<div class="dot"></div>
</div>
header .master_play .bar {
position: relative;
width: 43%;
height: 2px;
background: rgb(105,105,170,.1);
margin: 0px 15px 0px 10px;
}
header .master_play .bar .bar2 {
position: absolute;
background: #36e2ec;
width: 0%;
height: 100%;
top: 0;
transition: 1s linear;
}
header .master_play .bar .dot {
position: absolute;
width: 5px;
height: 5px;
background: #36e2ec;
border-radius: 50%;
left: 0%;
top: -1.5px;
transition: 1s linear;
}
header .master_play .bar .dot::before {
content: '';
position: absolute;
width: 15px;
height: 15px;
border: 1px solid #36e2ec;
border-radius: 50%;
left: -6.5px;
top: -6.5px;
box-shadow: inset 0px 0px 3px #36e2ec;
}
header .master_play .bar input {
position: absolute;
width: 100%;
top: -7px;
left: 0;
cursor: pointer;
z-index: 999999999999;
opacity: .5;
}
I'm not sure if I am in the wrong, or if the tutorial is outdated.
I figured out it was the platform I was running the code on. Somewhere it had clashed, so I was able to move it to a new host and it worked.

How to add a Vertical line at the end of a percentage bar HTML/Javascript

I am using the following HTML/Javascipt code to make the classic percentage bar.
function update() {
var element = document.getElementById("myprogressBar");
var width = 1;
var identity = setInterval(scene, 10);
function scene() {
if (width >= 70) {
clearInterval(identity);
} else {
width++;
element.style.width = width + '%';
element.innerHTML = width * 1 + '%';
}
}
}
#Progress_Status {
width: 50%;
background-color: #ddd;
}
#myprogressBar {
width: 1%;
height: 35px;
background-color: #4CAF50;
text-align: center;
line-height: 32px;
color: black;
}
<!DOCTYPE html>
<html>
<body>
<h3>Example of Progress Bar Using JavaScript</h3>
<p>Download Status of a File:</p>
<div id="Progress_Status">
<div id="myprogressBar">1%</div>
</div>
<br>
<button onclick="update()">Start Download</button>
</body>
</html>
What I would like to obtain and I am trying to achieve with .innerHTML is the following situation
The vertical line has to appear at the same level of the specified percentage.
For the vertical bar I used an added div nested inside the #Progress_Status container. It's styled to be absolute positioned and to change its offset in % in sync with the progress bar width.
For it to work, its container was set to position:relative as the reference frame.
function update() {
//fetches the vertical bar elements
var vbar = document.querySelector("#Progress_Status .percverticalbar");
var element = document.getElementById("myprogressBar");
var width = 1;
var identity = setInterval(scene, 10);
function scene() {
if (width >= 70) {
clearInterval(identity);
} else {
width++;
//updates the left offset of the vertical bar
vbar.style.left = `${width}%`;
element.style.width = width + '%';
element.innerHTML = width * 1 + '%';
}
}
}
#Progress_Status {
width: 50%;
background-color: #ddd;
position: relative;
}
.percverticalbar{
position: absolute;
height: 100px;
width: 5px;
background: gray;
top: -25px;
left: 0;
}
#myprogressBar {
width: 1%;
height: 35px;
background-color: #4CAF50;
text-align: center;
line-height: 32px;
color: black;
margin: 50px 0;
}
<h3>Example of Progress Bar Using JavaScript</h3>
<p>Download Status of a File:</p>
<div id="Progress_Status">
<div id="myprogressBar">1%</div>
<div class="percverticalbar"></div>
</div>
<br>
<button onclick="update()">Start Download</button>
You could just add an :after pseudo element and add the following styles to it. Keep in mind that the parent, in the case #myprogressBar should be relatively positioned.
#myprogressBar {
width: 1%;
height: 35px;
background-color: #4CAF50;
text-align: center;
line-height: 32px;
color: black;
position: relative;
}
#myprogressBar:after {
width: 5px;
height: 80px;
background: #333;
content: '';
position: absolute;
right: -5px;
top: 50%;
transform: translateY(-50%);
border-radius: 5px;
}

setting line bars on the circumference of a circle

I'm trying to create the below picture using CSS and javascript.
I'm successfully creating the semi-circle, but I have no idea how I can align the different line bars around the circumference of the circle. I pray to the CSS gods some of you can help me in my quest.
This is the code I have so far
.roll-degrees{
position: absolute;
top: 0px;
z-index: 1;
}
.roll-curve{
width:400px;
height:120px;
border:solid 3px #000;
border-color: black transparent transparent transparent;
border-radius: 50%/120px 120px 0px 0;
}
<div class="roll-degrees">
<div class="roll-curve"></div>
</div>
Updated based on the answer: Now I'm trying to display the arrow at the bottom of the circle. Code below. Is it possible I need to add/subtract the dimensions of the arrow?
.roll-degrees-arrow{
--width: 3px;
--height: 16px;
position: absolute;
width: 0;
height: 0;
border-left: 15px solid transparent;
border-right: 15px solid transparent;
border-bottom: 25px solid white;
z-index: 1;
--arrow-angle-direction: 1; /* default towards right*/
top: calc(50% - var(--height));
left: calc(50% - var(--width) / 2);
transform:
rotate(calc(var(--arrow-angle-direction) * var(--arrow-angle)))
translateY(calc(-1 * var(--circle-radius)))
;
}
<div class="roll-degrees-wrapper">
<div class="roll-degrees">
<div class="roll-degrees-arrow"></div>
...
</div>
</div>
Initial Setup
First, it's easier to do the math using a proper circle rather than an oval, so let's make the roll-curve element a circle (then we can crop the rest using a container). I've also added an additional wrapper around the whole thing that can be used to cut the size, while the original wrapper (roll-degrees) will be the appropriate size for the full circle in order to make tick positioning easier.
Ticks
Then the approach is to control the exact location of each tick by applying absolute positioning (starting at the circle's center) and moving the tick using transform: translateY(). Center all of the ticks in the middle of the roll-curve circle, rotate each, and translate each out to the perimeter of the circle from there. By rotating first, we can just translate each tick up by the radius of the circle and "up" will be in the appropriate direction.
Marker
As for setting the position of the marker dynamically, you can use largely the same approach as for the ticks (using the same CSS styling). You'll just need a way of translating a value to an angle (which can be done fairly simply---see the example below for details) and an angle direction.
The example below includes a range input, but you can provide a value to the marker any way you like.
Example
const minValue = 0;
const maxValue = 100;
function getAngleForValue(value) {
const angleRange = 90;
const angleCenter = angleRange / 2;
return value / maxValue * angleRange - angleCenter;
}
const marker = document.querySelector("#marker");
function setMarkerPosition(value) {
const angle = getAngleForValue(value);
const absAngle = Math.abs(angle);
const angleDirection = Math.sign(angle);
marker.style.setProperty("--tick-angle", `${absAngle}deg`);
marker.style.setProperty("--tick-angle-direction", angleDirection);
}
const markerRangeInput = document.querySelector("#marker-range-input");
markerRangeInput.min = minValue;
markerRangeInput.max = maxValue;
markerRangeInput.value = (maxValue - minValue) / 2;
markerRangeInput.addEventListener("change", (event) => {
setMarkerPosition(event.target.value)
})
* {
box-sizing: border-box;
}
body {
background-color: blue;
}
.roll-degrees-wrapper {
--circle-radius: 200px;
height: calc(var(--circle-radius) / 2);
position: relative;
overflow: hidden;
--tick-1-angle: 45deg;
--tick-2-angle: 30deg;
--tick-3-angle: 15deg;
--tick-4-angle: 0deg; /* middle */
}
.roll-degrees {
box-sizing: content-box;
--size: calc(var(--circle-radius) * 2);
width: var(--size);
height: var(--size);
padding: 16px;
position: relative;
}
.roll-curve {
--size: calc(var(--circle-radius) * 2);
width: var(--size);
height: var(--size);
border: solid 3px #000;
border-color: transparent;
border-top-color: white;
border-radius: 50%;
}
.tick {
--width: 3px;
--height: 16px;
width: var(--width);
height: var(--height);
background-color: white;
position: absolute;
--v-offset: var(--height);
--h-offset: var(--width);
top: calc(50% - var(--v-offset));
left: calc(50% - var(--h-offset) / 2);
--tick-angle-direction: 1;
transform:
rotate(calc(var(--tick-angle-direction) * var(--tick-angle)))
translateY(calc(-1 * var(--circle-radius)))
;
transform-origin: bottom;
}
.tick--tall {
--height: 24px;
}
.tick:nth-child(1),
.tick:nth-child(2),
.tick:nth-child(3) {
--tick-angle-direction: -1;
}
.tick:nth-child(1),
.tick:nth-child(7) {
--tick-angle: var(--tick-1-angle);
}
.tick:nth-child(2),
.tick:nth-child(6) {
--tick-angle: var(--tick-2-angle);
}
.tick:nth-child(3),
.tick:nth-child(5) {
--tick-angle: var(--tick-3-angle);
}
.tick:nth-child(4) {
--tick-angle: var(--tick-4-angle);
}
.tick.marker {
--marker-half-size: 14px;
--marker-full-size: calc(var(--marker-half-size) * 2);
--v-offset: var(--marker-half-size);
--h-offset: var(--marker-full-size);
--tick-angle: 0deg;
background-color: transparent;
width: 0;
height: 0;
border: var(--marker-half-size) solid transparent;
--marker-color: red;
border-top-color: var(--marker-color);
border-bottom-color: var(--marker-color);
transform-origin: center;
}
<div class="roll-degrees-wrapper">
<div class="roll-degrees">
<div class="tick tick--tall"></div>
<div class="tick"></div>
<div class="tick tick--tall"></div>
<div class="tick"></div>
<div class="tick tick--tall"></div>
<div class="tick"></div>
<div class="tick tick--tall"></div>
<div id="marker" class="marker tick"></div>
<div class="roll-curve"></div>
</div>
</div>
<input id="marker-range-input" type="range">
Note: You'll probably want to do a bit better styling on the marker or use an icon of some sort, but this serves as a simple example.

css rotation of 2 elements with different width to remain on the same distance

I have 2 elements that I position one of them with the offsetLeft and offsetTop of the other one. When there is no rotation they position fine, but when there is rotation they are losing their position relative to each other, because they rotate around their center. Is there a way to fix this and if there is some formula can you also explain it?
Examples:http://jsfiddle.net/9t6n8dmk/8/
//firstExample without rotation
<div class ="first-element" id="first-element">
</div>
<div class="second-element" id="second-element">
</div>
//secondExample with rotation
<div class ="first-element-rotation" id="first-element-rotation">
</div>
<div class="second-element-rotation" id="second-element-rotation">
</div>
let firstElement = document.getElementById("first-element");
let secondElement = document.getElementById("second-element");
secondElement.style.top = firstElement.offsetTop + "px";
secondElement.style.left = firstElement.offsetLeft + "px";
let firstElementRotation = document.getElementById("first-element-rotation");
let secondElementRotation = document.getElementById("second-element-rotation");
secondElementRotation.style.top = firstElementRotation.offsetTop + "px";
secondElementRotation.style.left = firstElementRotation.offsetLeft + "px";
.first-element{
background-color: black;
height: 50px;
width: 150px;
}
.second-element{
background-color: red;
height: 50px;
width: 50px;
position:absolute;
}
.first-element-rotation{
background-color: black;
height: 50px;
width: 150px;
margin-top:100px;
transform: rotate(30deg);
}
.second-element-rotation{
background-color: red;
height: 50px;
width: 50px;
position:absolute;
transform: rotate(30deg);
}
Setting transform-origin property would help:
let firstElement = document.getElementById("first-element");
let secondElement = document.getElementById("second-element");
secondElement.style.top = firstElement.offsetTop + "px";
secondElement.style.left = firstElement.offsetLeft + "px";
let firstElementRotation = document.getElementById("first-element-rotation");
let secondElementRotation = document.getElementById("second-element-rotation");
secondElementRotation.style.top = firstElementRotation.offsetTop + "px";
secondElementRotation.style.left = firstElementRotation.offsetLeft + "px";
.first-element {
background-color: black;
height: 50px;
width: 150px;
}
.second-element {
background-color: red;
height: 50px;
width: 50px;
position: absolute;
}
.first-element-rotation {
background-color: black;
height: 50px;
width: 150px;
margin-top: 100px;
transform-origin: 0 100%;
transform: rotate(30deg);
}
.second-element-rotation {
background-color: red;
height: 50px;
width: 50px;
position: absolute;
transform-origin: 0 100%;
transform: rotate(30deg);
}
//firstExample without rotation
<div class="first-element" id="first-element">
</div>
<div class="second-element" id="second-element">
</div>
//secondExample with rotation
<div class="first-element-rotation" id="first-element-rotation">
</div>
<div class="second-element-rotation" id="second-element-rotation">
</div>
A solution may be to group the 2 objects together with a <div> element and rotate that element instead.

Bootstrap + jQuery: Resizing diagram based on screen width

I made a diagram that changes its size based on the screen width (recreated (poorly) in the fiddle), but when I use this code on my page, the final circle/glyph falls to the following line when I decrease the screen width, when it should stay on the same line (as in the fiddle).
My fiddle
Here's my code:
html
<div class="glyphicon-belt">
<div id="rectangle"></div>
<div class="container circle-container circle-1">
<i class="icon-steak" style="font-size: 60px"></i>
</div>
<div class="container circle-container circle-2">
<i class="icon-brain" style="font-size: 60px"></i>
</div>
<div class="container circle-container circle-3">
<i class="icon-happy" style="font-size: 60px"></i>
</div>
</div>
css
.circle-container {
background-color: #FDA220;
width: 100px;
height: 100px;
border-radius: 100px;
text-align: center;
display: inline-block;
line-height: 100px;
margin-top: -60px;
}
.glyphicon-belt {
width: 50%;
left: 25%;
position: absolute;
text-align: center;
margin-top: 100px;
// background-color: black;
}
#rectangle {
width: 80%;
margin-left: 10%;
height: 20px;
background: #E7292A;
}
.circle-1 {
margin-right: 26%;
}
.circle-2 {
margin-right: 26%;
}
.circle-3 {
// margin-right: -5%;
}
.glyph-connect {
// left-margin: 25%;
text-align: center;
padding: 0px;
background-color: black;
}
jQuery
var screen = $(window).width();
var fontRatio = 60 / screen;
var circleRatio = 100 / screen;
var barRatio = 20 / screen;
$(window).on('resize', function() {
var screen = $(window).width();
var fontSize = screen * fontRatio;
var circleSize = screen * circleRatio;
var lineHeight = circleSize + "px";
var barHeight = screen * barRatio
$(".icon-steak").css("font-size", fontSize);
$(".icon-brain").css("font-size", fontSize);
$(".icon-happy").css("font-size", fontSize);
$(".circle-container").css("width", circleSize);
$(".circle-container").css("height", circleSize);
$(".circle-container").css("line-height", lineHeight);
$("#rectangle").css("height", barHeight);
});
If I understand your question right and playing around with it, it looks like you need to fix the circle-3:
.circle-3 {
margin-right: 1%;
}
Not sure why you had it commented out, but that it seems to fix the problem when you uncomment it and play with the %'s.

Categories