This repository has been archived on 2024-07-27. You can view files and clone it, but cannot push or open issues or pull requests.
keksAccountGUI/node_modulesOLD/vuetify/lib/components/VSparkline/VSparkline.js
2019-08-11 20:48:02 +02:00

355 lines
No EOL
9.3 KiB
JavaScript

// Mixins
import Colorable from '../../mixins/colorable'; // Utilities
import mixins from '../../util/mixins';
import { genPoints, genBars } from './helpers/core';
import { genPath } from './helpers/path';
export default mixins(Colorable).extend({
name: 'VSparkline',
inheritAttrs: false,
props: {
autoDraw: Boolean,
autoDrawDuration: {
type: Number,
default: 2000
},
autoDrawEasing: {
type: String,
default: 'ease'
},
autoLineWidth: {
type: Boolean,
default: false
},
color: {
type: String,
default: 'primary'
},
fill: {
type: Boolean,
default: false
},
gradient: {
type: Array,
default: () => []
},
gradientDirection: {
type: String,
validator: val => ['top', 'bottom', 'left', 'right'].includes(val),
default: 'top'
},
height: {
type: [String, Number],
default: 75
},
labels: {
type: Array,
default: () => []
},
labelSize: {
type: [Number, String],
default: 7
},
lineWidth: {
type: [String, Number],
default: 4
},
padding: {
type: [String, Number],
default: 8
},
showLabels: Boolean,
smooth: {
type: [Boolean, Number, String],
default: false
},
type: {
type: String,
default: 'trend',
validator: val => ['trend', 'bar'].includes(val)
},
value: {
type: Array,
default: () => []
},
width: {
type: [Number, String],
default: 300
}
},
data: () => ({
lastLength: 0
}),
computed: {
parsedPadding() {
return Number(this.padding);
},
parsedWidth() {
return Number(this.width);
},
parsedHeight() {
return parseInt(this.height, 10);
},
parsedLabelSize() {
return parseInt(this.labelSize, 10) || 7;
},
totalHeight() {
let height = this.parsedHeight;
if (this.hasLabels) height += parseInt(this.labelSize, 10) * 1.5;
return height;
},
totalWidth() {
let width = this.parsedWidth;
if (this.type === 'bar') width = Math.max(this.value.length * this._lineWidth, width);
return width;
},
totalValues() {
return this.value.length;
},
_lineWidth() {
if (this.autoLineWidth && this.type !== 'trend') {
const totalPadding = this.parsedPadding * (this.totalValues + 1);
return (this.parsedWidth - totalPadding) / this.totalValues;
} else {
return parseFloat(this.lineWidth) || 4;
}
},
boundary() {
if (this.type === 'bar') return {
minX: 0,
maxX: this.totalWidth,
minY: 0,
maxY: this.parsedHeight
};
const padding = this.parsedPadding;
return {
minX: padding,
maxX: this.totalWidth - padding,
minY: padding,
maxY: this.parsedHeight - padding
};
},
hasLabels() {
return Boolean(this.showLabels || this.labels.length > 0 || this.$scopedSlots.label);
},
parsedLabels() {
const labels = [];
const points = this._values;
const len = points.length;
for (let i = 0; labels.length < len; i++) {
const item = points[i];
let value = this.labels[i];
if (!value) {
value = typeof item === 'object' ? item.value : item;
}
labels.push({
x: item.x,
value: String(value)
});
}
return labels;
},
normalizedValues() {
return this.value.map(item => typeof item === 'number' ? item : item.value);
},
_values() {
return this.type === 'trend' ? genPoints(this.normalizedValues, this.boundary) : genBars(this.normalizedValues, this.boundary);
},
textY() {
let y = this.parsedHeight;
if (this.type === 'trend') y -= 4;
return y;
},
_radius() {
return this.smooth === true ? 8 : Number(this.smooth);
}
},
watch: {
value: {
immediate: true,
handler() {
this.$nextTick(() => {
if (!this.autoDraw || this.type === 'bar') return;
const path = this.$refs.path;
const length = path.getTotalLength();
if (!this.fill) {
path.style.transition = 'none';
path.style.strokeDasharray = length + ' ' + length;
path.style.strokeDashoffset = Math.abs(length - (this.lastLength || 0)).toString();
path.getBoundingClientRect();
path.style.transition = `stroke-dashoffset ${this.autoDrawDuration}ms ${this.autoDrawEasing}`;
path.style.strokeDashoffset = '0';
} else {
path.style.transformOrigin = 'bottom center';
path.style.transition = 'none';
path.style.transform = `scaleY(0)`;
path.getBoundingClientRect();
path.style.transition = `transform ${this.autoDrawDuration}ms ${this.autoDrawEasing}`;
path.style.transform = `scaleY(1)`;
}
this.lastLength = length;
});
}
}
},
methods: {
genGradient() {
const gradientDirection = this.gradientDirection;
const gradient = this.gradient.slice(); // Pushes empty string to force
// a fallback to currentColor
if (!gradient.length) gradient.push('');
const len = Math.max(gradient.length - 1, 1);
const stops = gradient.reverse().map((color, index) => this.$createElement('stop', {
attrs: {
offset: index / len,
'stop-color': color || this.color || 'currentColor'
}
}));
return this.$createElement('defs', [this.$createElement('linearGradient', {
attrs: {
id: this._uid,
x1: +(gradientDirection === 'left'),
y1: +(gradientDirection === 'top'),
x2: +(gradientDirection === 'right'),
y2: +(gradientDirection === 'bottom')
}
}, stops)]);
},
genG(children) {
return this.$createElement('g', {
style: {
fontSize: '8',
textAnchor: 'middle',
dominantBaseline: 'mathematical',
fill: this.color || 'currentColor'
}
}, children);
},
genPath() {
const points = genPoints(this.normalizedValues, this.boundary);
return this.$createElement('path', {
attrs: {
id: this._uid,
d: genPath(points, this._radius, this.fill, this.parsedHeight),
fill: this.fill ? `url(#${this._uid})` : 'none',
stroke: this.fill ? 'none' : `url(#${this._uid})`
},
ref: 'path'
});
},
genLabels(offsetX) {
const children = this.parsedLabels.map((item, i) => this.$createElement('text', {
attrs: {
x: item.x + offsetX + this._lineWidth / 2,
y: this.textY + this.parsedLabelSize * 0.75,
'font-size': Number(this.labelSize) || 7
}
}, [this.genLabel(item, i)]));
return this.genG(children);
},
genLabel(item, index) {
return this.$scopedSlots.label ? this.$scopedSlots.label({
index,
value: item.value
}) : item.value;
},
genBars() {
if (!this.value || this.totalValues < 2) return undefined;
const bars = genBars(this.normalizedValues, this.boundary);
const offsetX = (Math.abs(bars[0].x - bars[1].x) - this._lineWidth) / 2;
return this.$createElement('svg', {
attrs: {
display: 'block',
viewBox: `0 0 ${this.totalWidth} ${this.totalHeight}`
}
}, [this.genGradient(), this.genClipPath(bars, offsetX, this._lineWidth, 'sparkline-bar-' + this._uid), this.hasLabels ? this.genLabels(offsetX) : undefined, this.$createElement('g', {
attrs: {
'clip-path': `url(#sparkline-bar-${this._uid}-clip)`,
fill: `url(#${this._uid})`
}
}, [this.$createElement('rect', {
attrs: {
x: 0,
y: 0,
width: this.totalWidth,
height: this.height
}
})])]);
},
genClipPath(bars, offsetX, lineWidth, id) {
const rounding = typeof this.smooth === 'number' ? this.smooth : this.smooth ? 2 : 0;
return this.$createElement('clipPath', {
attrs: {
id: `${id}-clip`
}
}, bars.map(item => {
return this.$createElement('rect', {
attrs: {
x: item.x + offsetX,
y: item.y,
width: lineWidth,
height: item.height,
rx: rounding,
ry: rounding
}
}, [this.autoDraw ? this.$createElement('animate', {
attrs: {
attributeName: 'height',
from: 0,
to: item.height,
dur: `${this.autoDrawDuration}ms`,
fill: 'freeze'
}
}) : undefined]);
}));
},
genTrend() {
return this.$createElement('svg', this.setTextColor(this.color, {
attrs: { ...this.$attrs,
display: 'block',
'stroke-width': this._lineWidth || 1,
viewBox: `0 0 ${this.width} ${this.totalHeight}`
}
}), [this.genGradient(), this.hasLabels && this.genLabels(-(this._lineWidth / 2)), this.genPath()]);
}
},
render(h) {
if (this.totalValues < 2) return undefined;
return this.type === 'trend' ? this.genTrend() : this.genBars();
}
});
//# sourceMappingURL=VSparkline.js.map