I've just started to study javascript, and checked the example from the website https://cssanimation.rocks/clocks/. But, unfortunatelly, one part in js script does not work. The code is like this:
/*
* Starts any clocks using the user's local time
* From: cssanimation.rocks/clocks
*/
(function() {
// Initialise the locale-enabled clocks
//initInternationalClocks();
// Initialise any local time clocks
initLocalClocks();
// Start the seconds container moving
//moveSecondHands();
// Set the intial minute hand container transition, and then each subsequent step
//setUpMinuteHands();
})();
function initLocalClocks() {
//get the local time using javascript
var date = new Date();
var seconds = date.getSeconds();
var minutes = date.getMinutes();
var hours = date.getHours();
var hands = [
{
hand: "hours",
angle: (hours * 30) + (minutes/2)
},
{
hand: "minutes",
angle: (minutes * 6)
},
{
hand: "seconds",
angle: (seconds * 6)
},
];
for (var j = 0; j < hands.length; j++){
var elements = document.querySelectorAll('.' + hands[j].hand);
// window.alert(elements.length);
for (var k = 0; k < elements.length; k++)
{
// window.alert(elements[k]);
elements[k].style.webkitTransform = 'rotateZ(' + hands[j].angle + 'deg)';
elements[k].style.transform = 'rotateZ(' + hands[j].angle + 'deg)';
if (hands[j].hand === 'minutes'){
elements[k].parentNode.setAttribute('data-second-angle', hands[j+1].angle)
}
}
}
}
// Set a timeout for the first minute hand movement (less than 1 minute), then rotate it every minute after that
function setUpMinuteHands() {
// Find out how far into the minute we are
var containers = document.querySelectorAll('.minutes-container');
var secondAngle = containers[0].getAttribute("data-second-angle");
if (secondAngle > 0) {
// Set a timeout until the end of the current minute, to move the hand
var delay = (((360 - secondAngle) / 6) + 0.1) * 1000;
setTimeout(function() {
moveMinuteHands(containers);
}, delay);
}
}
.footer{
color: black;
font-style: italic;
position: fixed; bottom: 0; left:0; right: 0; height: 30px;
float: left;
clear: both;
}
.clock {
border-radius: 50%;
background: #fff url(./images/ios_clock.svg) no-repeat center;
background-size: 88%;
height: 20em;
padding-bottom: 0%;
position: relative;
width: 20em;
}
.clock::after{
background: #000;
border-radius: 50%;
content: "";
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 5%;
height: 5%;
z-index: 10;
}
.minutes-container, .hours-container, .seconds-container {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.hours {
background: #000;
height: 20%;
left: 48.75%;
position: absolute;
top: 30%;
transform-origin: 50% 100%;
width: 2.5%;
}
.minutes {
background: #000;
height: 40%;
left: 49%;
position: absolute;
top: 10%;
transform-origin: 50% 100%;
width: 2%;
}
.seconds {
background: #000;
height: 45%;
left: 49.5%;
position: absolute;
top: 14%;
transform-origin: 50% 100%;
width: 1%;
z-index: 8;
}
#keyframes rotate {
100% {
transform: rotateZ(360deg);
}
}
.hours-container{
animation: rotate 43200s infinite linear;
}
.minutes-container{
animation: rotate 3600s infinite linear;
}
.seconds-container {
animation: rotate 60s infinite linear;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="styles.css">
<script type="text/javascript" src="script.js" ></script>
</head>
<body>
<article class="clock">
<div class="hours-container">
<div class="hours"></div>
</div>
<div class="minutes-container">
<div class="minutes"></div>
</div>
<div class="seconds-container">
<div class="seconds"></div>
</div>
</article>
</body>
<footer>
<div class="footer">All materials are taken from the website cssanimation.rocks
</div>
</footer>
</html>
And when I open page, javascript is executed, but array "elements" from the line:
var elements = document.querySelectorAll('.' + hands[j].hand)
is empty. I've checked via alert windows, and really, querySelectorAll does not return objects, but name of css class seems to be correct... I've tried the same in console (like: document.querySelectorAll('.hands'), and it returns the needed div...
Could you, please, help me - what can be wrong with it?...
P.S. When I've pasted snippet to this post, the js script seems working... Now I'm completely lost - is it something with my browser settings, or something?
Thank you very much in advance for any suggestion/help!
Related
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.
I'm making an app using JavaScript and JQuery, which will tell the user if there device is straight or not, basically like a spirit level. I want to draw a line a straight line across the middle of the screen and i want this to be responsive no matter the size of the device. This will be used on mobiles and tablets. I used a canvas to the draw a line and so far i'm not sure if this is the right way to approach this?
if anyone could give me any advice i would really appreciate it. Below is my canvas line so far. And I've included some rough drawing of what i mean.
const c = document.getElementById("LineCanvas");
const drw = c.getContext("2d");
drw.beginPath();
drw.moveTo(10,45);
drw.lineTo(180,47);
drw.lineWidth = 5;
drw.strokeStyle = '#006400';
drw.stroke();
If the phone is aligned straight the line will be green else red
to draw the line you can use a pseudo element from HTML or body or any specific tag that you want to use in a specific page or click , then update rotation via transform:rotate() ; or rotate3D()
example ( without javascript, rotate values will have to be taken from your device via your app ):
let level = document.querySelector("#level");
document.querySelector("#spirit").onclick = function() {
level.classList.toggle('show');
}
#level {
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
display: none;
pointer-events: none;
}
#level.show {
display: block;
}
#level::before {
content: '';
position: absolute;
width: 200vmax;
margin: 0 -50vmax;
border-top: 1px solid;
box-shadow: 0 0 1px 5px #bee;
top: 50%;
transform: rotate(0deg);
}
#level.show~#spirit::before {
content: 'Hide';
}
#level:not(.show)~#spirit::before {
content: 'Show';
}
/* animation to fake phone device moving */
#level::before {
animation: rt 10s infinite;
}
#keyframes rt {
20% {
transform: rotate3d(1, -1, 1, -0.25turn);
}
40% {
transform: rotate3d(1, 1, 1, 0.5turn);
}
60% {
transform: rotate3d(1, -1, 1, -0.75turn);
}
80% {
transform: rotate3d(1, 1, -1, -0.5turn);
}
}
<div id="level">
<!-- to show on a single page or via js on user request -->
</div>
<button id="spirit" type=button> that spirit level</button>
While drawing a line with canvas can work you might find it more straightforward to draw it with a simple div element. When you sense a slope you can change its color to red and back to green if it's level.
Of course you will have to do some calculations to decide what angle you want the line to be - but I guess that is the whole point of your webapp to show people how far off they are.
When you know the angle you want the line to be call slope(n) where n is the number of degrees. I've also put in a simple button so the user can choose whether to show the line or not but I expect you'll have your own code for that.
On any page where you want the user to be able to show the line put this in the head:
<style>
* {
margin: 0;
padding: 0;
}
.linecontainer {
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
overflow: hidden;
z-index: 99999;
}
#line {
width: 200vmax;
height: 5px;
position: relative;
top: 50%;
left: calc(50vw - 100vmax);
transform: rotate(45deg);
background-color:red;
}
.hideline {
display: none;
}
#showbtn {
font-size: 20px;
background-color: blue;
color: white;
height: 2em;
width: auto;
padding: 2px;
}
</style>
and put this in the main body of the page:
<div class="linecontainer">
<div id="showbtn" onclick="document.getElementById('line').classList.toggle('hideline');">
Click me to show/hide the line
</div>
<div id="line"></div>
</div>
<script>
function slope(deg) {
let line = document.getElementById('line');
line.style.backgroundColor = ( deg%180 == 0 ) ? 'green' : 'red';
line.style.transform = 'rotate(' + deg + 'deg)';
}
</script>
Here's a snippet where you can show the line at different angles.
function slope(deg) {
let line = document.getElementById('line');
line.style.backgroundColor = ( deg%180 == 0 ) ? 'green' : 'red';
line.style.transform = 'rotate(' + deg + 'deg)';
}
* {
margin: 0;
padding: 0;
}
.linecontainer {
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
overflow: hidden;
z-index: 99999;
}
#line {
width: 200vmax;
height: 5px;
position: relative;
top: 50%;
left: calc(50vw - 100vmax);
transform: rotate(45deg);
background-color:red;
}
.hideline {
display: none;
}
#showbtn {
font-size: 20px;
background-color: blue;
color: white;
height: 2em;
width: auto;
padding: 2px;
}
<div class="linecontainer">
<div id="showbtn" onclick="document.getElementById('line').classList.toggle('hideline');">
Click me to show/hide the line
</div>
<div id="line"></div>
</div>
<!-- this is just for the demo -->
<div style="background-#eeeeee;font-size: 20px;position:fixed;z-index:100000;bottom:0;left:0;">How many degrees do you want me to rotate? <input style="font-size:20px;"value="45" onchange="slope(this.value);"/></div>
I'm trying to rotate an image away from the origin (transformed) in circle, or rather, clockwise. I have successfully setup an absolute center for the images relative to my modal. I have complete control for minutes and hours. The thing is, I need the day period indicator (in this case I only have night time) to follow the hours indicator (or "hand") simultaneously. I only manage to get it right manually: manual adjustment. But over time, it returns to the original position, or something like that, I haven't watched every step: out of circle. Here is my code: CSS:
#clock {
display: -webkit-box;
margin-left: auto;
margin-right: auto;
/*margin: 0 auto;*/
padding: 100px;
position: relative;
}
.minutes {
position: absolute;
/*top: -90px;
left: -27px;*/
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
z-index: 1;
width: 208.5px;
height: 208.5px;
transition: transform 0.3s cubic-bezier(.4,2.08,.55,.44);
}
.hours {
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
z-index: 2;
height: 155.5px;
position: absolute;
transition: transform 0.3s cubic-bezier(.4,2.08,.55,.44);
}
.night {
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
position: absolute;
z-index: 3;
height: 50px;
transform-origin: 120px 0px;
-webkit-transform-origin: 120px 0px;
-webkit-transition: transform 0.3s cubic-bezier(.4,2.08,.55,.44);
transition: transform 0.3s cubic-bezier(.4,2.08,.55,.44);
}
Javascript:
let rings = [], elements = [];
rings = [{
ring: 'minutes',
angle: 0
},
{
ring: 'hours',
angle: 0
},
{
ring: 'night',
angle: 0
}
];
for (let index = 0; index < rings.length; index++) {
elements[index] = document.querySelector('.' + rings[index].ring);
}
setInterval(function () {
let now = new Date();
minutes = now.getMinutes();
hours = now.getHours();
for (var id = 0; id < rings.length; id++) {
if (rings[id].ring === 'minutes') {
rings[id].angle = minutes * 6;
} else if (rings[id].ring === 'hours') {
rings[id].angle = (hours * 30) + (minutes / 2);
} else if (rings[id].ring === 'night') {
rings[id].angle = (hours * 30) + (minutes / 2);
} else {
console.log('Err: ');
}
elements[id].style.webkitTransform = 'rotateZ(' + rings[id].angle + 'deg)';
elements[id].style.transform = 'rotateZ(' + rings[id].angle + 'deg);';
}
}, 1000);
HTML:
<div id="clock">
<img src="res/termina_clock/outside.png" alt="" class="minutes">
<img src="res/termina_clock/inside.png" alt="" class="hours">
<img src="res/termina_clock/night.png" alt="" class="night">
</div>
What you have to do is nest day/night indicator inside of hours. Then you can precisely position it.
<div id="clock">
<img src="http://i.imgur.com/4k04SRS.png" alt="" class="minutes">
<div class="hours">
<img src="http://i.imgur.com/9cQMi2m.png" alt="" class="night">
</div>
</div>
I also had to get rid of your custom transform-origin since it's no longer needed and was messing up the positioning.
.night {
/*transform-origin: 120px 0px;*/
/*-webkit-transform-origin: 120px 0px;*/
}
https://jsfiddle.net/5ak3zLy0/2/
so I have some images and I would like to show them as a slideshow in the background. However, I want the image to cross-fade between the current image and the next image. So far, I have only been able to switch between the images:
$(document).ready(function () {
var images = ["landing_background_1.jpg", "landing_background_2.jpg", "landing_background_3.jpg", "landing_background_4.jpg"];
var currentImage = 0;
function changeBackgroundImage() {
$("html").fadeIn().css({
"background-image": "url('img/backgrounds/" + images[++currentImage] + "')",
});
if (currentImage >= images.length - 1) {
//set it back to the begining
currentImage -= images.length;
}
}
setInterval(changeBackgroundImage, 1500);
});
Any help would be much appreciated! :)
What you have to do is layer two element on top of each other. Then have one fadeout and the other fadein.
Here is how I would go about doing it ...
css ...
#background-images {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
#bImg1 {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 3;
background: url(starting-img1.jpg) no-repeat;
background-size: contain;
}
#bImg2 {
display: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 2;
background: url(starting-img2.jpg) no-repeat;
background-size: contain;
}
.container {
width: 960px;
height: 900px;
background: rgba(255,255,255,.7);
margin: auto;
position: relative;
z-index: 10;
}
The html ...
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<html>
<body>
<div id="background-images">
<div id="bImg1"></div>
<div id="bImg2"></div>
</div>
<div class="container">
Content Here
</div>
</body>
</html>
The script ...
var imageSet1 = ["image1.jpg", "image2.jpg", "image3.jpg"];
var currentImageSet1 = 0;
var imageSet2 = ["image4.jpg", "image5.jpg", "image6.jpg"];
var currentImageSet2 = 0;
function changeBackgroundImages() {
img1Fade();
setTimeout(img2Fade, 2000);
}
function img1Fade(){
$('#bImg1').fadeOut('slow', function(){$('#bImg1').css({background: 'url(' + imageSet1[++currentImageSet1] + ')'})});
$('#bImg2').fadeIn('slow');
if (currentImageSet1 >= imageSet1.length - 1) {
currentImageSet1 -= imageSet1.length;
};
}
function img2Fade(){
$('#bImg2').fadeOut('slow', function(){$('#bImg2').css({background: 'url(' + imageSet2[++currentImageSet2] + ')'})});
$('#bImg1').fadeIn('slow');
if (currentImageSet2 >= imageSet2.length - 1) {
currentImageSet2 -= imageSet2.length;
};
}
$(document).ready(function(){
setInterval(changeBackgroundImages, 5000);
});
You will need to mess with the timing to get it to look good. Make sure to set your urls to the images in the image array or when the sting in the css is built.
I've spent a lot of time to find the most clean and easy way.
This finally works:
var i=0;
var imghead=[
"url(http://yoururl.com/picture0.jpg)",
"url(http://yoururl.com/picture1.jpg)"
];//add as many images as you like
function slideimg() {
setTimeout(function () {
jQuery('#element').css('background-image', imghead[i]);
i++;
if(i==imghead.length) i=0;
slideimg();
}, 6000);
}
slideimg();
#element{
height: 100%;
overflow: hidden;
opacity: 1.0;
-webkit-transition: background-image 1.5s linear;
-moz-transition: background-image 1.5s linear;
-o-transition: background-image 1.5s linear;
-ms-transition: background-image 1.5s linear;
transition: background-image 1.5s linear;
}
Easier:
var current = 1;
function anim() {
if(current == 4) {current = 1; }
$('#bImg'+ current).fadeOut(3000);
++current;
$('#bImg'+ current).fadeIn(3000);
setTimeout(anim, 8000);
}
anim();
html:
<div class="inside" >
<div id="bImg2"></div>
<div id="bImg3"></div>
</div>
css:
.inside {
background:url(top_01.jpg) no-repeat center top ;
}
#bImg2 {
position: absolute;
top: 0px;
width: 100%;
background:url(top_02.jpg) no-repeat center top ;
display: none;
}
#bImg3 {
position: absolute;
top: 0px;
width: 100%;
background:url(top_03.jpg) no-repeat center top ;
display: none;
}
I've been searching and I can't find anything on the web, but I'm interested in creating (or using something already available, hopefully since I'm pressed with time) similar to this site:
http://www.citroen.hr/citroen/#/citroen/
It's also similar to the Safari Top Sites view, but has the added mouse-tracking and 3d rotation.
Does anyone know of something similar created with javascript/html/css or can point me in the right direction?
A basic version with HTML elements, CSS 3D transforms (so it only works in browsers supporting 3D transforms & nesting of 3D transformed elements - this means no Opera and no IE) and a little bit of JavaScript for the mouse tracking:
demo
HTML:
<ul class='tiles'>
<li class='tile'></li>
<!-- more tiles; I used 16 for the demo and put them on an icosagon -->
</ul>
<div class='slider'></div>
Relevant CSS:
.tiles {
position: absolute;
top: 50%; left: 50%;
padding: 0;
width: 0; height: 0;
list-style: none;
transform-style: preserve-3d;
transform: rotateY(-162deg);
}
.tile {
position: absolute;
left: 50%;
margin: 0.5em -10em;
width: 20em; height: 20em;
backface-visibility: hidden;
opacity: 0.5;
/* inradius of an icosagon */
cursor: pointer;
transition: 0.5s;
}
.tile:hover { opacity: 1; }
.tile:nth-child(odd) { bottom: 100%; }
.tile:nth-child(2), .tile:nth-child(1) {
transform: rotateY(18deg) translateZ(-66.29439em);
}
/* and so on... in general, something of the form:
.tile:nth-child(2*i), .tile:nth-child(2*i-1) {
transform: rotateY(1*18deg) translateZ(-66.29439em);
}
where 18deg = outer angle of the icosagon
66.29439em = 1.05*20em*(1 + sqrt(5) + sqrt(5 + 2*sqrt(5)))/2
= 1.05 * inradius of icosagon
see http://mathworld.wolfram.com/Icosagon.html */
.tile:nth-child(1) {
background: url(image1.jpg);
background-size: cover;
}
/* and so on, set backgrounds for each */
.slider {
position: absolute;
bottom: 5%; left: 10%;
height: 0.25em; width: 80%;
opacity: 0.5;
background: grey
linear-gradient(90deg, crimson 100%, transparent 100%) no-repeat;
background-size: 5% 100%;
}
JavaScript:
(function(){
var b = document.body;
b.addEventListener('mousemove', function(e) {
var w = b.clientWidth, x = e.clientX,
perc = x/w,
full_angle = -162,
to_angle = full_angle + (100 - perc)*full_angle,
txt = 'rotateY(' + to_angle + 'deg)',
prefixes = ['Webkit', 'Moz', /*'ms', 'O', */''],
len = prefixes.length,
property = 'Transform',
a = document.querySelector('.tiles'),
s = document.querySelector('.slider');
for(var i = 0; i < len; i++) {
if(prefixes[i] == '')
property = property.toLowerCase();
a.style[prefixes[i] + property] = txt;
}
s.style.backgroundPosition = (perc*100 - .5) + '% 50%';
}, false);
}());