UNPKG

framework7-vue

Version:

Build full featured iOS & Android apps using Framework7 & Vue

170 lines 5.47 kB
import { renderList as _renderList, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock, normalizeClass as _normalizeClass, renderSlot as _renderSlot } from "vue"; const _hoisted_1 = ["width", "height", "viewBox"]; const _hoisted_2 = ["d", "fill", "data-index", "onClick", "onMouseenter"]; function render(_ctx, _cache) { return _openBlock(), _createElementBlock("div", { ref: "elRef", class: _normalizeClass(_ctx.classes) }, [(_openBlock(), _createElementBlock("svg", { xmlns: "http://www.w3.org/2000/svg", width: _ctx.size, height: _ctx.size, viewBox: `-${_ctx.size / 3} -${_ctx.size / 3} ${_ctx.size * 2 / 3} ${_ctx.size * 2 / 3}`, style: { transform: 'rotate(-90deg)' } }, [(_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.paths, (path, index) => { return _openBlock(), _createElementBlock("path", { key: path.label || index, d: path.points, fill: path.color, "data-index": index, class: _normalizeClass(_ctx.classNames({ 'pie-chart-hidden': _ctx.currentIndex !== null && _ctx.currentIndex !== index })), onClick: $event => _ctx.setCurrentIndex(index), onMouseenter: $event => _ctx.setCurrentIndex(index), onMouseleave: _cache[0] || (_cache[0] = $event => _ctx.setCurrentIndex(null)) }, null, 42, _hoisted_2); }), 128))], 8, _hoisted_1)), _renderSlot(_ctx.$slots, "default")], 2); } import { computed, onBeforeUnmount, ref, watch } from 'vue'; import { classNames } from '../shared/utils.js'; import { f7 } from '../shared/f7.js'; export default { name: 'f7-pie-chart', render, props: { size: { type: Number, default: 320 }, tooltip: Boolean, datasets: { type: Array, default: () => [] }, formatTooltip: Function }, emits: ['select'], setup(props, { emit }) { const elRef = ref(null); let f7Tooltip = null; const currentIndex = ref(null); const setCurrentIndex = index => { currentIndex.value = index; }; const summValue = computed(() => { let summ = 0; props.datasets.map(d => d.value || 0).forEach(value => { summ += value; }); return summ; }); const paths = computed(() => { const p = []; let cumulativePercentage = 0; function getCoordinatesForPercentage(percentage) { const x = Math.cos(2 * Math.PI * percentage) * (props.size / 3); const y = Math.sin(2 * Math.PI * percentage) * (props.size / 3); return [x, y]; } props.datasets.forEach(({ value, label, color }) => { const percentage = value / summValue.value; const [startX, startY] = getCoordinatesForPercentage(cumulativePercentage); cumulativePercentage += percentage; const [endX, endY] = getCoordinatesForPercentage(cumulativePercentage); const largeArcFlag = percentage > 0.5 ? 1 : 0; const points = [`M ${startX} ${startY}`, // Move `A ${props.size / 3} ${props.size / 3} 0 ${largeArcFlag} 1 ${endX} ${endY}`, // Arc 'L 0 0' // Line ].join(' '); p.push({ points, label, color }); }); return p; }); const formatTooltipText = () => { if (currentIndex.value === null) return ''; const { value, label, color } = props.datasets[currentIndex.value]; const percentage = value / summValue.value * 100; const round = v => { if (parseInt(v, 10) === v) return v; return Math.round(v * 100) / 100; }; if (props.formatTooltip) { return props.formatTooltip({ index: currentIndex.value, value, label, color, percentage }); } const tooltipText = `${label ? `${label}: ` : ''}${round(value)} (${round(percentage)}%)`; return ` <div class="pie-chart-tooltip-label"> <span class="pie-chart-tooltip-color" style="background-color: ${color};"></span> ${tooltipText} </div> `; }; const setTooltip = () => { const index = currentIndex.value; if (index === null && !f7Tooltip) return; if (!props.tooltip || !elRef.value || !f7) return; if (index !== null && !f7Tooltip) { f7Tooltip = f7.tooltip.create({ trigger: 'manual', containerEl: elRef.value, targetEl: elRef.value.querySelector(`path[data-index="${index}"]`), text: formatTooltipText(), cssClass: 'pie-chart-tooltip' }); f7Tooltip.show(); return; } if (!f7Tooltip) return; if (index !== null) { f7Tooltip.setText(formatTooltipText()); f7Tooltip.setTargetEl(elRef.value.querySelector(`path[data-index="${index}"]`)); f7Tooltip.show(); } else { f7Tooltip.hide(); } }; watch(() => currentIndex.value, () => { emit('select', currentIndex.value, props.datasets[currentIndex.value]); setTooltip(); }); onBeforeUnmount(() => { if (f7Tooltip && f7Tooltip.destroy) { f7Tooltip.destroy(); } f7Tooltip = null; }); const classes = computed(() => classNames('pie-chart')); return { elRef, currentIndex, classes, paths, classNames, setCurrentIndex }; } };