2018-06-30 14:52:34 +08:00
|
|
|
<template>
|
|
|
|
<div class="md-activity-indicator-rolling">
|
|
|
|
<svg
|
|
|
|
:viewBox="`0 0 ${viewBoxSize} ${viewBoxSize}`"
|
|
|
|
:style="{width: `${size}px`, height: `${size}px`}"
|
|
|
|
preserveAspectRatio="xMidYMid"
|
|
|
|
class="md-activity-indicator-svg rolling"
|
|
|
|
>
|
|
|
|
<g
|
|
|
|
v-if="!$slots.default"
|
|
|
|
class="circle"
|
|
|
|
transform="matrix(0, 1, 1, 0, 0, 0)"
|
|
|
|
>
|
|
|
|
<circle
|
|
|
|
class="stroke"
|
|
|
|
:cx="viewBoxSize/2"
|
|
|
|
:cy="viewBoxSize/2"
|
|
|
|
:fill="fill"
|
|
|
|
:stroke="color"
|
|
|
|
:stroke-width="strokeWidth"
|
|
|
|
:stroke-dashoffset="this.circlePerimeter / 2"
|
|
|
|
:r="radius"
|
2018-06-30 19:34:33 +08:00
|
|
|
:style="circleStyle"
|
2018-06-30 14:52:34 +08:00
|
|
|
>
|
|
|
|
<animateTransform
|
2018-07-01 01:42:39 +08:00
|
|
|
v-if="process === undefined"
|
2018-06-30 14:52:34 +08:00
|
|
|
:dur="`${duration}s`"
|
|
|
|
:values="`0 ${viewBoxSize/2} ${viewBoxSize/2};360 ${viewBoxSize/2} ${viewBoxSize/2}`"
|
|
|
|
attributeName="transform"
|
|
|
|
type="rotate"
|
|
|
|
calcMode="linear"
|
|
|
|
keyTimes="0;1"
|
|
|
|
begin="0s"
|
|
|
|
repeatCount="indefinite"
|
|
|
|
></animateTransform>
|
|
|
|
</circle>
|
|
|
|
</g>
|
|
|
|
<slot v-else></slot>
|
|
|
|
</svg>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
export default {
|
|
|
|
name: 'md-activity-indicator-rolling',
|
|
|
|
|
|
|
|
props: {
|
|
|
|
size: {
|
|
|
|
type: Number,
|
|
|
|
default: 70,
|
|
|
|
},
|
|
|
|
color: {
|
|
|
|
type: String,
|
2018-08-22 14:55:06 +08:00
|
|
|
default: '#2F86F6',
|
2018-06-30 14:52:34 +08:00
|
|
|
},
|
|
|
|
fill: {
|
|
|
|
type: String,
|
|
|
|
default: 'transparent',
|
|
|
|
},
|
2018-06-30 19:34:33 +08:00
|
|
|
process: {
|
|
|
|
// process control 0-1
|
|
|
|
type: Number,
|
|
|
|
},
|
2018-06-30 14:52:34 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
computed: {
|
|
|
|
id() {
|
|
|
|
return `${this.$options.name}-keyframes-${this.size}`
|
|
|
|
},
|
|
|
|
strokeWidth() {
|
|
|
|
return this.size / 16
|
|
|
|
},
|
|
|
|
radius() {
|
|
|
|
return this.size / 2
|
|
|
|
},
|
|
|
|
viewBoxSize() {
|
|
|
|
return this.size + 2 * this.strokeWidth
|
|
|
|
},
|
|
|
|
circlePerimeter() {
|
|
|
|
return this.size * 3.1415
|
|
|
|
},
|
2018-06-30 19:34:33 +08:00
|
|
|
circleStyle() {
|
|
|
|
/* istanbul ignore else */
|
|
|
|
if (this.process === undefined) {
|
|
|
|
return {
|
|
|
|
animation: `${this.id} 2s cubic-bezier(1.0, 0.5, 0.8, 1.0) infinite`,
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return {
|
|
|
|
strokeDasharray: `${this.process * this.circlePerimeter} ${(1 - this.process) * this.circlePerimeter}`,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2018-06-30 14:52:34 +08:00
|
|
|
duration() {
|
|
|
|
return 2
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
watch: {
|
|
|
|
size: {
|
|
|
|
handler() {
|
|
|
|
this.$_insertKeyframes()
|
|
|
|
},
|
|
|
|
immediate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
methods: {
|
|
|
|
$_insertKeyframes() {
|
|
|
|
const id = this.id
|
|
|
|
const keyframes = `from{stroke-dasharray:0 ${this.circlePerimeter};}to{stroke-dasharray:${this
|
|
|
|
.circlePerimeter} 0;}`
|
|
|
|
const css = `@-webkit-keyframes ${id}{${keyframes}}@keyframes ${id}{${keyframes}}}`
|
|
|
|
|
|
|
|
let isCssExisting = true
|
|
|
|
let elem = document.getElementById(id)
|
|
|
|
|
|
|
|
if (!elem) {
|
|
|
|
elem = document.createElement('style')
|
|
|
|
elem.setAttribute('type', 'text/css')
|
|
|
|
elem.setAttribute('id', id)
|
|
|
|
isCssExisting = false
|
|
|
|
}
|
|
|
|
|
|
|
|
/* istanbul ignore else */
|
|
|
|
if ('textContent' in elem) {
|
|
|
|
elem.textContent = css
|
|
|
|
} else {
|
|
|
|
elem.styleSheet.cssText = css
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isCssExisting) {
|
|
|
|
document.getElementsByTagName('head')[0].appendChild(elem)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="stylus">
|
|
|
|
.md-activity-indicator-rolling
|
|
|
|
clearfix()
|
|
|
|
.rolling
|
|
|
|
float left
|
|
|
|
circle.stroke
|
|
|
|
will-change auto
|
|
|
|
</style>
|