svghmi/widget_slider.ysl2
branchsvghmi
changeset 3056 827bf284feec
parent 3045 f6d428330e04
child 3059 e0db3f6a5f39
equal deleted inserted replaced
3045:f6d428330e04 3056:827bf284feec
     3 template "widget[@type='Slider']", mode="widget_class"
     3 template "widget[@type='Slider']", mode="widget_class"
     4     ||
     4     ||
     5     class SliderWidget extends Widget{
     5     class SliderWidget extends Widget{
     6         frequency = 5;
     6         frequency = 5;
     7         range = undefined;
     7         range = undefined;
       
     8         handle_orig = undefined;
       
     9         scroll_size = 10;
       
    10         min_size = 0.07;
     8         fi = undefined;
    11         fi = undefined;
     9         svg_dist = undefined;
    12         curr_value = 0;
    10         drag = false;
    13         drag = false;
    11         enTimer = false;
    14         enTimer = false;
       
    15         handle_click = undefined;
       
    16         last_drag = false;
    12 
    17 
    13         dispatch(value) {
    18         dispatch(value) {
       
    19             //save current value inside widget
       
    20             this.curr_value = value;
       
    21 
    14             if(this.value_elt)
    22             if(this.value_elt)
    15                 this.value_elt.textContent = String(value);
    23                 this.value_elt.textContent = String(value);
    16 
    24 
    17             this.update_DOM(value, this.handle_elt);
    25             //don't update if draging and setpoint ghost doesn't exist
    18 
    26             if(!this.drag || (this.setpoint_elt != undefined)){
    19         }
    27                 this.update_DOM(value, this.handle_elt);
    20 
    28             }
    21         last_drag = false;
    29         }
    22 
    30 
    23         update_DOM(value, elt){
    31         update_DOM(value, elt){
    24             let [min,max,start,totallength] = this.range;
    32             let [min,max,start,totallength] = this.range;
    25             let length = Math.max(0,Math.min(totallength,(Number(value)-min)*totallength/(max-min)));
    33             // check if handle is resizeable
    26             let tip = this.range_elt.getPointAtLength(length);
    34             if (this.scroll_size != undefined){ //size changes
    27             elt.setAttribute('transform',"translate("+(tip.x-start.x)+","+(tip.y-start.y)+")");
    35                 //get parameters
    28 
    36                 let length = Math.max(min,Math.min(max,(Number(value)-min)*max/(max-min)));
       
    37                 let tip = this.range_elt.getPointAtLength(length);
       
    38                 let handle_min = totallength*this.min_size;
       
    39 
       
    40                 let step = 1;
       
    41                 //check if range is bigger than  max displayed and recalculate step
       
    42                 if ((totallength/handle_min) < (max-min+1)){
       
    43                     step = (max-min+1)/(totallength/handle_min-1);
       
    44                 }
       
    45 
       
    46                 let kx,ky,offseY,offseX = undefined;
       
    47                 //scale on x or y axes
       
    48                 if (this.fi > 0.75){
       
    49                     //get scale factor
       
    50                     if(step > 1){
       
    51                         ky = handle_min/this.handle_orig.height;
       
    52                     }
       
    53                     else{
       
    54                         ky = (totallength-handle_min*(max-min))/this.handle_orig.height;
       
    55                     }
       
    56                     kx = 1;
       
    57                     //get 0 offset to stay inside range
       
    58                     offseY = start.y - (this.handle_orig.height + this.handle_orig.y) * ky;
       
    59                     offseX = 0;
       
    60                     //get distance from value
       
    61                     tip.y =this.range_elt.getPointAtLength(0).y - length/step *handle_min;
       
    62                 }
       
    63                 else{
       
    64                     //get scale factor
       
    65                     if(step > 1){
       
    66                         kx = handle_min/this.handle_orig.width;
       
    67                     }
       
    68                     else{
       
    69                         kx = (totallength-handle_min*(max-min))/this.handle_orig.width;
       
    70                     }
       
    71                     ky = 1;
       
    72                     //get 0 offset to stay inside range
       
    73                     offseX = start.x - (this.handle_orig.x * kx);
       
    74                     offseY = 0;
       
    75                     //get distance from value
       
    76                     tip.x =this.range_elt.getPointAtLength(0).x + length/step *handle_min;
       
    77                 }
       
    78                 elt.setAttribute('transform',"matrix("+(kx)+" 0 0 "+(ky)+" "+(tip.x-start.x+offseX)+" "+(tip.y-start.y+offseY)+")");
       
    79             }
       
    80             else{ //size stays the same
       
    81                 let length = Math.max(0,Math.min(totallength,(Number(value)-min)*totallength/(max-min)));
       
    82                 let tip = this.range_elt.getPointAtLength(length);
       
    83                 elt.setAttribute('transform',"translate("+(tip.x-start.x)+","+(tip.y-start.y)+")");
       
    84             }
       
    85 
       
    86             // show or hide ghost if exists
    29             if(this.setpoint_elt != undefined){
    87             if(this.setpoint_elt != undefined){
    30                 if(this.last_drag!= this.drag){
    88                 if(this.last_drag!= this.drag){
    31                     if(this.drag){
    89                     if(this.drag){
    32                         this.setpoint_elt.setAttribute("style", this.setpoint_style);
    90                         this.setpoint_elt.setAttribute("style", this.setpoint_style);
    33                     }else{
    91                     }else{
    37                 }
    95                 }
    38             }
    96             }
    39         }
    97         }
    40 
    98 
    41         on_release(evt) {
    99         on_release(evt) {
       
   100             //unbind events
    42             window.removeEventListener("touchmove", this.on_bound_drag, true);
   101             window.removeEventListener("touchmove", this.on_bound_drag, true);
    43             window.removeEventListener("mousemove", this.on_bound_drag, true);
   102             window.removeEventListener("mousemove", this.on_bound_drag, true);
    44 
   103 
    45             window.removeEventListener("mouseup", this.bound_on_release, true)
   104             window.removeEventListener("mouseup", this.bound_on_release, true)
    46             window.removeEventListener("touchend", this.bound_on_release, true);
   105             window.removeEventListener("touchend", this.bound_on_release, true);
    47             window.removeEventListener("touchcancel", this.bound_on_release, true);
   106             window.removeEventListener("touchcancel", this.bound_on_release, true);
       
   107 
       
   108             //reset drag flag
    48             if(this.drag){
   109             if(this.drag){
    49                 this.drag = false;
   110                 this.drag = false;
    50             }
   111             }
       
   112 
       
   113             // get final position
    51             this.update_position(evt);
   114             this.update_position(evt);
    52         }
   115 
    53 
   116         }
    54 
   117 
    55         on_drag(evt){
   118         on_drag(evt){
       
   119             //ignore drag event for X amount of time and if not selected
    56             if(this.enTimer && this.drag){
   120             if(this.enTimer && this.drag){
    57                 this.update_position(evt);
   121                 this.update_position(evt);
       
   122 
    58                 //reset timer
   123                 //reset timer
    59                 this.enTimer = false;
   124                 this.enTimer = false;
    60                 setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100);
   125                 setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100);
    61             }
   126             }
    62         }
   127         }
    63 
   128 
    64         update_position(evt){
   129         update_position(evt){
    65             var html_dist = 0;
   130             var html_dist = 0;
       
   131             let [min,max,start,totallength] = this.range;
    66 
   132 
    67             //calculate size of widget in html
   133             //calculate size of widget in html
    68             var range_borders = this.range_elt.getBoundingClientRect();
   134             var range_borders = this.range_elt.getBoundingClientRect();
       
   135             var [minX,minY,maxX,maxY] = [range_borders.left,range_borders.bottom,range_borders.right,range_borders.top];
    69             var range_length = Math.sqrt( range_borders.height*range_borders.height + range_borders.width*range_borders.width );
   136             var range_length = Math.sqrt( range_borders.height*range_borders.height + range_borders.width*range_borders.width );
    70             var [minX,minY,maxX,maxY] = [range_borders.left,range_borders.bottom,range_borders.right,range_borders.top];
       
    71 
   137 
    72             //get range and mouse coordinates
   138             //get range and mouse coordinates
    73             var mouseX = undefined;
   139             var mouseX = undefined;
    74             var mouseY = undefined;
   140             var mouseY = undefined;
    75             if (evt.type.startsWith("touch")){
   141             if (evt.type.startsWith("touch")){
    79             else{
   145             else{
    80                 mouseX = evt.pageX;
   146                 mouseX = evt.pageX;
    81                 mouseY = evt.pageY;
   147                 mouseY = evt.pageY;
    82             }
   148             }
    83 
   149 
    84             //get handle distance from mouse position
   150             // calculate position
    85             if (minX > mouseX && minY < mouseY){
   151             if (this.handle_click){ //if clicked on handle
    86                 html_dist = 0;
   152                 let moveDist = 0, resizeAdd = 0;
    87             }
   153                 let range_percent = 1;
    88             else if (maxX < mouseX && maxY > mouseY){
   154 
    89                 html_dist = range_length;
   155                 //set paramters for resizeable handle
       
   156                 if (this.scroll_size != undefined){
       
   157                     // add one more object to stay inside range
       
   158                     resizeAdd = 1;
       
   159 
       
   160                     //chack if range is bigger than display option and
       
   161                     // calculate percent of range with out handle
       
   162                     if(((max/(max*this.min_size)) < (max-min+1))){
       
   163                         range_percent = 1-this.min_size;
       
   164                     }
       
   165                     else{
       
   166                         range_percent = 1-(max-max*this.min_size*(max-min))/max;
       
   167                     }
       
   168                 }
       
   169 
       
   170                 //calculate value difference on x or y axis
       
   171                 if(this.fi > 0.7){
       
   172                     moveDist = ((max-min+resizeAdd)/(range_length*range_percent))*((this.handle_click[1]-mouseY)/Math.sin(this.fi));
       
   173                 }
       
   174                 else{
       
   175                     moveDist = ((max-min+resizeAdd)/(range_length*range_percent))*((mouseX-this.handle_click[0])/Math.cos(this.fi));
       
   176                 }
       
   177 
       
   178                 this.curr_value = Math.ceil(this.handle_click[2] + moveDist);
       
   179             }
       
   180             else{ //if clicked on widget
       
   181                 //get handle distance from mouse position
       
   182                 if (minX > mouseX && minY < mouseY){
       
   183                     html_dist = 0;
       
   184                 }
       
   185                 else if (maxX < mouseX && maxY > mouseY){
       
   186                     html_dist = range_length;
       
   187                 }
       
   188                 else{
       
   189                     if(this.fi > 0.7){
       
   190                         html_dist = (minY - mouseY)/Math.sin(this.fi);
       
   191                     }
       
   192                     else{
       
   193                         html_dist = (mouseX - minX)/Math.cos(this.fi);
       
   194                     }
       
   195                 }
       
   196                 //calculate distance
       
   197                 this.curr_value=Math.ceil((html_dist/range_length)*(this.range[1]-this.range[0])+this.range[0]);
       
   198             }
       
   199 
       
   200             //check if in range
       
   201             if (this.curr_value > max){
       
   202                 this.curr_value = max;
       
   203             }
       
   204             else if (this.curr_value < min){
       
   205                 this.curr_value = min;
       
   206             }
       
   207 
       
   208             this.apply_hmi_value(0, this.curr_value);
       
   209 
       
   210             //redraw handle
       
   211             this.request_animate();
       
   212 
       
   213         }
       
   214 
       
   215         animate(){
       
   216             // redraw handle on screen refresh
       
   217             // check if setpoint(ghost) handle exsist otherwise update main handle
       
   218             if(this.setpoint_elt != undefined){
       
   219                 this.update_DOM(this.curr_value, this.setpoint_elt);
    90             }
   220             }
    91             else{
   221             else{
    92                 // calculate distace
   222                 this.update_DOM(this.curr_value, this.handle_elt);
    93                 if(this.fi > 0.7){
   223             }
    94                     html_dist = (minY - mouseY)/Math.sin(this.fi);
       
    95                 }
       
    96                 else{
       
    97                     html_dist = (mouseX - minX)/Math.cos(this.fi);
       
    98                 }
       
    99 
       
   100                 //check if in range
       
   101                 if (html_dist > range_length){
       
   102                     html_dist = range_length;
       
   103                 }
       
   104                 else if (html_dist < 0){
       
   105                     html_dist = 0;
       
   106                 }
       
   107 
       
   108             }
       
   109 
       
   110             this.svg_dist=Math.ceil((html_dist/range_length)*this.range[1]);
       
   111 
       
   112             this.apply_hmi_value(0, this.svg_dist);
       
   113 
       
   114             // update ghost cursor
       
   115             if(this.setpoint_elt != undefined){
       
   116                 this.request_animate();
       
   117             }
       
   118         }
       
   119 
       
   120         animate(){
       
   121             this.update_DOM(this.svg_dist, this.setpoint_elt);
       
   122         }
   224         }
   123 
   225 
   124         on_select(evt){
   226         on_select(evt){
       
   227             //enable drag flag and timer
   125             this.drag = true;
   228             this.drag = true;
   126             this.enTimer = true;
   229             this.enTimer = true;
       
   230 
       
   231             //bind events
   127             window.addEventListener("touchmove", this.on_bound_drag, true);
   232             window.addEventListener("touchmove", this.on_bound_drag, true);
   128             window.addEventListener("mousemove", this.on_bound_drag, true);
   233             window.addEventListener("mousemove", this.on_bound_drag, true);
   129 
   234 
   130             window.addEventListener("mouseup", this.bound_on_release, true)
   235             window.addEventListener("mouseup", this.bound_on_release, true)
   131             window.addEventListener("touchend", this.bound_on_release, true);
   236             window.addEventListener("touchend", this.bound_on_release, true);
   132             window.addEventListener("touchcancel", this.bound_on_release, true);
   237             window.addEventListener("touchcancel", this.bound_on_release, true);
   133             this.update_position(evt);
   238 
       
   239             // check if handle was pressed
       
   240             if (evt.currentTarget == this.handle_elt){
       
   241                 //get mouse position on the handle
       
   242                 let mouseX = undefined;
       
   243                 let mouseY = undefined;
       
   244                 if (evt.type.startsWith("touch")){
       
   245                     mouseX = Math.ceil(evt.touches[0].clientX);
       
   246                     mouseY = Math.ceil(evt.touches[0].clientY);
       
   247                 }
       
   248                 else{
       
   249                     mouseX = evt.pageX;
       
   250                     mouseY = evt.pageY;
       
   251                 }
       
   252                 //save coordinates and orig value
       
   253                 this.handle_click = [mouseX,mouseY,this.curr_value];
       
   254             }
       
   255             else{
       
   256                 // get new handle position and reset if handle was not pressed
       
   257                 this.handle_click = undefined;
       
   258                 this.update_position(evt);
       
   259             }
       
   260 
       
   261             //prevent next events
       
   262             evt.stopPropagation();
   134         }
   263         }
   135 
   264 
   136         init() {
   265         init() {
       
   266             //set min max value if not defined
   137             let min = this.min_elt ?
   267             let min = this.min_elt ?
   138                         Number(this.min_elt.textContent) :
   268                         Number(this.min_elt.textContent) :
   139                         this.args.length >= 1 ? this.args[0] : 0;
   269                         this.args.length >= 1 ? this.args[0] : 0;
   140             let max = this.max_elt ?
   270             let max = this.max_elt ?
   141                         Number(this.max_elt.textContent) :
   271                         Number(this.max_elt.textContent) :
   142                         this.args.length >= 2 ? this.args[1] : 100;
   272                         this.args.length >= 2 ? this.args[1] : 100;
   143 
   273 
       
   274             // save initial parameters
       
   275             this.range_elt.style.strokeMiterlimit="0";
   144             this.range = [min, max, this.range_elt.getPointAtLength(0),this.range_elt.getTotalLength()];
   276             this.range = [min, max, this.range_elt.getPointAtLength(0),this.range_elt.getTotalLength()];
   145             let start = this.range_elt.getPointAtLength(0);
   277             let start = this.range_elt.getPointAtLength(0);
   146             let end = this.range_elt.getPointAtLength(this.range_elt.getTotalLength());
   278             let end = this.range_elt.getPointAtLength(this.range_elt.getTotalLength());
   147             this.fi = Math.atan2(start.y-end.y, end.x-start.x);
   279             this.fi = Math.atan2(start.y-end.y, end.x-start.x);
   148 
   280             this.handle_orig = this.handle_elt.getBBox();
       
   281 
       
   282             //bind functions
   149             this.bound_on_select = this.on_select.bind(this);
   283             this.bound_on_select = this.on_select.bind(this);
   150             this.bound_on_release = this.on_release.bind(this);
   284             this.bound_on_release = this.on_release.bind(this);
   151             this.on_bound_drag = this.on_drag.bind(this);
   285             this.on_bound_drag = this.on_drag.bind(this);
   152 
   286 
       
   287             this.handle_elt.addEventListener("mousedown", this.bound_on_select);
   153             this.element.addEventListener("mousedown", this.bound_on_select);
   288             this.element.addEventListener("mousedown", this.bound_on_select);
   154             this.element.addEventListener("touchstart", this.bound_on_select);
   289             this.element.addEventListener("touchstart", this.bound_on_select);
   155 
   290 
   156             if(this.setpoint_elt != undefined){
   291             if(this.setpoint_elt != undefined){
   157                 this.setpoint_style = this.setpoint_elt.getAttribute("style");
   292                 this.setpoint_style = this.setpoint_elt.getAttribute("style");