Index: reference/jquery-plugins/javascript-fluid-meter-master/LICENSE =================================================================== diff -u --- reference/jquery-plugins/javascript-fluid-meter-master/LICENSE (revision 0) +++ reference/jquery-plugins/javascript-fluid-meter-master/LICENSE (revision 620a2782ad05c3a10709c0f43a84ee83e912e2b2) @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Angel Arcoraci + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. Index: reference/jquery-plugins/javascript-fluid-meter-master/README.md =================================================================== diff -u --- reference/jquery-plugins/javascript-fluid-meter-master/README.md (revision 0) +++ reference/jquery-plugins/javascript-fluid-meter-master/README.md (revision 620a2782ad05c3a10709c0f43a84ee83e912e2b2) @@ -0,0 +1,60 @@ +# ❗❗❗❗❗ there is a newer version (totally rewritten) of this gauges. ❗❗❗❗❗ + +https://github.com/aarcoraci/fluid-meter + +# javascript-fluid-meter + +### examples + +https://codepen.io/aarcoraci/pen/abzjaOW + +![Image Example](https://raw.githubusercontent.com/aarcoraci/javascript-fluid-meter/master/fluid-meter.gif) + +--- + +### about + +I've been playing with **canvas** for some time now and from time to time I do small projects just to practice. + +This library (aimed to be used on old browsers) renders a percentage meter as a bowl (?) with certain amount of fluid. + +### install + +download the js-fluid-meter.js and add it to your project or page + +### usage + +create as many instances as you want. Notice the target container **requires an id** + +```javascript +var fm = new FluidMeter(); +fm.init({ + targetContainer: document.getElementById("fluid-meter"), + fillPercentage: 15, + options: { + fontFamily: "Raleway", + drawPercentageSign: false, + drawBubbles: true, + size: 300, + borderWidth: 19, + backgroundColor: "#e2e2e2", + foregroundColor: "#fafafa", + foregroundFluidLayer: { + fillStyle: "purple", + angularSpeed: 100, + maxAmplitude: 12, + frequency: 30, + horizontalSpeed: -150, + }, + backgroundFluidLayer: { + fillStyle: "pink", + angularSpeed: 100, + maxAmplitude: 9, + frequency: 30, + horizontalSpeed: 150, + }, + }, +}); +``` + +--- Index: reference/jquery-plugins/javascript-fluid-meter-master/fluid-meter.gif =================================================================== diff -u Binary files differ Index: reference/jquery-plugins/javascript-fluid-meter-master/index.html =================================================================== diff -u --- reference/jquery-plugins/javascript-fluid-meter-master/index.html (revision 0) +++ reference/jquery-plugins/javascript-fluid-meter-master/index.html (revision 620a2782ad05c3a10709c0f43a84ee83e912e2b2) @@ -0,0 +1,141 @@ + + + + + + + + + + + Document + + + + +
+
+
+
+ + +
+
+
+ + +
+
+
+ + +
+
+
+ + + + + + + \ No newline at end of file Index: reference/jquery-plugins/javascript-fluid-meter-master/js/js-fluid-meter.js =================================================================== diff -u --- reference/jquery-plugins/javascript-fluid-meter-master/js/js-fluid-meter.js (revision 0) +++ reference/jquery-plugins/javascript-fluid-meter-master/js/js-fluid-meter.js (revision 620a2782ad05c3a10709c0f43a84ee83e912e2b2) @@ -0,0 +1,366 @@ +/** + * Javascript Fluid Meter + * by Angel Arcoraci + * https://github.com/aarcoraci + * + * MIT License + */ +function FluidMeter() { + var context; + var targetContainer; + + var time = null; + var dt = null; + + var options = { + drawShadow: true, + drawText: true, + drawPercentageSign: true, + drawBubbles: true, + fontSize: "70px", + fontFamily: "Arial", + fontFillStyle: "white", + size: 300, + borderWidth: 25, + backgroundColor: "#e2e2e2", + foregroundColor: "#fafafa" + }; + + var currentFillPercentage = 0; + var fillPercentage = 0; + + //#region fluid context values + var foregroundFluidLayer = { + fillStyle: "purple", + angle: 0, + horizontalPosition: 0, + angularSpeed: 0, + maxAmplitude: 9, + frequency: 30, + horizontalSpeed: -150, + initialHeight: 0 + }; + + var backgroundFluidLayer = { + fillStyle: "pink", + angle: 0, + horizontalPosition: 0, + angularSpeed: 140, + maxAmplitude: 12, + frequency: 40, + horizontalSpeed: 150, + initialHeight: 0 + }; + + var bubblesLayer = { + bubbles: [], + amount: 12, + speed: 20, + current: 0, + swing: 0, + size: 2, + reset: function (bubble) { + // calculate the area where to spawn the bubble based on the fluid area + var meterBottom = (options.size - (options.size - getMeterRadius()) / 2) - options.borderWidth; + var fluidAmount = currentFillPercentage * (getMeterRadius() - options.borderWidth * 2) / 100; + + bubble.r = random(this.size, this.size * 2) / 2; + bubble.x = random(0, options.size); + bubble.y = random(meterBottom, meterBottom - fluidAmount); + bubble.velX = 0; + bubble.velY = random(this.speed, this.speed * 2); + bubble.swing = random(0, 2 * Math.PI); + }, + init() { + for (var i = 0; i < this.amount; i++) { + + var meterBottom = (options.size - (options.size - getMeterRadius()) / 2) - options.borderWidth; + var fluidAmount = currentFillPercentage * (getMeterRadius() - options.borderWidth * 2) / 100; + this.bubbles.push({ + x: random(0, options.size), + y: random(meterBottom, meterBottom - fluidAmount), + r: random(this.size, this.size * 2) / 2, + velX: 0, + velY: random(this.speed, this.speed * 2) + }); + } + } + } + //#endregion + + /** + * initializes and mount the canvas element on the document + */ + function setupCanvas() { + var canvas = document.createElement('canvas'); + canvas.width = options.size; + canvas.height = options.size; + canvas.imageSmoothingEnabled = true; + context = canvas.getContext("2d"); + targetContainer.appendChild(canvas); + + // shadow is not required to be on the draw loop + //#region shadow + if (options.drawShadow) { + context.save(); + context.beginPath(); + context.filter = "drop-shadow(0px 4px 6px rgba(0,0,0,0.1))"; + context.arc(options.size / 2, options.size / 2, getMeterRadius() / 2, 0, 2 * Math.PI); + context.closePath(); + context.fill(); + context.restore(); + } + //#endregion + } + + /** + * draw cycle + */ + function draw() { + var now = new Date().getTime(); + dt = (now - (time || now)) / 1000; + time = now; + + requestAnimationFrame(draw); + context.clearRect(0, 0, options.size, options.size); + drawMeterBackground(); + drawFluid(dt); + if (options.drawText) { + drawText(); + } + drawMeterForeground(); + } + + function drawMeterBackground() { + context.save(); + context.fillStyle = options.backgroundColor; + context.beginPath(); + context.arc(options.size / 2, options.size / 2, getMeterRadius() / 2 - options.borderWidth, 0, 2 * Math.PI); + context.closePath(); + context.fill(); + context.restore(); + } + + function drawMeterForeground() { + context.save(); + context.lineWidth = options.borderWidth; + context.strokeStyle = options.foregroundColor; + context.beginPath(); + context.arc(options.size / 2, options.size / 2, getMeterRadius() / 2 - options.borderWidth / 2, 0, 2 * Math.PI); + context.closePath(); + context.stroke(); + context.restore(); + } + /** + * draws the fluid contents of the meter + * @param {} dt elapsed time since last frame + */ + function drawFluid(dt) { + context.save(); + context.arc(options.size / 2, options.size / 2, getMeterRadius() / 2 - options.borderWidth, 0, Math.PI * 2); + context.clip(); + drawFluidLayer(backgroundFluidLayer, dt); + drawFluidLayer(foregroundFluidLayer, dt); + if (options.drawBubbles) { + drawFluidMask(foregroundFluidLayer, dt); + drawBubblesLayer(dt); + } + context.restore(); + } + + + /** + * draws the foreground fluid layer + * @param {} dt elapsed time since last frame + */ + function drawFluidLayer(layer, dt) { + // calculate wave angle + if (layer.angularSpeed > 0) { + layer.angle += layer.angularSpeed * dt; + layer.angle = layer.angle < 0 ? layer.angle + 360 : layer.angle; + } + + // calculate horizontal position + layer.horizontalPosition += layer.horizontalSpeed * dt; + if (layer.horizontalSpeed > 0) { + layer.horizontalPosition > Math.pow(2, 53) ? 0 : layer.horizontalPosition; + } + else if (layer.horizontalPosition < 0) { + layer.horizontalPosition < -1 * Math.pow(2, 53) ? 0 : layer.horizontalPosition; + } + + var x = 0; + var y = 0; + var amplitude = layer.maxAmplitude * Math.sin(layer.angle * Math.PI / 180); + + var meterBottom = (options.size - (options.size - getMeterRadius()) / 2) - options.borderWidth; + var fluidAmount = currentFillPercentage * (getMeterRadius() - options.borderWidth * 2) / 100; + + if (currentFillPercentage < fillPercentage) { + currentFillPercentage += 15 * dt; + } else if (currentFillPercentage > fillPercentage) { + currentFillPercentage -= 15 * dt; + } + + layer.initialHeight = meterBottom - fluidAmount; + + context.save(); + context.beginPath(); + + context.lineTo(0, layer.initialHeight); + + while (x < options.size) { + y = layer.initialHeight + amplitude * Math.sin((x + layer.horizontalPosition) / layer.frequency); + context.lineTo(x, y); + x++; + } + + context.lineTo(x, options.size); + context.lineTo(0, options.size); + context.closePath(); + + context.fillStyle = layer.fillStyle; + context.fill(); + context.restore(); + } + + /** + * clipping mask for objects within the fluid constrains + * @param {Object} layer layer to be used as a mask + */ + function drawFluidMask(layer) { + var x = 0; + var y = 0; + var amplitude = layer.maxAmplitude * Math.sin(layer.angle * Math.PI / 180); + + context.beginPath(); + + context.lineTo(0, layer.initialHeight); + + while (x < options.size) { + y = layer.initialHeight + amplitude * Math.sin((x + layer.horizontalPosition) / layer.frequency); + context.lineTo(x, y); + x++; + } + context.lineTo(x, options.size); + context.lineTo(0, options.size); + context.closePath(); + context.clip(); + } + + function drawBubblesLayer(dt) { + context.save(); + for (var i = 0; i < bubblesLayer.bubbles.length; i++) { + var bubble = bubblesLayer.bubbles[i]; + + context.beginPath(); + context.strokeStyle = 'white'; + context.arc(bubble.x, bubble.y, bubble.r, 2 * Math.PI, false); + context.stroke(); + context.closePath(); + + var currentSpeed = bubblesLayer.current * dt; + + bubble.velX = Math.abs(bubble.velX) < Math.abs(bubblesLayer.current) ? bubble.velX + currentSpeed : bubblesLayer.current; + bubble.y = bubble.y - bubble.velY * dt; + bubble.x = bubble.x + (bubblesLayer.swing ? 0.4 * Math.cos(bubblesLayer.swing += 0.03) * bubblesLayer.swing : 0) + bubble.velX * 0.5; + + // determine if current bubble is outside the safe area + var meterBottom = (options.size - (options.size - getMeterRadius()) / 2) - options.borderWidth; + var fluidAmount = currentFillPercentage * (getMeterRadius() - options.borderWidth * 2) / 100; + + if (bubble.y <= meterBottom - fluidAmount) { + bubblesLayer.reset(bubble); + } + + } + context.restore(); + } + + function drawText() { + + var text = options.drawPercentageSign ? + currentFillPercentage.toFixed(0) + "%" : currentFillPercentage.toFixed(0); + + context.save(); + context.font = getFontSize(); + context.fillStyle = options.fontFillStyle; + context.textAlign = "center"; + context.textBaseline = 'middle'; + context.filter = "drop-shadow(0px 0px 5px rgba(0,0,0,0.4))" + context.fillText(text, options.size / 2, options.size / 2); + context.restore(); + } + + //#region helper methods + function clamp(number, min, max) { + return Math.min(Math.max(number, min), max); + }; + function getMeterRadius() { + return options.size * 0.9; + } + + function random(min, max) { + var delta = max - min; + return max === min ? min : Math.random() * delta + min; + } + + function getFontSize() { + return options.fontSize + " " + options.fontFamily; + } + //#endregion + + return { + init: function (env) { + if (!env.targetContainer) + throw "empty or invalid container"; + + targetContainer = env.targetContainer; + fillPercentage = clamp(env.fillPercentage, 0, 100); + + if (env.options) { + options.drawShadow = env.options.drawShadow === false ? false : true; + options.size = env.options.size; + options.drawBubbles = env.options.drawBubbles === false ? false : true; + options.borderWidth = env.options.borderWidth || options.borderWidth; + options.foregroundFluidColor = env.options.foregroundFluidColor || options.foregroundFluidColor; + options.backgroundFluidColor = env.options.backgroundFluidColor || options.backgroundFluidColor; + options.backgroundColor = env.options.backgroundColor || options.backgroundColor; + options.foregroundColor = env.options.foregroundColor || options.foregroundColor; + + options.drawText = env.options.drawText === false ? false : true; + options.drawPercentageSign = env.options.drawPercentageSign === false ? false : true; + options.fontSize = env.options.fontSize || options.fontSize; + options.fontFamily = env.options.fontFamily || options.fontFamily; + options.fontFillStyle = env.options.fontFillStyle || options.fontFillStyle; + // fluid settings + + if (env.options.foregroundFluidLayer) { + foregroundFluidLayer.fillStyle = env.options.foregroundFluidLayer.fillStyle || foregroundFluidLayer.fillStyle; + foregroundFluidLayer.angularSpeed = env.options.foregroundFluidLayer.angularSpeed || foregroundFluidLayer.angularSpeed; + foregroundFluidLayer.maxAmplitude = env.options.foregroundFluidLayer.maxAmplitude || foregroundFluidLayer.maxAmplitude; + foregroundFluidLayer.frequency = env.options.foregroundFluidLayer.frequency || foregroundFluidLayer.frequency; + foregroundFluidLayer.horizontalSpeed = env.options.foregroundFluidLayer.horizontalSpeed || foregroundFluidLayer.horizontalSpeed; + } + + if (env.options.backgroundFluidLayer) { + backgroundFluidLayer.fillStyle = env.options.backgroundFluidLayer.fillStyle || backgroundFluidLayer.fillStyle; + backgroundFluidLayer.angularSpeed = env.options.backgroundFluidLayer.angularSpeed || backgroundFluidLayer.angularSpeed; + backgroundFluidLayer.maxAmplitude = env.options.backgroundFluidLayer.maxAmplitude || backgroundFluidLayer.maxAmplitude; + backgroundFluidLayer.frequency = env.options.backgroundFluidLayer.frequency || backgroundFluidLayer.frequency; + backgroundFluidLayer.horizontalSpeed = env.options.backgroundFluidLayer.horizontalSpeed || backgroundFluidLayer.horizontalSpeed; + } + } + + + + bubblesLayer.init(); + setupCanvas(); + draw(); + }, + setPercentage(percentage) { + + fillPercentage = clamp(percentage, 0, 100); + } + } +};