I'm currently trying to make a website that displays markers with its own specific text.
When a user clicks on the marker, it displays the text.
I've copied some code online and trying to mess around with it. Unfortunately, I'm not too experience with javascript. I was wondering if anyone would be able to help.
This is what I have so far:
HTML (I don't think there's any problems here):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>MarkerWeb</title>
<link rel="stylesheet" href="style.css">
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
<body>
<div id="container">
<div id="image-wrapper" data-captions='{"coords": [{"top":250,"left":200,"text":"iMac 1"},{"top":250,"left":540,"text":"iMac 2"}]}'>
<!-- layout.jpg is just a picture of a layout/floorplan -->
<img src="layout.jpg" alt=""/>
</div>
</div>
</body>
<script type="text/javascript" src="script.js"></script>
</html>
Javascript (The part I'm having a hard time with):
var Markers = {
fn: {
addMarkers: function() {
var target = $('#image-wrapper');
var data = target.attr('data-captions');
var captions = $.parseJSON(data);
var coords = captions.coords;
for (var i = 0; i < coords.length; i++) {
var obj = coords[i];
var top = obj.top;
var left = obj.left;
var text = obj.text;
$('<div class="marker"><div class="pin"><span class="popuptext" id="myPopup">' + text + '</span></div><div class="pin-effect"></div></div>').css({
top: top,
left: left
}).appendTo(target);
}
},
//This is the part I'm having trouble with.
showBeaconInfo: function() {
$('body').on('click', '.marker', function() {
var $marker = $(this),
$caption = $('popuptext', $marker);
if ($caption.is(':hidden')) {
$caption.show();
} else {
$caption.toggle("show");
}
});
}
},
init: function() {
this.fn.addMarkers();
this.fn.showBeaconInfo();
}
};
function clickBeacon() {
var popup = document.getElementById("myPopup");
popup.classList.toggle("show");
}
$(function() {
Markers.init();
});
CSS (I don't think there's any problems here):
body {
background: #e6e6e6;
}
#image-wrapper {
width: 800px;
height: 760px;
position: relative;
margin: 2em auto;
background: #f6f6f6;
border: 2px solid #ddd;
}
#image-wrapper img {
display: block;
margin: 25px auto;
}
.map-bg {
background: url(images/map-bg.jpg) no-repeat;
background-position: 0px 0px;
background-size: auto;
width: 100%;
height: 440px; /*adjust to the height of your image*/
position: relative;
}
.marker {
width: 100px;
height: 100px;
position: absolute;
/*top: 130px; /*positions our marker*/
/*left: 200px; /*positions our marker*/
display: block;
}
.pin {
width: 20px;
height: 20px;
position: relative;
top: 38px;
left: 38px;
background: rgba(5, 124, 255, 1);
border: 2px solid #FFF;
border-radius: 50%;
z-index: 1000;
cursor: pointer;
display: inline-block;
}
.pin-effect {
width: 100px;
height: 100px;
position: absolute;
top: 0;
display: block;
background: rgba(5, 124, 255, 0.6);
border-radius: 50%;
opacity: 0;
animation: pulsate 2400ms ease-out infinite;
}
#keyframes pulsate {
0% {
transform: scale(0.1);
opacity: 0;
}
50% {
opacity: 1;
}
100% {
transform: scale(1.2);
opacity: 0;
}
}
/* The actual popup (appears on top) */
.pin .popuptext {
visibility: hidden;
width: 160px;
background-color: #555;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 8px 0;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -80px;
}
/* Popup arrow */
.pin .popuptext::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #555 transparent transparent transparent;
}
/* Toggle this class when clicking on the popup container (hide and show the popup) */
.pin .show {
visibility: visible;
-webkit-animation: fadeIn 1s;
animation: fadeIn 1s
}
/* Add animation (fade in the popup) */
#-webkit-keyframes fadeIn {
from {opacity: 0;}
to {opacity: 1;}
}
#keyframes fadeIn {
from {opacity: 0;}
to {opacity:1 ;}
}
You need to update your showBeaconInfo function in 2 ways:
1) Fix the selector for $caption to grab the class popuptext by adding a period
2) Using the jquery function toggleClass to add or remove the class "show" on the popuptext, the css is setup to either use visibility: hidden or visibility: visible
showBeaconInfo: function() {
$('body').on('click', '.marker', function() {
var $marker = $(this);
var $caption = $('.popuptext', $marker); //needs period to indicate class
$caption.toggleClass('show'); //adding the class "show" will display the text
});
}
For Example:
var Markers = {
fn: {
addMarkers: function() {
var target = $('#image-wrapper');
var data = target.attr('data-captions');
var captions = $.parseJSON(data);
var coords = captions.coords;
for (var i = 0; i < coords.length; i++) {
var obj = coords[i];
var top = obj.top;
var left = obj.left;
var text = obj.text;
$('<div class="marker"><div class="pin"><span class="popuptext" id="myPopup">' + text + '</span></div><div class="pin-effect"></div></div>').css({
top: top,
left: left
}).appendTo(target);
}
},
//This is the part I'm having trouble with.
showBeaconInfo: function() {
$('body').on('click', '.marker', function() {
var $marker = $(this);
var $caption = $('.popuptext', $marker); //needs period to indicate class
$caption.toggleClass('show'); //adding the class "show" will display the text
});
}
},
init: function() {
this.fn.addMarkers();
this.fn.showBeaconInfo();
}
};
function clickBeacon() {
var popup = document.getElementById("myPopup");
popup.classList.toggle("show");
}
$(function() {
Markers.init();
});
body {
background: #e6e6e6;
}
#image-wrapper {
width: 800px;
height: 760px;
position: relative;
margin: 2em auto;
background: #f6f6f6;
border: 2px solid #ddd;
}
#image-wrapper img {
display: block;
margin: 25px auto;
}
.map-bg {
background: url(images/map-bg.jpg) no-repeat;
background-position: 0px 0px;
background-size: auto;
width: 100%;
height: 440px;
/*adjust to the height of your image*/
position: relative;
}
.marker {
width: 100px;
height: 100px;
position: absolute;
/*top: 130px; /*positions our marker*/
/*left: 200px; /*positions our marker*/
display: block;
}
.pin {
width: 20px;
height: 20px;
position: relative;
top: 38px;
left: 38px;
background: rgba(5, 124, 255, 1);
border: 2px solid #FFF;
border-radius: 50%;
z-index: 1000;
cursor: pointer;
display: inline-block;
}
.pin-effect {
width: 100px;
height: 100px;
position: absolute;
top: 0;
display: block;
background: rgba(5, 124, 255, 0.6);
border-radius: 50%;
opacity: 0;
animation: pulsate 2400ms ease-out infinite;
}
#keyframes pulsate {
0% {
transform: scale(0.1);
opacity: 0;
}
50% {
opacity: 1;
}
100% {
transform: scale(1.2);
opacity: 0;
}
}
/* The actual popup (appears on top) */
.pin .popuptext {
visibility: hidden;
width: 160px;
background-color: #555;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 8px 0;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -80px;
}
/* Popup arrow */
.pin .popuptext::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #555 transparent transparent transparent;
}
/* Toggle this class when clicking on the popup container (hide and show the popup) */
.pin .show {
visibility: visible;
-webkit-animation: fadeIn 1s;
animation: fadeIn 1s
}
/* Add animation (fade in the popup) */
#-webkit-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div id="image-wrapper" data-captions='{"coords": [{"top":250,"left":200,"text":"iMac 1"},{"top":250,"left":540,"text":"iMac 2"}]}'>
<!-- layout.jpg is just a picture of a layout/floorplan -->
<img src="layout.jpg" alt="" />
</div>
</div>
Related
I am trying to create a linear animation with pipes just like the flappy bird game. When I have one single pipe, I see a random gap and it works well, but when I clone all the pipes, there is no longer a gap at a random position.
How can I give the gaps in the pipe a random position when I have multiple pipes, and why is it not working as expected?
var block = document.getElementById("block");
//clone the pipe multiples times
var blockClone;
for (var i = 0; i < 4; i++) {
blockClone = block.cloneNode(true);
// the true is for deep cloning
//append all clones to original pipe
block.appendChild(blockClone);
//remove animtion from clones
blockClone.style.animationName = "none";
}
//gap inbetween each pipe
var hole = document.getElementById("hole");
var holeClone;
for (var i = 0; i < 4; i++) {
holeClone = hole.cloneNode(true);
// the true is for deep cloning
//append all clones to original pipe
blockClone.appendChild(hole);
block.appendChild(hole);
//remove animtion from clones
holeClone.style.animationName = "none";
hole.addEventListener('animationiteration', () => {
var random = -((Math.random() * 300) + 150);
hole.style.top = random + "px";
});
}
body {
text-align: center;
position: fixed;
width: 100%;
height: 100%;
}
* {
padding: 0;
margin: 0;
}
#game {
width: 100%;
height: 500px;
border: 1px solid red;
margin: auto;
overflow: hidden;
}
/* pipe version 1 */
#block {
width: 60px;
height: 500px;
background-color: green;
background-image: url("https://l.dropbox.com/s/4jz7uq4e25o8su5/sketch-1664244879.png?dl=0");
background-size: cover;
position: absolute;
left: 100px;
animation: block 5s infinite linear;
}
#hole {
width: 60px;
height: 210px;
background-color: red;
position: absolute;
left: 0px;
top: -10px;
/* animation: block 5s infinite
linear;*/
background-image: url("https://dldropbox.com/s/j7enawgtuepj7au/sketch-166428805830.png?dl=0");
background-size: cover;
}
#character {
width: 40px;
height: 40px;
background-color: none;
position: absolute;
top: 100px;
left: 40px;
border-radius: ;
z-index: 1;
background-color: red;
}
}
#overlay {
position: fixed;
display: none;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: black;
cursor: none;
opacity: 0.3;
text-align: center;
}
/* used to prevent user from tapping even after the game has ended*/
.mainoverlay {
position: fixed;
display: block;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
cursor: none;
opacity: 0;
}
#blokhold {
animation: block 5s infinite linear;
}
#keyframes block {
0% {
left: 350px
}
100% {
left: -890px
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="game">
<div id="blokhold">
<div id="block">
<div id="hole"></div>
</div>
</div>
<div id="character"></div>
</div>
I have set up a switcher on my website to toggle between normal mouse / pointer & a Lego hand as a cursor and a head as pointer. However, I can only get the cursor to show when clicking the switcher. How can I also add this pointer
(cursor: url(https://cdn.shopify.com/s/files/1/0571/7137/8349/files/pointer.png?v=1644096049), pointer;)
It should be assigned to the following classes:
a, button, input, input, button, a, input, .slider, .round
I have then also added a snippet, which lets the switcher / checkbox stay on checked...
(You can see that on this video [password is 12345678]: https://easyupload.io/gknxoi)
However after a reload of the page for example, the switcher stays on checked, but the cursor doesn't show up...
var cbs = document.querySelectorAll('input[type=checkbox]');
for (var i = 0; i < cbs.length; i++) {
cbs[i].addEventListener('change', function() {
if (this.checked) {
document.body.style.cursor = "url(https://cdn.shopify.com/s/files/1/0571/7137/8349/files/cursor.png?v=1644096068), auto";
} else {
document.body.style.cursor = "default";
}
});
}
$(function() {
var test = localStorage.input === 'true' ? true : false;
$('input').prop('checked', test || false);
});
$('input').on('change', function() {
localStorage.input = $(this).is(':checked');
console.log($(this).is(':checked'));
});
.switcheronheader {
position: relative;
display: inline-block;
width: 30px;
height: 17px;
margin-bottom: 2px;
}
.mouseswitcher {
/* border-left: 1px solid #248751; */
padding-left: 20px;
}
.switcheronheader input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 13px;
width: 13px;
left: 2px;
bottom: 2px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked+.slider {
background-color: #248751;
}
input:focus+.slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked+.slider:before {
-webkit-transform: translateX(13px);
-ms-transform: translateX(13px);
transform: translateX(13px);
}
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="mouseswitcher">
<label class="switcheronheader">
<input type="checkbox" id="overheaderswitch">
<span class="slider round"></span>
</label>
</div>
Is this what you are looking for?
a, input, button, .slider, .round {
margin: 15px;
cursor:url(https://cdn.shopify.com/s/files/1/0571/7137/8349/files/pointer.png?v=1644096049), auto;
}
<input type="button" value="lego"/>
link to google.com
Use document.querySelector('html') instead of document.body will make it work.
Also, use cursor: auto instead of cursor: default
var cbs = document.querySelectorAll('input[type=checkbox]');
for (var i = 0; i < cbs.length; i++) {
cbs[i].addEventListener('change', function() {
if (this.checked) {
document.querySelector('html').style.cursor= ' url(https://cdn.shopify.com/s/files/1/0571/7137/8349/files/cursor.png?v=1644096068), auto'
document.querySelector('label').style.cursor = ' url(https://cdn.shopify.com/s/files/1/0571/7137/8349/files/cursor.png?v=1644096068), auto'
} else {
document.querySelector('html').style.cursor = "auto";
document.querySelector('label').style.cursor = 'auto'
}
});
}
.switcheronheader {
position: relative;
display: inline-block;
width: 30px;
height: 17px;
margin-bottom: 2px;
}
.mouseswitcher {
/* border-left: 1px solid #248751; */
padding-left: 20px;
}
.switcheronheader input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 13px;
width: 13px;
left: 2px;
bottom: 2px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked+.slider {
background-color: #248751;
}
input:focus+.slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked+.slider:before {
-webkit-transform: translateX(13px);
-ms-transform: translateX(13px);
transform: translateX(13px);
}
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="mouseswitcher">
<label class="switcheronheader">
<input type="checkbox" id="overheaderswitch">
<span class="slider round"></span>
</label>
</div>
I am trying to implement a notification system in my app without the use of a library. Here is a gif of the issue: https://imgur.com/oRc11dM
And here is the jsfiddle of the gif: https://jsfiddle.net/w9yk7n54/
When you click on new notification button, already displayed notifications jump up to make room for the new notification and new notification slides in. I was wondering how I could make it so that they all smoothly go up together.
The notifications wont all be the same dimensions so I cant set static values for height/etc.
Thank you!
let btn = document.querySelector('button')
let container = document.querySelector('.notifications-container')
let notif_contents = [
"<p>1</p><p>1</p><p>1</p><p>1</p>",
"<p>test</p>",
"<div><h1>testtesttest</h1><p>yoloalsdfasdf</p></div>"
]
let current = 0
btn.onclick = () => {
let notif = document.createElement('div')
notif.classList.add('notif')
notif.innerHTML = notif_contents[current]
notif.addEventListener('animationend', () => {
notif.parentElement.removeChild(notif)
})
current++
container.append(notif)
}
* {
box-sizing: border-box;
}
.container {
height: 300px;
width: 400px;
border: 1px solid black;
position: absolute;
}
.notifications-container {
position: absolute;
top: 0;
right: 0;
height: 100%;
width: 200px;
background: rgba( 0, 0, 0, 0.2);
display: flex;
flex-flow: column nowrap;
justify-content: flex-end;
overflow: hidden;
}
.notif {
position: relative;
width: 100%;
padding: 10px;
border: 1px solid black;
animation: notifAnim 5s forwards;
transition: all .2s;
background: white;
}
button {
z-index: 100;
background: lightcoral;
color: white;
border: none;
padding: 10px;
font-size: 20px;
margin: 5px;
}
#keyframes notifAnim {
0% {
transform: translateY( 100%)
}
20% {
transform: translateY( 0)
}
80% {
transform: translateY( 0)
}
100% {
transform: translateY( 100%)
}
}
<div class="container">
<button>New Notification</button>
<div class="notifications-container"></div>
</div>
Your notif container has justify-content: flex-end. This means that whenever you add a new one, the previous ones will be pushed up with the height of the new one.
The "fix" is to give each element a negative margin-top equal to its height and integrate in your current transition getting margin-top back to 0.
Example:
let btn = document.querySelector('button'),
container = document.querySelector('.notifications-container'),
notif_contents = [
"<p>1</p><p>1</p><p>1</p><p>1</p>",
"<p>test</p>",
"<div><h1>testtesttest</h1><p>yoloalsdfasdf</p></div>",
"<code>another.test()</code>",
"<strong>another</strong> <i>test</i>"
]
btn.onclick = () => {
let notif = document.createElement('div'),
index = Math.floor(Math.random() * notif_contents.length)
notif.classList.add('notif')
notif.innerHTML = notif_contents[index]
notif.addEventListener('animationend', () => {
notif.parentElement.removeChild(notif)
})
container.append(notif)
notif.style.marginTop = '-' + notif.offsetHeight + 'px'
}
* {
box-sizing: border-box;
}
.container {
height: 300px;
width: 400px;
border: 1px solid #888;
position: absolute;
}
.notifications-container {
position: absolute;
top: 0;
right: 0;
height: 100%;
width: 200px;
background: rgba( 0, 0, 0, 0.2);
display: flex;
flex-flow: column nowrap;
justify-content: flex-end;
overflow: hidden;
}
.notif {
position: relative;
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-bottom: none;
animation: notifAnim 5s forwards;
background: white;
}
button {
z-index: 100;
background: lightcoral;
color: white;
border: none;
padding: 10px;
font-size: 20px;
margin: 5px;
}
#keyframes notifAnim {
0%,
100% {
transform: translateY( 100%)
}
20%,
80% {
transform: translateY( 0);
margin-top: 0
}
}
<div class="container">
<button>New Notification</button>
<div class="notifications-container"></div>
</div>
An idea is to insert new element with a height equal to 0 and you animate the height in addition to translate. Of course, you should use max-height since height are unknown and we cannot animate to auto:
let btn = document.querySelector('button')
let container = document.querySelector('.notifications-container')
let notif_contents = [
"<p>1</p><p>1</p><p>1</p><p>1</p>",
"<p>test</p>",
"<div><h1>testtesttest</h1><p>yoloalsdfasdf</p></div>"
]
let current = 0
btn.onclick = () => {
let notif = document.createElement('div')
notif.classList.add('notif')
notif.innerHTML = notif_contents[current]
notif.addEventListener('animationend', () => {
notif.parentElement.removeChild(notif)
})
current++
container.append(notif)
}
* {
box-sizing: border-box;
}
.container {
height: 300px;
width: 400px;
border: 1px solid black;
position: absolute;
}
.notifications-container {
position: absolute;
top: 0;
right: 0;
height: 100%;
width: 200px;
background: rgba( 0, 0, 0, 0.2);
display: flex;
flex-flow: column nowrap;
justify-content: flex-end;
overflow: hidden;
}
.notif {
position: relative;
width: 100%;
padding:0 10px;
max-height:0px;
border: 1px solid black;
animation: notifAnim 5s forwards;
transition: all .2s;
background: white;
}
button {
z-index: 100;
background: lightcoral;
color: white;
border: none;
padding: 10px;
font-size: 20px;
margin: 5px;
}
#keyframes notifAnim {
0% {
transform: translateY( 100%);
max-height:0;
padding:0 10px;
}
30% {
transform: translateY( 0);
max-height:300px;
padding:10px;
}
80% {
transform: translateY( 0);
max-height:300px;
padding:10px;
}
100% {
transform: translateY( 100%);
max-height:300px;
padding:10px;
}
}
<div class="container">
<button>New Notification</button>
<div class="notifications-container"></div>
</div>
We have to build a clock in JavaScript using divs only, (document.createElement()). Somehow, I never get the positioning of the divs right. Currently, I'm already struggling to make the first DIV.
Sorry if I have mistakes in the calculation of the angles.
Are there any better ways to achieve this goal?
Now it looks a bit like this:
The red lines are representing the numbers of a clock (12 of them in total).
window.onload = function drawclock() {
var clock = this.document.getElementById("clock");
var width = clock.offsetHeight;
var radius = width / 2;
for (var i = 1; i < 12; i++) {
var element = document.createElement("DIV");
addClass(element, "h");
addClass(element, i);
var deg = 30 * i;
var x = Math.cos(deg * (180 / Math.PI)) * radius + radius;
var y = Math.sin((90 - deg) * (180 / Math.PI)) * radius + radius;
console.log(x + " " + y);
element.style.position = "absolute";
element.style.left = x + "px";
element.style.top = y + "px";
element.style.transform = "rotate(" + deg + "deg)";
clock.appendChild(element);
}
}
function addClass(element, name) {
var arr;
arr = element.className.split(" ");
if (arr.indexOf(name) == -1) {
element.className += " " + name;
}
}
* {
margin: 0;
padding: 0;
border: 0;
}
body {
background-color: #000;
}
#clock {
height: 500px;
width: 500px;
background-color: #DDDDDD;
border-radius: 100%;
position: absolute;
}
.h {
width: 10px;
height: 70px;
background-color: red
}
.m {
width: 5px;
height: 80px;
background-color: blue
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<script src="main.js"></script>
</head>
<body>
<div id="clock">
</div>
</body>
</html>
Here is a clock example made by Eric Brewer on CodePen.
I have compiled SCSS and Pug keeping only the necessary parts of the code to make the clock work. This version doesn't require any JavaScript to run.
However, I have added some JavaScript code to make it start from a particular position. This can be achieved using the class Date to get the current date and setting the animation-delay CSS property with the property animationDelay for each clock arms.
Here is the working code:
let setTime = function(date) {
const delay = [
date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds(),
date.getMinutes() * 60 + date.getSeconds(),
date.getSeconds()
];
[...document.querySelectorAll('.hand')].forEach((e, i) => e.style.animationDelay = `-${delay[i]}s`);
}
setTime(new Date())
body {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
/* Main style for the clock */
.face {
position: relative;
display: flex;
justify-content: center;
align-items: flex-start;
width: 400px;
height: 400px;
background: #eee;
border-radius: 50%;
padding: 20px;
border: 20px solid #d9d9d9;
}
.face:after {
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: "";
border-radius: 50%;
z-index: 3;
}
/* Numbers: styling and positioning */
.numbers {
position: relative;
}
.number {
position: absolute;
height: 200px;
transform-origin: 0 100%;
font-size: 28px;
}
.number:nth-child(1) {
transform: rotate(25deg);
}
.number:nth-child(1) span {
display: block;
transform: rotate(-25deg);
}
.number:nth-child(2) {
transform: rotate(55deg);
}
.number:nth-child(2) span {
display: block;
transform: rotate(-55deg);
}
.number:nth-child(3) {
transform: rotate(85deg);
}
.number:nth-child(3) span {
display: block;
transform: rotate(-85deg);
}
.number:nth-child(4) {
transform: rotate(115deg);
}
.number:nth-child(4) span {
display: block;
transform: rotate(-115deg);
}
.number:nth-child(5) {
transform: rotate(145deg);
}
.number:nth-child(5) span {
display: block;
transform: rotate(-145deg);
}
.number:nth-child(6) {
transform: rotate(178deg);
}
.number:nth-child(6) span {
display: block;
transform: rotate(-175deg);
}
.number:nth-child(7) {
transform: rotate(205deg);
}
.number:nth-child(7) span {
display: block;
transform: rotate(-205deg);
}
.number:nth-child(8) {
transform: rotate(235deg);
}
.number:nth-child(8) span {
display: block;
transform: rotate(-235deg);
}
.number:nth-child(9) {
transform: rotate(265deg);
}
.number:nth-child(9) span {
display: block;
transform: rotate(-265deg);
}
.number:nth-child(10) {
transform: rotate(295deg);
}
.number:nth-child(10) span {
display: block;
transform: rotate(-295deg);
}
.number:nth-child(11) {
transform: rotate(325deg);
}
.number:nth-child(11) span {
display: block;
transform: rotate(-325deg);
}
.number:nth-child(12) {
transform: rotate(355deg);
}
.number:nth-child(12) span {
display: block;
transform: rotate(-355deg);
}
/* Clock hands styling */
.hands {
position: absolute;
top: 50%;
left: 50%;
}
.hand {
position: absolute;
top: 50%;
left: 50%;
height: 120px;
width: 10px;
content: "";
background: black;
transform: translate(-50%, -100%);
border-radius: 0 0 20px 20px;
transform-origin: 50% 100%;
z-index: 4;
animation: count 3600s linear infinite;
}
.hand:before {
display: block;
position: absolute;
top: -50px;
width: 0;
height: 0;
border: 10px solid transparent;
border-width: 10px 5px 41px;
border-bottom-color: black;
content: "";
}
.hand.hand-hour {
height: 70px;
transform: translate(-50%, -100%) rotate(30deg);
animation: count 43200s linear infinite;
}
.hand.hand-second {
height: 130px;
width: 8px;
transform: translate(-50%, -100%) rotate(60deg);
z-index: 3;
background: red;
animation: count 60s linear infinite;
}
.hand.hand-second .body {
display: block;
position: relative;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: "";
background: red;
z-index: 4;
}
.hand.hand-second:before {
border-width: 10px 4px 41px;
border-bottom-color: red;
z-index: -1;
}
/* animation of the clock hands */
#keyframes count {
0%,
100% {
transform: translate(-50%, -100%);
}
25% {
transform: translate(-50%, -100%) rotate(90deg);
}
50% {
transform: translate(-50%, -100%) rotate(180deg);
}
75% {
transform: translate(-50%, -100%) rotate(270deg);
}
}
<div class="watch">
<div class="face">
<div class="numbers">
<div class="number number-1"><span>1</span></div>
<div class="number number-2"><span>2</span></div>
<div class="number number-3"><span>3</span></div>
<div class="number number-4"><span>4</span></div>
<div class="number number-5"><span>5</span></div>
<div class="number number-6"><span>6</span></div>
<div class="number number-7"><span>7</span></div>
<div class="number number-8"><span>8</span></div>
<div class="number number-9"><span>9</span></div>
<div class="number number-10"><span>10</span></div>
<div class="number number-11"><span>11</span></div>
<div class="number number-12"><span>12</span></div>
</div>
<div class="hands">
<div class="hand hand-hour"></div>
<div class="hand hand-minute"></div>
<div class="hand hand-second">
<div class="body"></div>
</div>
</div>
</div>
</div>
Simply set the current date in date, the JavaScript code will loop through the clock's arms and delay each animation. CSS animation will allow the clock to run continuously after page has been loaded.
This method is a lot more efficient than using a JavaScript function to compute the positions and move clock hands. CSS animations are way more powerful here.
EDIT :
When you're programming a piece of code you should always start with a piece of paper and define what you want, how you will achieve it before starting typing. You have to have a plan before typing, otherwise, it will simply not work.
So as you told me you only want to position the number ticks (the original question wasn't that clear...). It's easier to have all ticks as black rectangles positioned in the center, set their height and width. So we have:
Then use the transform property to rotate each tick to the right angle: 0°, 30°, 60°, 90°, ..., 300°, 330° and 360°. Use rotate(x deg).
Lastly here's the trick to the set the ticks' size correctly:
use a gradient to hide the part of the tick closer to the center so we only show the tip of each tick:
background: linear-gradient(
to top,
#eee 0%,
#eee 80%,
black 80%,
black 100%
);
In the end you should have:
Combining this with the previous code to make the clock turn you get:
let drawTicks = function() {
for (let i = 1; i < 13; i++) {
let el = document.createElement('div');
el.setAttribute('class', `number number${i}`);
el.style.transform = `rotate(${i*30}deg)`;
document.querySelector('.numbers').appendChild(el);
}
}; drawTicks()
let setTime = function(date) {
const delay = [
date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds(),
date.getMinutes() * 60 + date.getSeconds(),
date.getSeconds()
];
[...document.querySelectorAll('.hand')].forEach((e, i) => e.style.animationDelay = `-${delay[i]}s`);
}; setTime(new Date())
body {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
/* Main style for the clock */
.face {
position: relative;
display: flex;
justify-content: center;
align-items: flex-start;
width: 400px;
height: 400px;
background: #eee;
border-radius: 50%;
padding: 20px;
border: 20px solid #d9d9d9;
}
.face:after {
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: "";
border-radius: 50%;
z-index: 3;
}
/* Numbers: styling and positioning */
.numbers {
position: relative;
}
.number {
width: 5px;
background: linear-gradient( to top, #eee 0%, #eee 80%, black 80%, black 100%);
position: absolute;
height: 200px;
transform-origin: 0 100%;
font-size: 28px;
}
/* Clock hands styling */
.hands {
position: absolute;
top: 50%;
left: 50%;
}
.hand {
position: absolute;
top: 50%;
left: 50%;
height: 120px;
width: 10px;
content: "";
background: black;
transform: translate(-50%, -100%);
border-radius: 0 0 20px 20px;
transform-origin: 50% 100%;
z-index: 4;
animation: count 3600s linear infinite;
}
.hand:before {
display: block;
position: absolute;
top: -50px;
width: 0;
height: 0;
border: 10px solid transparent;
border-width: 10px 5px 41px;
border-bottom-color: black;
content: "";
}
.hand.hand-hour {
height: 70px;
transform: translate(-50%, -100%) rotate(30deg);
animation: count 43200s linear infinite;
}
.hand.hand-second {
height: 130px;
width: 8px;
transform: translate(-50%, -100%) rotate(60deg);
z-index: 3;
background: red;
animation: count 60s linear infinite;
}
.hand.hand-second:before {
border-width: 10px 4px 41px;
border-bottom-color: red;
z-index: -1;
}
/* animation of the clock hands */
#keyframes count {
0%,
100% {
transform: translate(-50%, -100%);
}
25% {
transform: translate(-50%, -100%) rotate(90deg);
}
50% {
transform: translate(-50%, -100%) rotate(180deg);
}
75% {
transform: translate(-50%, -100%) rotate(270deg);
}
}
<div class="watch">
<div class="face">
<div class="numbers"></div>
<div class="hands">
<div class="hand hand-hour"></div>
<div class="hand hand-minute"></div>
<div class="hand hand-second">
</div>
</div>
</div>
</div>
I'm trying to add red overlay on my image-box class, but I can't get the result because:
new overlay class replaces the old one, and I only get red background.
I need the new class in addition to, not instead of the old one.
This is what I have tried so far:
$(function($) {
$(document).on('click', '.wrapper', function(event) {
var target = $(event.target).closest('.wrapper');
target.find('.image-box').addClass("overlay");
});
});
.image-box {
height: 300px;
width: 100%;
padding-right: 0px;
padding-left: 0px;
background-position: center;
background-color: #4D4E56;
}
.overlay{
background-color:rgba(86, 61, 124, 0.55);
transition: 0.5s;
filter:alpha(opacity=50);
-moz-opacity:0.5;
-khtml-opacity: 0.5;
opacity: 0.5;
height:150px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="image-box"></div>
</div>
You may use :after to add overlay. Check the updated Code.
$(function($) {
$(document).on('click', '.wrapper', function(event) {
var target = $(event.target).closest('.wrapper');
target.find('.image-box').addClass("overlay");
});
});
.image-box {
height: 300px;
width: 100%;
padding-right: 0px;
padding-left: 0px;
background-position: center;
background-color: #4D4E56;
position: relative
}
.image-box:after {
opacity: 0;
background-color: rgba(86, 61, 124, 0.55);
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
content: "";
transition: opacity 5s;
}
.overlay:after {
opacity: 1;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="image-box"></div>
</div>
If I understand you better below is the code snippet.
$(function($) {
$(document).on('click', '.wrapper', function(event) {
$(this).find('.image-box').addClass("overlay");
});
});
.image-box {
height: 300px;
width: 100%;
padding-right: 0px;
padding-left: 0px;
background-position: center;
background-color: #4D4E56;
}
.overlay{
/*background-color:rgba(86, 61, 124, 0.55);*/
background-color:rgba(255, 0, 0, 1);
transition: 0.5s;
filter:alpha(opacity=50);
-moz-opacity:0.5;
-khtml-opacity: 0.5;
opacity: 0.5;
height:300px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<div class="wrapper">
<div class="image-box"></div>
</div>
Have you tried to change the .overlay & image-box property
.image-box{
/* add position:relative */
}
.overlay{
position:absolute; background-color:red; filter:alpha(opacity=50); opacity: 0.8; height: 100%; width: 100%; opacity: 1; z-index: 9; position: absolute; top: 0; opacity: 0.5;transition: 0.5s;
}
While clicking on image-box, it will give you the overlay over the image-box