framework7
Version:
Full featured mobile HTML framework for building iOS & Android apps
298 lines (296 loc) • 9.2 kB
JavaScript
/* eslint no-nested-ternary: off */
import { getDocument } from 'ssr-window';
import $ from '../../shared/dom7.js';
import { extend, deleteProps } from '../../shared/utils.js';
import Framework7Class from '../../shared/class.js';
/** @jsx $jsx */
import $jsx from '../../shared/$jsx.js';
class Gauge extends Framework7Class {
constructor(app, params) {
if (params === void 0) {
params = {};
}
super(params, [app]);
const self = this;
const defaults = extend({}, app.params.gauge);
// Extend defaults with modules params
self.useModulesParams(defaults);
self.params = extend(defaults, params);
const {
el
} = self.params;
if (!el) return self;
const $el = $(el);
if ($el.length === 0) return self;
if ($el[0].f7Gauge) return $el[0].f7Gauge;
extend(self, {
app,
$el,
el: $el && $el[0]
});
$el[0].f7Gauge = self;
// Install Modules
self.useModules();
self.init();
return self;
}
calcRadius() {
const self = this;
const {
size,
borderWidth
} = self.params;
return size / 2 - borderWidth / 2;
}
calcBorderLength() {
const self = this;
const radius = self.calcRadius();
return 2 * Math.PI * radius;
}
render() {
const self = this;
if (self.params.render) return self.params.render.call(self, self);
const {
type,
value,
size,
bgColor,
borderBgColor,
borderColor,
borderWidth,
valueText,
valueTextColor,
valueFontSize,
valueFontWeight,
labelText,
labelTextColor,
labelFontSize,
labelFontWeight
} = self.params;
const semiCircle = type === 'semicircle';
const radius = self.calcRadius();
const length = self.calcBorderLength();
const progress = Math.max(Math.min(value, 1), 0);
return $jsx("svg", {
class: "gauge-svg",
width: `${size}px`,
height: `${semiCircle ? size / 2 : size}px`,
viewBox: `0 0 ${size} ${semiCircle ? size / 2 : size}`
}, semiCircle && $jsx("path", {
class: "gauge-back-semi",
d: `M${size - borderWidth / 2},${size / 2} a1,1 0 0,0 -${size - borderWidth},0`,
stroke: borderBgColor,
"stroke-width": borderWidth,
fill: bgColor || 'none'
}), semiCircle && $jsx("path", {
class: "gauge-front-semi",
d: `M${size - borderWidth / 2},${size / 2} a1,1 0 0,0 -${size - borderWidth},0`,
stroke: borderColor,
"stroke-width": borderWidth,
"stroke-dasharray": length / 2,
"stroke-dashoffset": length / 2 * (1 + progress),
fill: borderBgColor ? 'none' : bgColor || 'none'
}), !semiCircle && borderBgColor && $jsx("circle", {
class: "gauge-back-circle",
stroke: borderBgColor,
"stroke-width": borderWidth,
fill: bgColor || 'none',
cx: size / 2,
cy: size / 2,
r: radius
}), !semiCircle && $jsx("circle", {
class: "gauge-front-circle",
transform: `rotate(-90 ${size / 2} ${size / 2})`,
stroke: borderColor,
"stroke-width": borderWidth,
"stroke-dasharray": length,
"stroke-dashoffset": length * (1 - progress),
fill: borderBgColor ? 'none' : bgColor || 'none',
cx: size / 2,
cy: size / 2,
r: radius
}), valueText && $jsx("text", {
class: "gauge-value-text",
x: "50%",
y: semiCircle ? '100%' : '50%',
"font-weight": valueFontWeight,
"font-size": valueFontSize,
fill: valueTextColor,
dy: semiCircle ? labelText ? -labelFontSize - 15 : -5 : 0,
"text-anchor": "middle",
"dominant-baseline": !semiCircle && 'middle'
}, valueText), labelText && $jsx("text", {
class: "gauge-label-text",
x: "50%",
y: semiCircle ? '100%' : '50%',
"font-weight": labelFontWeight,
"font-size": labelFontSize,
fill: labelTextColor,
dy: semiCircle ? -5 : valueText ? valueFontSize / 2 + 10 : 0,
"text-anchor": "middle",
"dominant-baseline": !semiCircle && 'middle'
}, labelText));
}
update(newParams) {
if (newParams === void 0) {
newParams = {};
}
const self = this;
const document = getDocument();
const {
params,
$svgEl
} = self;
Object.keys(newParams).forEach(param => {
if (typeof newParams[param] !== 'undefined') {
params[param] = newParams[param];
}
});
if ($svgEl.length === 0) return self;
const {
value,
size,
bgColor,
borderBgColor,
borderColor,
borderWidth,
valueText,
valueTextColor,
valueFontSize,
valueFontWeight,
labelText,
labelTextColor,
labelFontSize,
labelFontWeight
} = params;
const length = self.calcBorderLength();
const progress = Math.max(Math.min(value, 1), 0);
const radius = self.calcRadius();
const semiCircle = params.type === 'semicircle';
const svgAttrs = {
width: `${size}px`,
height: `${semiCircle ? size / 2 : size}px`,
viewBox: `0 0 ${size} ${semiCircle ? size / 2 : size}`
};
Object.keys(svgAttrs).forEach(attr => {
$svgEl.attr(attr, svgAttrs[attr]);
});
if (semiCircle) {
const backAttrs = {
d: `M${size - borderWidth / 2},${size / 2} a1,1 0 0,0 -${size - borderWidth},0`,
stroke: borderBgColor,
'stroke-width': borderWidth,
fill: bgColor || 'none'
};
const frontAttrs = {
d: `M${size - borderWidth / 2},${size / 2} a1,1 0 0,0 -${size - borderWidth},0`,
stroke: borderColor,
'stroke-width': borderWidth,
'stroke-dasharray': length / 2,
'stroke-dashoffset': length / 2 * (1 + progress),
fill: borderBgColor ? 'none' : bgColor || 'none'
};
Object.keys(backAttrs).forEach(attr => {
$svgEl.find('.gauge-back-semi').attr(attr, backAttrs[attr]);
});
Object.keys(frontAttrs).forEach(attr => {
$svgEl.find('.gauge-front-semi').attr(attr, frontAttrs[attr]);
});
} else {
const backAttrs = {
stroke: borderBgColor,
'stroke-width': borderWidth,
fill: bgColor || 'none',
cx: size / 2,
cy: size / 2,
r: radius
};
const frontAttrs = {
transform: `rotate(-90 ${size / 2} ${size / 2})`,
stroke: borderColor,
'stroke-width': borderWidth,
'stroke-dasharray': length,
'stroke-dashoffset': length * (1 - progress),
fill: borderBgColor ? 'none' : bgColor || 'none',
cx: size / 2,
cy: size / 2,
r: radius
};
Object.keys(backAttrs).forEach(attr => {
$svgEl.find('.gauge-back-circle').attr(attr, backAttrs[attr]);
});
Object.keys(frontAttrs).forEach(attr => {
$svgEl.find('.gauge-front-circle').attr(attr, frontAttrs[attr]);
});
}
if (valueText) {
if (!$svgEl.find('.gauge-value-text').length) {
const textEl = document.createElementNS('http://www.w3.org/2000/svg', 'text');
textEl.classList.add('gauge-value-text');
$svgEl.append(textEl);
}
const textAttrs = {
x: '50%',
y: semiCircle ? '100%' : '50%',
'font-weight': valueFontWeight,
'font-size': valueFontSize,
fill: valueTextColor,
dy: semiCircle ? labelText ? -labelFontSize - 15 : -5 : 0,
'text-anchor': 'middle',
'dominant-baseline': !semiCircle && 'middle'
};
Object.keys(textAttrs).forEach(attr => {
$svgEl.find('.gauge-value-text').attr(attr, textAttrs[attr]);
});
$svgEl.find('.gauge-value-text').text(valueText);
} else {
$svgEl.find('.gauge-value-text').remove();
}
if (labelText) {
if (!$svgEl.find('.gauge-label-text').length) {
const textEl = document.createElementNS('http://www.w3.org/2000/svg', 'text');
textEl.classList.add('gauge-label-text');
$svgEl.append(textEl);
}
const labelAttrs = {
x: '50%',
y: semiCircle ? '100%' : '50%',
'font-weight': labelFontWeight,
'font-size': labelFontSize,
fill: labelTextColor,
dy: semiCircle ? -5 : valueText ? valueFontSize / 2 + 10 : 0,
'text-anchor': 'middle',
'dominant-baseline': !semiCircle && 'middle'
};
Object.keys(labelAttrs).forEach(attr => {
$svgEl.find('.gauge-label-text').attr(attr, labelAttrs[attr]);
});
$svgEl.find('.gauge-label-text').text(labelText);
} else {
$svgEl.find('.gauge-label-text').remove();
}
return self;
}
init() {
const self = this;
const $svgEl = $(self.render()).eq(0);
$svgEl.f7Gauge = self;
extend(self, {
$svgEl,
svgEl: $svgEl && $svgEl[0]
});
self.$el.append($svgEl);
return self;
}
destroy() {
const self = this;
if (!self.$el || self.destroyed) return;
self.$el.trigger('gauge:beforedestroy');
self.emit('local::beforeDestroy gaugeBeforeDestroy', self);
self.$svgEl.remove();
delete self.$el[0].f7Gauge;
deleteProps(self);
self.destroyed = true;
}
}
export default Gauge;