UNPKG

quasar

Version:

Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time

144 lines (118 loc) 4.38 kB
import { h, computed, getCurrentInstance } from 'vue' import useSize from '../../composables/private/use-size.js' import { useCircularCommonProps } from './use-circular-progress.js' import { createComponent } from '../../utils/private/create.js' import { hMergeSlotSafely } from '../../utils/private/render.js' import { between } from '../../utils/format.js' const radius = 50, diameter = 2 * radius, circumference = diameter * Math.PI, strokeDashArray = Math.round(circumference * 1000) / 1000 export default createComponent({ name: 'QCircularProgress', props: { ...useCircularCommonProps, value: { type: Number, default: 0 }, animationSpeed: { type: [ String, Number ], default: 600 }, indeterminate: Boolean }, setup (props, { slots }) { const { proxy: { $q } } = getCurrentInstance() const sizeStyle = useSize(props) const svgStyle = computed(() => { const angle = ($q.lang.rtl === true ? -1 : 1) * props.angle return { transform: props.reverse !== ($q.lang.rtl === true) ? `scale3d(-1, 1, 1) rotate3d(0, 0, 1, ${ -90 - angle }deg)` : `rotate3d(0, 0, 1, ${ angle - 90 }deg)` } }) const circleStyle = computed(() => ( props.instantFeedback !== true && props.indeterminate !== true ? { transition: `stroke-dashoffset ${ props.animationSpeed }ms ease 0s, stroke ${ props.animationSpeed }ms ease` } : '' )) const viewBox = computed(() => diameter / (1 - props.thickness / 2)) const viewBoxAttr = computed(() => `${ viewBox.value / 2 } ${ viewBox.value / 2 } ${ viewBox.value } ${ viewBox.value }` ) const normalized = computed(() => between(props.value, props.min, props.max)) const strokeDashOffset = computed(() => circumference * ( 1 - (normalized.value - props.min) / (props.max - props.min) )) const strokeWidth = computed(() => props.thickness / 2 * viewBox.value) function getCircle ({ thickness, offset, color, cls, rounded }) { return h('circle', { class: 'q-circular-progress__' + cls + (color !== void 0 ? ` text-${ color }` : ''), style: circleStyle.value, fill: 'transparent', stroke: 'currentColor', 'stroke-width': thickness, 'stroke-dasharray': strokeDashArray, 'stroke-dashoffset': offset, 'stroke-linecap': rounded, cx: viewBox.value, cy: viewBox.value, r: radius }) } return () => { const svgChild = [] props.centerColor !== void 0 && props.centerColor !== 'transparent' && svgChild.push( h('circle', { class: `q-circular-progress__center text-${ props.centerColor }`, fill: 'currentColor', r: radius - strokeWidth.value / 2, cx: viewBox.value, cy: viewBox.value }) ) props.trackColor !== void 0 && props.trackColor !== 'transparent' && svgChild.push( getCircle({ cls: 'track', thickness: strokeWidth.value, offset: 0, color: props.trackColor }) ) svgChild.push( getCircle({ cls: 'circle', thickness: strokeWidth.value, offset: strokeDashOffset.value, color: props.color, rounded: props.rounded === true ? 'round' : void 0 }) ) const child = [ h('svg', { class: 'q-circular-progress__svg', style: svgStyle.value, viewBox: viewBoxAttr.value, 'aria-hidden': 'true' }, svgChild) ] props.showValue === true && child.push( h('div', { class: 'q-circular-progress__text absolute-full row flex-center content-center', style: { fontSize: props.fontSize } }, slots.default !== void 0 ? slots.default() : [ h('div', normalized.value) ]) ) return h('div', { class: `q-circular-progress q-circular-progress--${ props.indeterminate === true ? 'in' : '' }determinate`, style: sizeStyle.value, role: 'progressbar', 'aria-valuemin': props.min, 'aria-valuemax': props.max, 'aria-valuenow': props.indeterminate === true ? void 0 : normalized.value }, hMergeSlotSafely(slots.internal, child)) // "internal" is used by QKnob } } })