# HG changeset patch # User usveticic # Date 1596633363 -7200 # Node ID 0ea6b4f435de1119062ed5b26ca1d15593b888c9 # Parent 65471f50b4217d2c5192e24ac2ce45e2a8cd5af7 Create new CircularSlider widget which extand class widget diff -r 65471f50b421 -r 0ea6b4f435de svghmi/widget_circularslider.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svghmi/widget_circularslider.ysl2 Wed Aug 05 15:16:03 2020 +0200 @@ -0,0 +1,159 @@ +// widget_circuralslider.ysl2 + +template "widget[@type='CircularSlider']", mode="widget_class" + || + class CircularSliderWidget extends Widget{ + frequency = 5; + range = undefined; + circle = undefined; + handle_pos = undefined; + drag = false; + enTimer = false; + + dispatch(value) { + if(!this.drag){ + if(this.value_elt) + this.value_elt.textContent = String(value); + + this.handle_position(value); + } + } + + handle_position(value){ + let [min,max,totalDistance] = this.range; + let length = Math.max(0,Math.min((totalDistance),(Number(value)-min)/(max-min)*(totalDistance))); + let tip = this.range_elt.getPointAtLength(length); + this.handle_elt.setAttribute('transform',"translate("+(tip.x-this.handle_pos.x)+","+(tip.y-this.handle_pos.y)+")"); + } + + on_release(evt) { + if(this.drag){ + this.drag = false; + } + } + + update_position(evt){ + if(this.drag && this.enTimer){ + var svg_dist = 0; + + //calculate center of widget in html + // --TODO maybe it would be better to bind this part to window change size event ??? + let [xdest,ydest,svgWidth,svgHeight] = page_desc[current_visible_page].bbox; + let [cX, cY,fiStart,fiEnd,minMax,x1,y1,width,height] = this.circle; + let htmlCirc = this.range_elt.getBoundingClientRect(); + let cxHtml = ((htmlCirc.right-htmlCirc.left)/(width)*(cX-x1))+htmlCirc.left; + let cyHtml = ((htmlCirc.bottom-htmlCirc.top)/(height)*(cY-y1))+htmlCirc.top; + + + //get mouse coordinates + let mouseX = undefined; + let 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; + } + + //calculate angle + let fi = Math.atan2(cyHtml-mouseY, mouseX-cxHtml); + + // transform from 0 to 2PI + if (fi > 0){ + fi = 2*Math.PI-fi; + } + else{ + fi = -fi; + } + + //offset it to 0 + fi = fi - fiStart; + if (fi < 0){ + fi = fi + 2*Math.PI; + } + + //get handle distance from mouse position + if(fi= 1 ? this.args[0] : 0; + let max = this.max_elt ? + Number(this.max_elt.textContent) : + this.args.length >= 2 ? this.args[1] : 100; + + //fiStart ==> offset + let fiStart = Number(this.range_elt.getAttribute('sodipodi:start')); + let fiEnd = Number(this.range_elt.getAttribute('sodipodi:end')); + fiEnd = fiEnd - fiStart; + + //fiEnd ==> size of angle + if (fiEnd < 0){ + fiEnd = 2*Math.PI + fiEnd; + } + + //min max barrier angle + let minMax = (2*Math.PI - fiEnd)/2; + + //get parameters from svg + let cX = Number(this.range_elt.getAttribute('sodipodi:cx')); + let cY = Number(this.range_elt.getAttribute('sodipodi:cy')); + this.range_elt.style.strokeMiterlimit="0"; //eliminates some weird border around html object + this.range = [min, max,this.range_elt.getTotalLength()]; + let cPos = this.range_elt.getBBox(); + this.handle_pos = this.range_elt.getPointAtLength(0); + this.circle = [cX, cY,fiStart,fiEnd,minMax,cPos.x,cPos.y,cPos.width,cPos.height]; + + //init events + this.handle_elt.addEventListener("touchstart", hmi_widgets[this.element_id].on_select.bind(this)); + this.handle_elt.addEventListener("mousedown", hmi_widgets[this.element_id].on_select.bind(this)); + this.element.addEventListener("mousedown", hmi_widgets[this.element_id].on_select.bind(this)); + + window.addEventListener("touchmove", hmi_widgets[this.element_id].update_position.bind(this)); + window.addEventListener("mousemove", hmi_widgets[this.element_id].update_position.bind(this)); + + window.addEventListener("mouseup", hmi_widgets[this.element_id].on_release.bind(this)) + window.addEventListener("touchend", hmi_widgets[this.element_id].on_release.bind(this)); + window.addEventListener("touchcancel", hmi_widgets[this.element_id].on_release.bind(this)); + + } + } + || + +template "widget[@type='CircularSlider']", mode="widget_defs" { + param "hmi_element"; + labels("handle range"); + optional_labels("value min max"); + |, +} \ No newline at end of file