Just for fun.
[{"id":"1e1a0b8d6b5f1c5a","type":"ui_template","z":"bf0d83d32eec75c2","group":"55888982bdd0637f","name":"oldscool-gauge with blue negative digits","order":6,"width":"6","height":"1","format":"<style>\n .negative-blue .fg-num:nth-child(-n+3) {\n color: #0052d7;\n }\n</style>\n<div ng-init=\"init()\" id=\"{{'fg_'+$id}}\" class=\"fg-body\">\n <div class=\"fg-display\">\n <div class=\"fg-backplate\">\n <div class=\"fg-numbers\"> \n </div>\n </div>\n <div class=\"fg-needle\"></div>\n </div> \n</div>\n\n<script>\n(function(scope) {\n //display contains those numbers. min and max will be taken from this\n const numbers = [-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13] \n\n // the width of the plate must be big enough to fit all numbers.\n // bigger plate with less numbers increases the spacing betwwen digits\n \n const plateSize = 600;\n \n //boundaries must be determined by using browser developer tools\n //find element with class name \"fg-backplate\" and change the \"right\" property\n //to find suitable value - left for lowest limit and right for highest limit \n const movingLimits = {left:-132,right:435};\n \n const min = numbers[0];\n const max = numbers[numbers.length-1];\n let nums\n let root\n let plate\n let lastValue = null\n \n scope.init = function(){\n if($(\"#fg_\"+scope.$id).length){\n actuallyInit()\n }\n else{\n setTimeout(function(){\n actuallyInit()\n },40)\n }\n }\n\n const range = function (n, p, a, r) {\n if (a == \"clamp\") {\n if (n < p.minin) { \n n=p.minin; \n } \n if (n> p.maxin) {\n n = p.maxin;\n }\n }\n if (a == \"roll\") {\n let d = p.maxin - p.minin;\n n = ((n - p.minin) % d + d) % d + p.minin;\n }\n let v = ((n - p.minin) / (p.maxin - p.minin) * (p.maxout - p.minout)) + p.minout;\n if (r) {\n v = Math.round(v);\n }\n return v\n }\n\n const actuallyInit = function(){\n root = $(\"#fg_\"+scope.$id)\n nums = root.find(\".fg-numbers\")[0]\n plate = root.find(\".fg-backplate\")\n plate.css('width',plateSize)\n build()\n draw()\n }\n\n const build = function(){\n numbers.forEach(n => {\n let num = document.createElement('div')\n num.className = 'fg-num';\n num.textContent = n\n nums.appendChild(num)\n })\n }\n const position = function(v){ \n const p = {minin:min, maxin:max, minout:movingLimits.left, maxout:movingLimits.right}; \n return range(v,p,'clamp',false) + 'px';\n }\n\n const draw = function(){\n if(plate && lastValue){\n plate.css('right',position(lastValue))\n }\n }\n\n scope.$watch('msg', function(msg) {\n if (msg) { \n lastValue = msg.payload\n draw()\n }\n });\n})(scope);\n</script>\n","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"negative-blue","x":660,"y":1020,"wires":[[]]},{"id":"e44443b8b3e42e1c","type":"inject","z":"bf0d83d32eec75c2","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"2.5","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":230,"y":1020,"wires":[["f3b778e1c2cee77f"]]},{"id":"f3b778e1c2cee77f","type":"function","z":"bf0d83d32eec75c2","name":"random","func":"function randomBetween(min, max) { // min and max included \n return Math.random() * (max - min + 1) + min\n}\n\nmsg.payload = randomBetween(-3, 13)\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":380,"y":1020,"wires":[["1e1a0b8d6b5f1c5a"]]},{"id":"66a438e99e4a8c78","type":"ui_template","z":"bf0d83d32eec75c2","group":"55888982bdd0637f","name":"oldscool-gauge","order":6,"width":"6","height":"1","format":"<div ng-init=\"init()\" id=\"{{'fg_'+$id}}\" class=\"fg-body\">\n <div class=\"fg-display\">\n <div class=\"fg-backplate\">\n <div class=\"fg-numbers\"> \n </div>\n </div>\n <div class=\"fg-needle\"></div>\n </div> \n</div>\n\n\n<script>\n(function(scope) {\n //display contains those numbers. min and max will be taken from this\n const numbers = [0,10,20,30,40,50,60,70,80,90,100] \n\n // the width of the plate must be big enough to fit all numbers.\n // bigger plate with less numbers increases the spacing betwwen digits\n \n const plateSize = 600;\n \n //boundaries must be determined by using browser developer tools\n //find element with class name \"fg-backplate\" and change the \"right\" property\n //to find suitable value - left for lowest limit and right for highest limit \n const movingLimits = {left:-132,right:435};\n \n const min = numbers[0];\n const max = numbers[numbers.length-1];\n let nums\n let root\n let plate\n let lastValue = null\n \n scope.init = function(){\n if($(\"#fg_\"+scope.$id).length){\n actuallyInit()\n }\n else{\n setTimeout(function(){\n actuallyInit()\n },40)\n }\n }\n\n const range = function (n, p, a, r) {\n if (a == \"clamp\") {\n if (n < p.minin) { \n n=p.minin; \n } \n if (n> p.maxin) {\n n = p.maxin;\n }\n }\n if (a == \"roll\") {\n let d = p.maxin - p.minin;\n n = ((n - p.minin) % d + d) % d + p.minin;\n }\n let v = ((n - p.minin) / (p.maxin - p.minin) * (p.maxout - p.minout)) + p.minout;\n if (r) {\n v = Math.round(v);\n }\n return v\n }\n\n const actuallyInit = function(){\n root = $(\"#fg_\"+scope.$id)\n nums = root.find(\".fg-numbers\")[0]\n plate = root.find(\".fg-backplate\")\n plate.css('width',plateSize)\n build()\n draw()\n }\n\n const build = function(){\n numbers.forEach(n => {\n let num = document.createElement('div')\n num.className = 'fg-num';\n num.textContent = n\n nums.appendChild(num)\n })\n }\n const position = function(v){ \n const p = {minin:min, maxin:max, minout:movingLimits.left, maxout:movingLimits.right}; \n return range(v,p,'clamp',false) + 'px';\n }\n\n const draw = function(){\n if(plate && lastValue){\n plate.css('right',position(lastValue))\n }\n }\n\n scope.$watch('msg', function(msg) {\n if (msg) { \n lastValue = msg.payload\n draw()\n }\n });\n})(scope);\n</script>\n","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":580,"y":1060,"wires":[[]]},{"id":"5384461fccbc85cb","type":"inject","z":"bf0d83d32eec75c2","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"2","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":230,"y":1060,"wires":[["94d17c103c63e67b"]]},{"id":"94d17c103c63e67b","type":"function","z":"bf0d83d32eec75c2","name":"random","func":"function randomBetween(min, max) { // min and max included \n return Math.random() * (max - min + 1) + min\n}\n\nmsg.payload = randomBetween(0, 100)\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":380,"y":1060,"wires":[["66a438e99e4a8c78"]]},{"id":"c8e9293339d84eb3","type":"ui_template","z":"bf0d83d32eec75c2","group":"674712f8d915bcc0","name":"oldscool-gauge-css","order":6,"width":0,"height":0,"format":"<style>\n .fg-body {\n position: relative;\n width: 100%;\n height: 100%;\n display: flex;\n align-content: center;\n flex-wrap: wrap;\n }\n\n .fg-numbers {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n height: 30px;\n align-content: center;\n flex-wrap: wrap;\n }\n\n\n .fg-backplate {\n width: 600px;\n position: relative;\n transition: 1s ease-in-out;\n }\n\n .fg-backplate:before {\n content: \"\";\n position: absolute;\n right: 0%;\n width: 100%;\n top: 0px;\n height: 25%;\n background: linear-gradient(to right,\n #00000050,\n #00000050 50%,\n transparent 50%,\n transparent);\n background-size: 0.6% 100%;\n }\n\n .fg-backplate:after {\n content: \"Gauges by hotNipi ®\";\n position: absolute;\n font-size: 9px;\n left: -90px;\n top: 9px;\n color: #00000080;\n }\n\n .fg-display {\n width: 100%;\n position: relative;\n box-sizing: border-box;\n overflow: hidden;\n border: 3px solid black;\n background-color: #c7c7c7;\n outline: 1px solid #4d4d4d;\n outline-offset: -2px;\n border-radius: 6px;\n box-shadow: inset 0 0 9px 1px black;\n }\n\n .fg-display:before,\n .fg-display:after {\n content: \"\";\n position: absolute;\n inset: 0;\n\n }\n\n .fg-display:before {\n background: linear-gradient(270deg, #000000b0, transparent 20%);\n }\n\n .fg-display:after {\n background: linear-gradient(90deg, #000000b0, transparent 20%);\n }\n\n .fg-num {\n position: relative;\n text-align: center;\n top: 3px;\n width: 30px;\n color: black;\n }\n\n .fg-needle {\n position: absolute;\n left: calc(50% - 1px);\n top: 1px;\n width: 2px;\n height: 21px;\n background-color: #eb1e1e;\n box-shadow: 0px 0px 7px 2px #0000008c;\n }\n</style>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"global","className":"","x":590,"y":980,"wires":[[]]},{"id":"55888982bdd0637f","type":"ui_group","name":"1. group","tab":"62083694d0eab7ca","order":1,"disp":true,"width":"6","collapse":false,"className":""},{"id":"674712f8d915bcc0","type":"ui_group","name":"1. group","tab":"8482b305c416b850","order":1,"disp":true,"width":"6","collapse":true,"className":"ordered-1"},{"id":"62083694d0eab7ca","type":"ui_tab","name":"Home","icon":"dashboard","order":1,"disabled":false,"hidden":false},{"id":"8482b305c416b850","type":"ui_tab","name":"Away","icon":"dashboard","disabled":false,"hidden":false}]