📜 ⬆️ ⬇️

Set the time interval on the watch face. Javascript

Good day, dear reader.

What it is?


In the course of my development, I was faced with the task of creating a functional selection of the time interval. The first thing that came to mind was, of course, the simplest and most obvious - several text fields where the initial and final values ​​are driven in. But is it interesting? Not.

I decided to take a bit of the original.

I think the picture quite clearly demonstrates my idea: we have a clock face and 2 sliders with which we select the interval. I want to say at once that if I suddenly invented a bicycle ... hmm, well, not fatal. All the same to create more interesting than using someone else's.
')

Skeleton


I want to immediately note that I am not a web designer, and I do not have the skills to work with CSS at the guru level, so my approach may seem clumsy to someone, not right.

How to make a ring on HTML?

The ring is ready, but we need not a whole ring, but only half of it, so we will add one more item


For the final result, we need two “colored” semicircles (the code name is a sash ), and two semicircles with a background color (the code name is an anti - fold ).


Changing the position of the slider, we will rotate the sash. Anti-binders are needed to hide the leaves , when the selection interval is less than 180 grams. To hide is to display anti-folds over the doors, changing the value of z-index .

The final HTML skeleton should look like this:


How should this work?


So. We have two sliders (code name - slider 1 and slider 2 ). When you click on the slider, or rather at the onmousedown event, it is activated to move. Moving the cursor, change the position of the slider, then release the cursor (the onmouseup event) to select it.

It should be noted that the movement of the cursor should not just be chaotic in all possible directions, as if we are forming an SSH key through puttygen, it is necessary that the movement more or less resemble circular ones. To do this, when the slider is activated, the area in which movement is possible is determined. When you exit the zone, the slider is deactivated. Zone - two circles with radii larger and smaller than the radius of the circle along which the slider moves.



From the point of view of formulas, everything is simple: we count the distance that the cursor is located away from the center of the circle. Check whether this value is in the interval or not.

onmousemove
onmousemove = function(e){ /*         .         ,          */ var rect = Area.getBoundingClientRect(); var Xpoint = (e.clientX - area_radius) - rect.left; var Ypoint = (e.clientY - area_radius) - rect.top; var R = Math.sqrt(Math.pow(Xpoint,2)+Math.pow(Ypoint,2)); var a = (180*Math.acos((Xpoint-0)/R))/Math.PI; a = (Ypoint>=0) ? a=360-a : a;//  ,      move(a,R); }; 



Different coordinate systems


If everything fits, then we calculate the angle of the segment between the center of the circle and the position of the cursor. And then one uncomfortable moment pops up - different coordinate systems (SC): normal, with an initial value at the extreme right point, increasing the angle when moving counterclockwise. And watch. 00:00 we are in the highest position, and the movement, respectively, in a clockwise direction.

Elements must be moved in the usual SC, and the clock is calculated in the hour.

Boundaries of what is permitted


Each slider has borders: left and right, beyond which it can not move. That's just the creation of these boundaries and was the biggest snag.

I spent 3 days trying to come up with the right ... no, this is not the right word ... the working mechanism for handling borders. Anyone who wants to repeat my feat will come up with his “right” mechanism, with more or less success than me. I completely "re-invented" it 3 times, when, going to a certain moment, I realized that with the current mechanism, it would not be possible to make a certain moment.

As a result, the mechanism looks like this: each slider has 4 states (in the code, the variables responsible for the states are designated as sONE and sTWO ). Everything is built around them.

In fact, with positions 2 and -2, the sliders are at the same point, but the difference is from which side they came there. Accordingly, further they can only move back.

To determine in which direction the slider moves, the new value of the slider position is compared to the old one. For example, to determine when the slider moves from the first turn on the dial to the second, you need to observe the condition under which the previous angle value was in the interval: 60 <X, 0 <X , and new 0 == X; 330 <x . All similar checks are done in approximately the same way, i.e. not just checking A> B , but specifying the interval where A can be located, but where B is . You can simply pull the slider sharply and its value will immediately change to 10 or 15 degrees.

border handling
 if(R>=low_limit_polzunok_ONE && R<=high_limit_polzunok_ONE){ angle_polzunok_ONE_last = angle_polzunok_ONE; angle_polzunok_ONE = toClk(a); if(barier_ONE==true){ if(angle_polzunok_ONE>300){ if(toClk(a)>angle_polzunok_TWO+1 && toClk(a)<angle_polzunok_TWO+60+1){ move_polzunok_ONE(toCoo(angle_polzunok_ONE)); barier_ONE=false; } }else{ if(toClk(a)>angle_polzunok_TWO+1){ move_polzunok_ONE(toCoo(angle_polzunok_ONE)); barier_ONE=false; } } }else if(sONE==-2){//0 .          if(angle_polzunok_ONE>300){ sONE=-1; move_polzunok_ONE(a); }else{ angle_polzunok_ONE=360; } }else if(sONE==-1){ if(angle_polzunok_ONE>300 && (angle_polzunok_ONE_last>=0 && angle_polzunok_ONE_last<60)){ sONE=1; move_polzunok_ONE(a); }else if((angle_polzunok_ONE>=0 && angle_polzunok_ONE<60) && angle_polzunok_ONE_last>300){ sONE=-2; angle_polzunok_ONE = 0; move_polzunok_ONE(90); }else{ move_polzunok_ONE(a); } }else if(sONE==0){//  12   if(angle_polzunok_ONE>300){ sONE=1; move_polzunok_ONE(a); }else{ sONE=-1; move_polzunok_ONE(a); } }else if(sONE==1){ if((angle_polzunok_ONE>=0 && angle_polzunok_ONE<60) && angle_polzunok_ONE_last>300){ sONE=-1; move_polzunok_ONE(a); }else if((angle_polzunok_ONE==0 || angle_polzunok_ONE>300) && (angle_polzunok_ONE_last>0 && angle_polzunok_ONE_last<90)){ sONE=2; angle_polzunok_ONE = 0; move_polzunok_ONE(90); }else{ move_polzunok_ONE(a); } }else if(sONE==2){//24 .          if(angle_polzunok_ONE>0 && angle_polzunok_ONE<60){ sONE=1; move_polzunok_ONE(a); }else{ angle_polzunok_ONE=0; } } //   i     if(sTWO==sONE && angle_polzunok_TWO+1>angle_polzunok_ONE){ barier_ONE = true; angle_polzunok_ONE = angle_polzunok_TWO+1; move_polzunok_ONE(toCoo(angle_polzunok_ONE)); } }else{ polzunok_switch_ONE(false); } 


Timing


Actually on the previous paragraph ended all the most difficult and interesting. The process of calculating time is nothing special. A simple calculation of 360 g = 12 hours * 60 minutes indicates that one degree corresponds to two minutes. Knowing the degree of the slider in the clock coordinate system, it is easy to calculate the time. If the slider is on the second rotation, you need to add another 360 to the degree value.

The entire listing, as well as the result, can be found here.

On the road


My goal was to create such a thing, not for JavaScript , but for GWT . Initially easier to develop on JS, and then migrate to GWT. Therefore, I did not bother to create a convenient designer, and the procedure for calculating the date itself returns a plain text string as a result.

This is a draft. Test sample, but perhaps he will be useful to someone.

Thank you for your attention, dear reader.

PS Having finished writing a post, I realized that it would be possible to make everything easier. That's usually - "a good idea comes after."

Source: https://habr.com/ru/post/207792/


All Articles