Solved

Dragable hours and minutes clock using  javascript

Posted on 2016-10-19
15
142 Views
1 Endorsement
Last Modified: 2016-10-30
I  have made some changes to this example which is an analog clock   :  https://jsfiddle.net/sarmadm/0zkd68ux/

I want the clock hand ( hours and minutes ) to be draggable to set a certain time. I don't want the clock to run, .

Does anybody have an idea?
1
Comment
Question by:john a
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
  • 4
  • +1
15 Comments
 
LVL 56

Expert Comment

by:Julian Hansen
ID: 41851535
Very interesting question - just don't have time to look at it now but would like to tackle it later. If you don't get any bites and you don't have a solution try again in a week or two.
0
 

Author Comment

by:john a
ID: 41851788
Thanks very much , I will try to do something and I will wait your solution

Regards
0
 
LVL 56

Expert Comment

by:Julian Hansen
ID: 41851831
The general idea is to add an event listener on the canvas for a mousedown event.
In the listener check to see if the click is within the bounds of the hand you are targeting.
If it is set then set a flag
Then listen for mousemove events - in the handler if the flag is set then work out the angle from the centre of the clock to the current mouse point. Find the difference between this angle and the current angle of the hand. Redraw the clock with the hand in the new position and reapply to the canvas.

The maths for the above should be readily available on the net.

It is a nice question - will look at it next week once I have chased the wolves away ....
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 34

Expert Comment

by:Slick812
ID: 41852844
Greetings   john a, , , ,  I have some code below that makes a "Clock" display adjustable by clicks-touch, , I attempted some onmove event in the SVG image, but the SVG image is a VECTOR draw, and fills up the container, so getting the cursor position in x and y pixels was not working for me to use in SVG image. I did this code below with <div> display with some HTML CSS I did a clock before. BUT if you do a MOUSEDOWN event on the "hour" div then the cursor move off of the narrow div, I tried with the mousemove using the Clock div, but the trigonometry of pixel position in x and y of the <div> space to SIN COS and ARCTAN to degrees or rads to rotate the hour hand <div> was more than I could manage. SO I did an easier user time adjustment, by clicking on the NUMBER of the clock you need the hour-minute hand to go to. Although it is not a DRAG as you asked for, it may still allow the user to Change the Time on the Clock to what they need, as long as 5 minute intervals are acceptable.

<!DOCTYPE HTML>
<html lang="en"><head><title>Clock Click</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />

<style>
body{background:#f9e8ff;margin:1px;}

#title {
text-align: center;
padding: 12px;
background: #eda;
}

#clock{
position:relative;
background-color:#edd;
width:290px;
height:290px;
margin:10px;
text-align:center;
border: 4px solid #447;
border-radius:50%;
}

#sw {
position: absolute;
top: -5px;
right: -4px;
}

#time {
position: absolute;
bottom: 12px;
right: -4px;
}

#hour {
position: absolute;
top: 143px;
left: 51px;
width: 188px;
height: 13px;
z-index: 2;
}

#hour span{
display: block;
float: right;
width: 94px;
height: 7px;
background-color: #fcc;
border: 3px solid #668;
border-radius:9px;
}

#minute {
position: absolute;
top: 144px;
left: 20px;
width: 250px;
height: 9px;
transform: rotate(90deg);
z-index: 3;
}

#minute span{
display: block;
float: right;
width: 125px;
height: 5px;
background-color: #ccf;
border: 2px solid #668;
border-radius:9px;
}

#hrShow, #mnShow {
position: absolute;
left: -5px;
padding: 3px;
border:2px solid #b00;
border-radius:10px;
cursor: pointer;
}

#mnShow {
background-color: #ccf;
bottom: 1px;
}

#hrShow {
background-color: #fcc;
top: 1px;
}
</style>

<script>
function id2ob(elmt1){return document.getElementById(elmt1);}

function numClick() {
if(!doMn && !doHr) return;
var p = this.id.split("d");
p = parseInt(p[1]);// 30 degree, , 0 is ONE ,0 degree is num 3
var d = (p*30)-60;
if(doHr){
hour1.style.transform = "rotate("+d+"deg)";
tm[0] = ""+(p+1);
id2ob("time").innerHTML = tm[0]+":"+tm[1];
doHr = 0;
}else
if(doMn){
minute1.style.transform = "rotate("+d+"deg)";
tm[1] = (1+p)*5;
if(tm[1]> 55)tm[1]="0";
tm[1] = (tm[1]<10) ? "0"+tm[1] : ""+tm[1];
id2ob("time").innerHTML = tm[0]+":"+ tm[1];
doMn = 0;
}
for (var i=0;i<hrDivs.length;++i){
hrDivs[i].style.backgroundColor="transparent";
hrDivs[i].style.cursor="default";
}
sw.innerHTML = "";
}
</script>
</head><body><h3 id="title">Clock Click</h3>
<hr>
<div id="clock">
<div id="sw"></div>
<div id="time">3:30</div>
<div id="hrShow">Hour</div>
<div id="mnShow">Minute</div>
<div id="hour"><span></span></div>
<div id="minute"><span></span></div>
</div>
<hr>


<script>


var sw = id2ob("sw"), clock1 = id2ob("clock"), hour1 = id2ob("hour"), minute1 = id2ob("minute"), tm=["3","30"];

var hrDivs = [], doHr=0, doMn = 0;
for(var i=0;i<12;i++){// 12 width:290px;
  var sx = 138+Math.round(132*Math.cos(30*(i-2)*Math.PI/180));
  var sy = 135+Math.round(132*Math.sin(30*(i-2)*Math.PI/180));
  var nDiv = document.createElement("div"); 
  var tn = document.createTextNode(""+(i+1));
  nDiv.appendChild(tn);
  nDiv.id = "hrd"+i;
  nDiv.style.position = "absolute";
  if(i==11)sx-=3;
  nDiv.style.left = sx+"px";
  nDiv.style.top = sy+"px";
  nDiv.style.fontSize = "20px";
  nDiv.style.borderRadius = "6px";
  nDiv.style.fontFamily = "serif";
  nDiv.style.padding = "0 2px";
  nDiv.onclick = numClick;
  clock1.appendChild(nDiv);
  hrDivs[i] = nDiv;
  } 

id2ob("hrShow").onclick = function() {
doHr = 1;
sw.innerHTML = "Touch<br />Number";
for (var i=0;i<hrDivs.length;++i){
  hrDivs[i].style.backgroundColor="#d88";
  hrDivs[i].style.cursor="pointer";
  }
}

id2ob("mnShow").onclick = function() {
doMn = 1;
sw.innerHTML = "Touch<br />Number";
for (var i=0;i<hrDivs.length;++i){
  hrDivs[i].style.backgroundColor="#88d";
  hrDivs[i].style.cursor="pointer";
  }
}
</script>
</body></html>

Open in new window


See what you think?
0
 
LVL 35

Accepted Solution

by:
Robert Schutt earned 500 total points
ID: 41853008
Dragging the hands of the clock in the provided svg is not all that difficult. Getting the right coordinates was a bit harder due to the automatic scaling. Have a look at the update fiddle and let me know if that works for you?
var min = document.getElementById('min');
var hour = document.getElementById('hour');

var movingElem = null;
function mouseDown(e) {
  movingElem = e.target;
}
function mouseUp(e) {
  movingElem = null;
}
function mouseMove(e) {
  if (movingElem) {
    // get mouse coords in the svg coordinate system and
    // calculate angle in relation to the mid-point (50, 50)
    // more info: https://developer.mozilla.org/en/docs/Web/API/SVGMatrix
    var vwp = movingElem.nearestViewportElement,
        ctm = vwp.getScreenCTM(),
        pnt = vwp.createSVGPoint();
      pnt.x = e.clientX;
      pnt.y = e.clientY;
    var loc = pnt.matrixTransform(ctm.inverse());
    var deg = 90 - Math.atan2(50 - loc.y, loc.x - 50) * 180 / Math.PI;
    movingElem.setAttribute('transform', 'rotate(' + deg + ' 50 50)');
  }
}

min.addEventListener('mousedown', mouseDown, false);
hour.addEventListener('mousedown', mouseDown, false);
document.addEventListener('mouseup', mouseUp, false);
document.addEventListener('mousemove', mouseMove, false);

Open in new window

1
 
LVL 34

Expert Comment

by:Slick812
ID: 41853081
@Robert Schutt , Good work, , works in my firefox desktop.
How did you find addy for the the SVG API for the shown in the -
    https://developer.mozilla.org/en/docs/Web/API/SVGMatrix


but the Browser compatibility for SVGMatrix shows mostly question marks except for IE, that's extremely weird!

By the by, the minute hand in firefox does not do a hand Point centered rotation, you think a change in the -
   movingElem.setAttribute('transform', 'rotate(' + deg + ' 50 50)');
could correct that?
Maybe it's due to the different widths of hands?
0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 41853157
Thanks Slick, I work in Chrome and it works fine, at least for the svg/rect elements. That code was used in some examples I found and I worked from there, MDN is the first place I look for javascript help.

The transform/rotate setting was part of the original fiddle posted in the question (function rot). There does seem to be some inconsistencies with the svg properties that seem better when looking at the actual original code mentioned in the fiddle.
0
 

Author Comment

by:john a
ID: 41853496
Thanks very much Dear Robert Schutt and Slick812  for your help ,  it works perfectly
0
 

Author Comment

by:john a
ID: 41853497
Can I add the the clock numbers ( 1 to 12 ) as drag and drop elements above the clock ?
0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 41853503
1. That sounds like a new question.
2a. Who do you ask this? That sounds more related to Slick's solution than mine.
2b. Also, you may have to be a bit more specific, what/how do you want to drag the number to/from?
0
 

Author Comment

by:john a
ID: 41854023
Hi Robert

For example displaying hours as circles with numbers (1 to 12 ) above the clock , and theses circles

can be dragged and dropped to hours location inside the clock .  My purpose is to design a simple task

by asking the user to drag and drop hour numbers and set a certain time for example (10:10 )

Thanks
0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 41854085
It sounds like a project, but that can't be the intention here. I have made an updated fiddle to give you an idea how to proceed: https://jsfiddle.net/0zkd68ux/5/
0
 
LVL 34

Expert Comment

by:Slick812
ID: 41854721
@ john a , , You have now seems to have changed, and asked about -
   "displaying hours as circles with numbers (1 to 12 ) above the clock than can be dragged and dropped to hours location inside the clock"

But as far as being EASY for the user to adjust the time, it may be the least trouble for the user if you just have two input SELECT controls, one for hours and one for minutes, this is easy to use and easy to understand how to operate the changes, AND easy to do the code for. I do not see that having numbers to drag into a clock display will be easier to use, and It does not seem like it would impress anyone with the "Graphical Effect" ? ? Also if you are considering a usable web site page, it must be mobil and use the TOUCH javascript events, the touchbegin and touchmove javascript events are somewhat difficult to stuff into a MOUSE code like we are doing here.
0
 

Author Comment

by:john a
ID: 41856615
@ Slick812 , the idea is to display a clock to the user and ask to setup a certain time  and put the

numbers in the correct positions. I'm doing web based clock drawing test which is normally done using

paper and pencil and have the person draw the face of a clock and put the numbers in the correct

positions. then have them draw the hands to indicate the time like 3:40 -  ( one hand of the

clock on 3 and the other on the 40 )
0
 
LVL 34

Expert Comment

by:Slick812
ID: 41857595
I did not really understand the concept you just explained in your comment, , I did see meaning in this -
    "display a clock to the user and ask to setup a certain time"

but the part about - "drawing test" - on a web page in not something I understand, sorry. But tou have here two "Display" of a clock face, one with an SVG image, , and one with a <div> HTML display. There are some "Drag and Drop" javascript librarys out there, , even some built from the JQUERY, so  you may can use a javascript dragger with one of the clock displays you have here?
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Any business that wants to seriously grow needs to keep the needs and desires of an international audience of their websites in mind. Making a website friendly to international users isn’t prohibitively expensive and can provide an incredible return…
FAQ pages provide a simple way for you to supply and for customers to find answers to the most common questions about your company. Here are six reasons why your company website should have a FAQ page
This video teaches users how to migrate an existing Wordpress website to a new domain.
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.

740 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question