# Gauge's for Dashboard 2.0 made with ui\_template

**URL:** <https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955>\
**Category:** Dashboard\
**Tags:** dashboard-2\
**Created:** [27 February 2024 13:43 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955 "2024-02-27T13:43:09Z")\
**Posts on this page:** 1\
**Showing post:** 67

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [8 March 2024 15:21 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/67 "2024-03-08T15:21:12Z")

</div>

@Colin@arturv2000  
Made another try to make the scale divisions configurable. See if that does the trick for you.

> **Code is HERE**
>
> ```auto
> <template>
> <div class="hn-sng">
> <div class="label">{{label}}</div>
> <svg ref="hn-gauge" width="100%" height="100%" viewBox="0 0 100 100">
> <g>
> <path v-for="(item, index) in sectors" :key="index" :ref="'sector-' + index" class="sector"
> stroke-width="5" d="M 10 90 A 47.5 47.5 25 1 1 90 90"></path>
> </g>
> <g>
> <path class="tick-minor" :style="{'stroke-dasharray':minor }" pathLength="496" stroke-width="5" d="M 10 90 A 47.5 47.5 25 1 1 90 90" ></path>
> <path ref="arc" class="tick-major" :style="{'stroke-dasharray':major }" pathLength="248" stroke-width="5" d="M 10 90 A 47.5 47.5 25 1 1 90 90"></path>
> </g>
> <g>
> <text v-for="(item, index) in numbers" :key="index" class="num" text-anchor="middle" y="-37"
> :style="`rotate: ${item.r}deg;`">{{item.n}}</text>
> </g>
> <g>
> <text class="measurement" y="48" x="50%" text-anchor="middle">{{measurement}}</text>
> <text class="unit" y="75" x="50%" text-anchor="middle">{{unit}}</text>
> <text class="value" y="90" x="50%" text-anchor="middle">{{formattedValue}}</text>
> <text v-if="showUpdate" ref="update" class="update" y="100" x="0"
> text-anchor="left">{{formattedUpdate}}</text>
> </g>
> <g ref="o-needle" class="o-needle">
> <path d="M 0,0 -1.5,0 -0.15,-40 0.15,-40 1.5,0 z"></path>
> <circle cx="0" cy="0" r="3"></circle>
> </g>
> </svg>
> </div>
> </template>
> <script>
> export default{
> data(){
> return {
> //define me here
> min:-50,
> max:50,
> unit:"kg",
> label:"Yet another gauge",
> measurement:"Plums",
> updateLabel:"Last update:",
> divisors:{major:10,minor:10},
> sectors:[{start:-50,end:0,color:"#63cc25"},{start:10,end:20,color:"orange"},{start:20,end:50,color:"red"}],
> showUpdate:true,
>                 
> //no need to change
> value:0,
> updateTime:0                             
> }
> },
> methods:{
> getElement: function(name,base){
> if(base){
> return this.$refs[name]
> }
> return this.$refs[name][0]
> },
> validate: function(data){
> let ret                
> if(typeof data !== "number"){
> ret = parseFloat(data)
> if(isNaN(ret)){
> console.log("BAD DATA! gauge id:",this.id,"data:",data)
> return null
> }
> }                    
> else{
> ret = data
> }                
> return ret
> },
> range:function (n, p, r) {           
> if (n < p.minIn) {
> n=p.minIn;
> }
> if (n > p.maxIn) {
> n = p.maxIn;
> }
> if(r){
> return Math.round(((n - p.minIn) / (p.maxIn - p.minIn) * (p.maxOut - p.minOut)) + p.minOut);
> }
> return ((n - p.minIn) / (p.maxIn - p.minIn) * (p.maxOut - p.minOut)) + p.minOut;
> },
> generateNumbers:function(min,max){               
>                
> let nums = []
> let t = (max - min) / this.divisors.major;
> let i = min;
> let ro = -123
> let rp = 246 / this.divisors.major
>                
> for (let e = 0; e < this.divisors.major + 1; ++e){
> nums.push({n: i,r: ro + (e * rp) })
> i = parseFloat((i + t).toFixed(2));                   
> }
> return nums 
> },
> sectorData:function(full){               
> let params, pos, span, sec, str
> let ret = [] 
> this.sectors.forEach((sector,idx) => {
> sec = {name:'sector-'+idx,color:sector.color}
> params = {minIn:this.min, maxIn:this.max, minOut:0, maxOut:full}                   
> pos = this.range(sector.start,params,false)
> params = {minIn:0, maxIn:this.max-this.min, minOut:0, maxOut:full}
> span = this.range(sector.end - sector.start,params,false)                    
> sec.css = "0 "+pos+" "+span+" var(--dash)"
> ret.push(sec)
> })
> return ret
> },
> rotation:function(v){
> const params = {minIn:this.min, maxIn:this.max, minOut:-123, maxOut:123};
> return this.range(v,params,false) +'deg'          
> }
> 
> },
> watch: {
> msg: function(){
> if(this.msg.payload != undefined){                   
> const v = this.validate(this.msg.payload)                   
> if(v == null){
> return
> }
> this.value = v
> this.updateTime = Date.now()                    
> this.getElement('o-needle',true).style.rotate = this.rotation(this.value)                    
> }
> }
> },
> computed: {
> formattedValue: function () {
> return this.value.toFixed(1)
> },
> formattedUpdate:function (){
> return this.updateLabel+" "+this.time
> },
> time:function(){
> return new Intl.DateTimeFormat('default', {hour: 'numeric', minute: 'numeric',second: 'numeric'}).format(this.updateTime);
> },
> numbers:function(){
> return this.generateNumbers(this.min,this.max)
> },
> major:function(){
> return "1," + ((246 / this.divisors.major) - 1)           
> },
> minor:function(){
> let step = 492 / this.divisors.major / this.divisors.minor
> let line = "0," + step + ","
> step --
> for(let i=0;i<this.divisors.minor-1;++i){
> line += "1,"+step+","
> }
> line = line.slice(0, -1);
> 
> return line
> },
> offset:function(){
> return -1
> }
> 
> },
> mounted(){
>            
> const dal = this.getElement('arc',true).getTotalLength()
> const sec = this.sectorData(dal)              
> const gauge = this.getElement('hn-gauge',true)
> gauge.style.setProperty('--dash',dal)
>            
> sec.forEach(s =>{
> const sector = this.getElement(s.name,false)
> sector.style.setProperty("stroke-dasharray",s.css)
> sector.style.setProperty("stroke",s.color)
> })            
> 
> }
> 
> }
> </script>
> <style>
> .hn-sng {
> position: relative;
> }
> 
> .hn-sng .label {
> position: absolute;
> font-size: 1rem;
> color: currentColor;
> text-align: center;
> width: 100%;
> overflow: hidden;
> white-space: nowrap;
> text-overflow: ellipsis;
> }
> 
> .hn-sng .value {
> fill: currentColor;
> font-weigth: 600;
> }
> 
> .hn-sng .unit {
> fill: currentColor;
> font-size: 0.4rem;
> }
> 
> .hn-sng .measurement {
> fill: currentColor;
> font-size: 0.5rem;
> }
> 
> .hn-sng .update {
> fill: currentColor;
> fill-opacity: 0.6;
> font-size: 0.35rem;
> }
> 
> .hn-sng .num {
> transform-origin: center 64%;
> transform: translate(50%, 64%);
> fill: currentColor;
> fill-opacity: 0.6;
> font-size: .35rem;
> }
> 
> .hn-sng .tick-minor {       
> stroke-dashoffset: -2;
> fill: none;
> stroke: currentColor;
> stroke-opacity: 0.6;
> }
> 
> .hn-sng .tick-major {
> stroke-dashoffset: -1;
> fill: none;
> stroke: currentColor;
> }
> 
> .hn-sng .sector {
> fill: none;
> stroke: transparent;
> }
> .hn-sng .sector:first-of-type {
> stroke-dashoffset:-0.5;
> }
> 
> .hn-sng .o-needle {
> transform-origin: center 64%;
> transform: translate(50%, 64%);
> transition: rotate .5s;
> }
> 
> .hn-sng .o-needle path,
> .hn-sng .o-needle circle {
> fill: currentColor;
> }
> </style>
> 
> ```

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/f/2/f2c187a8e90e26a026834d71dcae53cc3d127480.png)

---

_[View the full topic](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955)._
