index.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import { createNamespace, isObject, addUnit } from '../utils';
  2. import { raf, cancelRaf } from '../utils/dom/raf';
  3. var _createNamespace = createNamespace('circle'),
  4. createComponent = _createNamespace[0],
  5. bem = _createNamespace[1];
  6. var PERIMETER = 3140;
  7. var uid = 0;
  8. function format(rate) {
  9. return Math.min(Math.max(rate, 0), 100);
  10. }
  11. function getPath(clockwise, viewBoxSize) {
  12. var sweepFlag = clockwise ? 1 : 0;
  13. return "M " + viewBoxSize / 2 + " " + viewBoxSize / 2 + " m 0, -500 a 500, 500 0 1, " + sweepFlag + " 0, 1000 a 500, 500 0 1, " + sweepFlag + " 0, -1000";
  14. }
  15. export default createComponent({
  16. props: {
  17. text: String,
  18. size: [Number, String],
  19. color: [String, Object],
  20. layerColor: String,
  21. strokeLinecap: String,
  22. value: {
  23. type: Number,
  24. default: 0
  25. },
  26. speed: {
  27. type: [Number, String],
  28. default: 0
  29. },
  30. fill: {
  31. type: String,
  32. default: 'none'
  33. },
  34. rate: {
  35. type: [Number, String],
  36. default: 100
  37. },
  38. strokeWidth: {
  39. type: [Number, String],
  40. default: 40
  41. },
  42. clockwise: {
  43. type: Boolean,
  44. default: true
  45. }
  46. },
  47. beforeCreate: function beforeCreate() {
  48. this.uid = "van-circle-gradient-" + uid++;
  49. },
  50. computed: {
  51. style: function style() {
  52. var size = addUnit(this.size);
  53. return {
  54. width: size,
  55. height: size
  56. };
  57. },
  58. path: function path() {
  59. return getPath(this.clockwise, this.viewBoxSize);
  60. },
  61. viewBoxSize: function viewBoxSize() {
  62. return +this.strokeWidth + 1000;
  63. },
  64. layerStyle: function layerStyle() {
  65. return {
  66. fill: "" + this.fill,
  67. stroke: "" + this.layerColor,
  68. strokeWidth: this.strokeWidth + "px"
  69. };
  70. },
  71. hoverStyle: function hoverStyle() {
  72. var offset = PERIMETER * this.value / 100;
  73. return {
  74. stroke: "" + (this.gradient ? "url(#" + this.uid + ")" : this.color),
  75. strokeWidth: +this.strokeWidth + 1 + "px",
  76. strokeLinecap: this.strokeLinecap,
  77. strokeDasharray: offset + "px " + PERIMETER + "px"
  78. };
  79. },
  80. gradient: function gradient() {
  81. return isObject(this.color);
  82. },
  83. LinearGradient: function LinearGradient() {
  84. var _this = this;
  85. var h = this.$createElement;
  86. if (!this.gradient) {
  87. return;
  88. }
  89. var Stops = Object.keys(this.color).sort(function (a, b) {
  90. return parseFloat(a) - parseFloat(b);
  91. }).map(function (key, index) {
  92. return h("stop", {
  93. "key": index,
  94. "attrs": {
  95. "offset": key,
  96. "stop-color": _this.color[key]
  97. }
  98. });
  99. });
  100. return h("defs", [h("linearGradient", {
  101. "attrs": {
  102. "id": this.uid,
  103. "x1": "100%",
  104. "y1": "0%",
  105. "x2": "0%",
  106. "y2": "0%"
  107. }
  108. }, [Stops])]);
  109. }
  110. },
  111. watch: {
  112. rate: {
  113. handler: function handler(rate) {
  114. this.startTime = Date.now();
  115. this.startRate = this.value;
  116. this.endRate = format(rate);
  117. this.increase = this.endRate > this.startRate;
  118. this.duration = Math.abs((this.startRate - this.endRate) * 1000 / this.speed);
  119. if (this.speed) {
  120. cancelRaf(this.rafId);
  121. this.rafId = raf(this.animate);
  122. } else {
  123. this.$emit('input', this.endRate);
  124. }
  125. },
  126. immediate: true
  127. }
  128. },
  129. methods: {
  130. animate: function animate() {
  131. var now = Date.now();
  132. var progress = Math.min((now - this.startTime) / this.duration, 1);
  133. var rate = progress * (this.endRate - this.startRate) + this.startRate;
  134. this.$emit('input', format(parseFloat(rate.toFixed(1))));
  135. if (this.increase ? rate < this.endRate : rate > this.endRate) {
  136. this.rafId = raf(this.animate);
  137. }
  138. }
  139. },
  140. render: function render() {
  141. var h = arguments[0];
  142. return h("div", {
  143. "class": bem(),
  144. "style": this.style
  145. }, [h("svg", {
  146. "attrs": {
  147. "viewBox": "0 0 " + this.viewBoxSize + " " + this.viewBoxSize
  148. }
  149. }, [this.LinearGradient, h("path", {
  150. "class": bem('layer'),
  151. "style": this.layerStyle,
  152. "attrs": {
  153. "d": this.path
  154. }
  155. }), h("path", {
  156. "attrs": {
  157. "d": this.path
  158. },
  159. "class": bem('hover'),
  160. "style": this.hoverStyle
  161. })]), this.slots() || this.text && h("div", {
  162. "class": bem('text')
  163. }, [this.text])]);
  164. }
  165. });