svghmi/widget_slider.ysl2
branchsvghmi
changeset 3024 0a9f6f29b7dd
parent 3021 49799de67540
child 3045 f6d428330e04
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/svghmi/widget_slider.ysl2	Wed Aug 12 15:24:02 2020 +0200
@@ -0,0 +1,169 @@
+// widget_slider.ysl2
+
+template "widget[@type='Slider']", mode="widget_class"
+    ||
+    class SliderWidget extends Widget{
+        frequency = 5;
+        range = undefined;
+        fi = undefined;
+        drag = false;
+        enTimer = false;
+
+        dispatch(value) {
+            if(this.value_elt)
+                this.value_elt.textContent = String(value);
+
+            this.update_DOM(value, this.handle_elt);
+
+        }
+
+        last_drag = false;
+
+        update_DOM(value, elt){
+            let [min,max,start,totallength] = this.range;
+            let length = Math.max(0,Math.min(totallength,(Number(value)-min)*totallength/(max-min)));
+            let tip = this.range_elt.getPointAtLength(length);
+            elt.setAttribute('transform',"translate("+(tip.x-start.x)+","+(tip.y-start.y)+")");
+
+            if(this.setpoint_elt != undefined){
+                if(this.last_drag!= this.drag){
+                    if(this.drag){
+                        this.setpoint_elt.setAttribute("style", this.setpoint_style);
+                    }else{
+                        this.setpoint_elt.setAttribute("style", "display:none");
+                    }
+                    this.last_drag = this.drag;
+                }
+            }
+        }
+
+        on_release(evt) {
+            window.removeEventListener("touchmove", this.on_bound_drag, true);
+            window.removeEventListener("mousemove", this.on_bound_drag, true);
+
+            window.removeEventListener("mouseup", this.bound_on_release, true)
+            window.removeEventListener("touchend", this.bound_on_release, true);
+            window.removeEventListener("touchcancel", this.bound_on_release, true);
+            if(this.drag){
+                this.drag = false;
+            }
+            this.update_position(evt);
+        }
+
+
+        on_drag(evt){
+            if(this.enTimer && this.drag){
+                this.update_position(evt);
+                //reset timer
+                this.enTimer = false;
+                setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100);
+            }
+        }
+
+        update_position(evt){
+            var html_dist = 0;
+
+            //calculate size of widget in html
+            var range_borders = this.range_elt.getBoundingClientRect();
+            var range_length = Math.sqrt( range_borders.height*range_borders.height + range_borders.width*range_borders.width );
+            var [minX,minY,maxX,maxY] = [range_borders.left,range_borders.bottom,range_borders.right,range_borders.top];
+
+            //get range and mouse coordinates
+            var mouseX = undefined;
+            var mouseY = undefined;
+            if (evt.type.startsWith("touch")){
+                mouseX = Math.ceil(evt.touches[0].clientX);
+                mouseY = Math.ceil(evt.touches[0].clientY);
+            }
+            else{
+                mouseX = evt.pageX;
+                mouseY = evt.pageY;
+            }
+
+            //get handle distance from mouse position
+            if (minX > mouseX && minY < mouseY){
+                html_dist = 0;
+            }
+            else if (maxX < mouseX && maxY > mouseY){
+                html_dist = range_length;
+            }
+            else{
+                // calculate distace
+                if(this.fi > 0.7){
+                    html_dist = (minY - mouseY)/Math.sin(this.fi);
+                }
+                else{
+                    html_dist = (mouseX - minX)/Math.cos(this.fi);
+                }
+
+                //check if in range
+                if (html_dist > range_length){
+                    html_dist = range_length;
+                }
+                else if (html_dist < 0){
+                    html_dist = 0;
+                }
+
+            }
+
+            this.svg_dist=Math.ceil((html_dist/range_length)*this.range[1]);
+
+            this.apply_hmi_value(0, this.svg_dist);
+
+            // update ghost cursor
+            if(this.setpoint_elt != undefined){
+                this.request_animate();
+            }
+        }
+
+        animate(){
+            this.update_DOM(this.svg_dist, this.setpoint_elt);
+        }
+
+        on_select(evt){
+            this.drag = true;
+            this.enTimer = true;
+            window.addEventListener("touchmove", this.on_bound_drag, true);
+            window.addEventListener("mousemove", this.on_bound_drag, true);
+
+            window.addEventListener("mouseup", this.bound_on_release, true)
+            window.addEventListener("touchend", this.bound_on_release, true);
+            window.addEventListener("touchcancel", this.bound_on_release, true);
+            this.update_position(evt);
+        }
+
+        init() {
+            let min = this.min_elt ?
+                        Number(this.min_elt.textContent) :
+                        this.args.length >= 1 ? this.args[0] : 0;
+            let max = this.max_elt ?
+                        Number(this.max_elt.textContent) :
+                        this.args.length >= 2 ? this.args[1] : 100;
+
+            this.range = [min, max, this.range_elt.getPointAtLength(0),this.range_elt.getTotalLength()];
+            let start = this.range_elt.getPointAtLength(0);
+            let end = this.range_elt.getPointAtLength(this.range_elt.getTotalLength());
+            this.fi = Math.atan2(start.y-end.y, end.x-start.x);
+
+            this.bound_on_select = this.on_select.bind(this);
+            this.bound_on_release = this.on_release.bind(this);
+            this.on_bound_drag = this.on_drag.bind(this);
+
+            this.element.addEventListener("mousedown", this.bound_on_select);
+            this.element.addEventListener("touchstart", this.bound_on_select);
+
+            if(this.setpoint_elt != undefined){
+                this.setpoint_style = this.setpoint_elt.getAttribute("style");
+                this.setpoint_elt.setAttribute("style", "display:none");
+            }
+
+        }
+    }
+    ||
+
+template "widget[@type='Slider']", mode="widget_defs" {
+    param "hmi_element";
+    labels("handle range");
+    optional_labels("value min max setpoint");
+    |,
+}