Reputation: 1159
I have a count down clock which works absolutely fine. Now the question is can I display images as digits instead of html. I cant seem to figure out the logic how would I approach it. I really dont want to use a plugin for this so that is really not an option.
and the JS for the clock is this
setInterval(function(){
var future = new Date("Jan 20 2014 21:15:00 GMT+0200");
var now = new Date();
var difference = Math.floor((future.getTime() - now.getTime()) / 1000);
var seconds = fixIntegers(difference % 60);
difference = Math.floor(difference / 60);
var minutes = fixIntegers(difference % 60);
difference = Math.floor(difference / 60);
var hours = fixIntegers(difference % 24);
difference = Math.floor(difference / 24);
var days = difference;
$(".seconds").text(seconds + "s");
$(".minutes").text(minutes + "m");
$(".hours").text(hours + "h");
$(".days").text(days + "d");
}, 1000);
function fixIntegers(integer)
{
if (integer < 0)
integer = 0;
if (integer < 10)
return "0" + integer;
return "" + integer;
}
I have stored the images in an array which is this
var linkCons = 'http://soumghosh.com/otherProjects/Numbers/'
var num = [];
var linkCons = "http://soumghosh.com/otherProjects/Numbers/";
for(var i = 0; i < 10; i++) {
num.push(linkCons + "nw" + i + ".png");
}
Thanks to stack overflow folks helping me cleaning the array. Really appriciate it
And here is the working fiddle http://jsfiddle.net/sghoush1/wvbPq/3/
Upvotes: 1
Views: 2556
Reputation: 206508
You can do it using only one sprite image and this bit of code I created:
jQuery(function($) { // DOM ready shorthand
// CLOCK
// Just a date in the future... Say 5 days from now
var fut = new Date().setDate(new Date().getDate() + 5);
// Number splitter
function intSpl(i) {
i = Math.floor(i);
return [Math.floor(i / 10), i % 10]; // 37=[3,7] // 5=[0,5] // 0=[0,0]
}
var obj = {}; // {d:[7,7], h:[1,9], .....}
function drawTime() {
var now = new Date().getTime();
var dif = now < fut ? Math.floor((fut - now) / 1000) : 0;
obj.s = intSpl(dif % 60);
obj.m = intSpl(dif / 60 % 60);
obj.h = intSpl(dif / 60 / 60 % 24);
obj.d = intSpl(dif / 60 / 60 / 24);
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
for (var i = 0; i < 2; i++) { // get el ID number (0,1)
$('#' + key + i).css({
backgroundPosition: -obj[key][i] * 50
});
}
}
}
}
drawTime();
setInterval(drawTime, 1000);
});
#clock span {
display: inline-block;
width: 50px;
height: 85px;
background: url('http://i.imgur.com/uBTxTTD.jpg');
background-position: 0 0;
}
#clock span:nth-child(even) {
margin-right: 15px;
}
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<div id="clock">
<span id="d0"></span>
<span id="d1"></span>
<span id="h0"></span>
<span id="h1"></span>
<span id="m0"></span>
<span id="m1"></span>
<span id="s0"></span>
<span id="s1"></span>
</div>
span
s in CSS-(witdh * number)
pxWhile the listed above seems logic, the first problem you can see here is how to retrieve separately a JS time number (1 or 2 digits) keep leading zero if needed, and reference each digit to target the right element in HTML?
Let's start by splitting numbers:
35 == 3, 5 /// 0 == 0, 0 // this is an example of what we need.
var n = 35; // Set any 1 or 2 digit number.
var n1 = ~~(n/10); // 3 //// ~~ "Double Bitwise NOT"
// just instead of parseInt(time/10, 10).
var n2 = n%10; // 5 //// % "Mudulus operator" (reminder).
JS Grouping
Now, how to group this two separated digits and say: "Hey you two are for my clock seconds!" ?
By simply putting them into an array! [3, 5]
, and for we'll have also minutes, hours and day - let's simply put all those arrays into an Object
and assign a Key Name which will result in having an object like:
obj = {d:[7,4], h:[1,9], m:[2,9], s:[0,7]}
Reference to HTML
Having that Object and knowing that inside an for...in
loop we can retrieve the Key name and the array value like eg: obj['d'][0] === 7
obj['d'][5] === 4
means that we'll need a for
loop to retrieve the 0
and 1
to get the values in our array positions [pos0, pos1]
all inside a for...in
loop that will get the KEY names : d, h, m, s
2pos x 4keyNames = 8 elements iterations/second
means that now we'll be able to target an ID element eg: #s0
and #s1
and all we need now is to retrieve the value and animate that element background by
-width * digit
Upvotes: 2
Reputation: 21124
Well, there's another way that you may use to solve the same problem. Here are the steps. Firstly I wrote one CSS class selector for each image position.
.list-group-item .digit-display{
display:inline-block;
width:50px;
height:85px;
background:url('http://i.imgur.com/uBTxTTD.jpg');
}
.position-0 {
background-position: 0 0;
}
.position-1 {
background-position: -50px 0px !important;
}
Then I wrote a JavaScript function which takes a digit as an input and return the CSS class selector for that digit as below.
displayDigit(digit) {
const baseSelector = "digit-display position-";
return `${baseSelector}${digit}`;
}
Finally this function is called inside the JSX element as below.
<span className = {this.displayDigit(remainingTime["h"].charAt(0))}></span>
That solved the issue.
However, if someone really needs to go with the jquery based approach specified above, we can still condense down that same code as below.
secondsToTime(secs) {
let hours = `${constants.ZERO}${Math.floor(secs / (60 * 60))}`.slice(-2);
let divisorForMinutes = secs % (60 * 60);
let minutes = `${constants.ZERO}${Math.floor(divisorForMinutes / 60)}`.slice(-2);
let divisorForSeconds = divisorForMinutes % 60;
let seconds = `${constants.ZERO}${Math.ceil(divisorForSeconds)}`.slice(-2);
let obj = {
"h": hours,
"m": minutes,
"s": seconds
};
return obj;
}
handleFlipClockImage = () => {
var myObj = this.secondsToTime(seconds);
Object.keys(myObj).forEach(key => {
let obj = myObj[key];
var digits = obj.split(constants.EMPTY_SPACE_CHAR);
digits.forEach((digit, index) => {
jquery(`#${this.state.label}${key}${index}`).css({backgroundPosition: -digit*50 });
});
});
}
Upvotes: 0