You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
296 lines
9.7 KiB
296 lines
9.7 KiB
<template>
|
|
<view class="van-circle">
|
|
<canvas class="van-circle__canvas" :type="type" :style="'width: ' + utils.addUnit(size) + ';height:' + utils.addUnit(size)" id="van-circle" canvas-id="van-circle"></canvas>
|
|
<view v-if="!text" class="van-circle__text">
|
|
<slot></slot>
|
|
</view>
|
|
<cover-view v-else class="van-circle__text">{{ text }}</cover-view>
|
|
</view>
|
|
</template>
|
|
<script module="utils" lang="wxs" src="@/miniprogram_npm/@vant/weapp/wxs/utils.wxs"></script>
|
|
<script>
|
|
'use strict';
|
|
Object.defineProperty(exports, '__esModule', {
|
|
value: true
|
|
});
|
|
var color_1 = require('../common/color');
|
|
var component_1 = require('../common/component');
|
|
var utils_1 = require('../common/utils');
|
|
var validator_1 = require('../common/validator');
|
|
var version_1 = require('../common/version');
|
|
var canvas_1 = require('./canvas');
|
|
function format(rate) {
|
|
return Math.min(Math.max(rate, 0), 100);
|
|
}
|
|
var PERIMETER = 2 * Math.PI;
|
|
var BEGIN_ANGLE = -Math.PI / 2;
|
|
var STEP = 1;
|
|
export default {
|
|
data() {
|
|
return {
|
|
hoverColor: color_1.BLUE
|
|
};
|
|
},
|
|
props: {
|
|
text: String,
|
|
lineCap: {
|
|
type: String,
|
|
default: 'round'
|
|
},
|
|
value: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
speed: {
|
|
type: Number,
|
|
default: 50
|
|
},
|
|
size: {
|
|
type: Number,
|
|
default: 100
|
|
},
|
|
fill: String,
|
|
layerColor: {
|
|
type: String,
|
|
default: color_1.WHITE
|
|
},
|
|
color: {
|
|
type: null,
|
|
default: color_1.BLUE
|
|
},
|
|
type: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
strokeWidth: {
|
|
type: Number,
|
|
default: 4
|
|
},
|
|
clockwise: {
|
|
type: Boolean,
|
|
default: true
|
|
}
|
|
},
|
|
methods: {
|
|
getContext: function () {
|
|
var that = this;
|
|
var _a = this;
|
|
var type = _a.type;
|
|
var size = _a.size;
|
|
if (type === '' || !(0, version_1.canIUseCanvas2d)()) {
|
|
var ctx = uni.createCanvasContext('van-circle', this);
|
|
return Promise.resolve(ctx);
|
|
}
|
|
var dpr = (0, utils_1.getSystemInfoSync)().pixelRatio;
|
|
return new Promise(function (resolve) {
|
|
uni.createSelectorQuery()
|
|
.in(that)
|
|
.select('#van-circle')
|
|
.node()
|
|
.exec(function (res) {
|
|
var canvas = res[0].node;
|
|
var ctx = canvas.getContext(type);
|
|
if (!that.inited) {
|
|
that.inited = true;
|
|
canvas.width = size * dpr;
|
|
canvas.height = size * dpr;
|
|
ctx.scale(dpr, dpr);
|
|
}
|
|
resolve((0, canvas_1.adaptor)(ctx));
|
|
});
|
|
});
|
|
},
|
|
setHoverColor: function () {
|
|
var that = this;
|
|
var _a = this;
|
|
var color = _a.color;
|
|
var size = _a.size;
|
|
if ((0, validator_1.isObj)(color)) {
|
|
return this.getContext().then(function (context) {
|
|
if (!context) {
|
|
return;
|
|
}
|
|
var LinearColor = context.createLinearGradient(size, 0, 0, 0);
|
|
Object.keys(color)
|
|
.sort(function (a, b) {
|
|
return parseFloat(a) - parseFloat(b);
|
|
})
|
|
.map(function (key) {
|
|
return LinearColor.addColorStop(parseFloat(key) / 100, color[key]);
|
|
});
|
|
that.hoverColor = LinearColor;
|
|
});
|
|
}
|
|
this.hoverColor = color;
|
|
return Promise.resolve();
|
|
},
|
|
presetCanvas: function (context, strokeStyle, beginAngle, endAngle, fill) {
|
|
var _a = this;
|
|
var strokeWidth = _a.strokeWidth;
|
|
var lineCap = _a.lineCap;
|
|
var clockwise = _a.clockwise;
|
|
var size = _a.size;
|
|
var position = size / 2;
|
|
var radius = position - strokeWidth / 2;
|
|
context.setStrokeStyle(strokeStyle);
|
|
context.setLineWidth(strokeWidth);
|
|
context.setLineCap(lineCap);
|
|
context.beginPath();
|
|
context.arc(position, position, radius, beginAngle, endAngle, !clockwise);
|
|
context.stroke();
|
|
if (fill) {
|
|
context.setFillStyle(fill);
|
|
context.fill();
|
|
}
|
|
},
|
|
renderLayerCircle: function (context) {
|
|
var _a = this;
|
|
var layerColor = _a.layerColor;
|
|
var fill = _a.fill;
|
|
this.presetCanvas(context, layerColor, 0, PERIMETER, fill);
|
|
},
|
|
renderHoverCircle: function (context, formatValue) {
|
|
var clockwise = this.clockwise;
|
|
// 结束角度
|
|
var progress = PERIMETER * (formatValue / 100);
|
|
var endAngle = clockwise ? BEGIN_ANGLE + progress : 3 * Math.PI - (BEGIN_ANGLE + progress);
|
|
this.presetCanvas(context, this.hoverColor, BEGIN_ANGLE, endAngle);
|
|
},
|
|
drawCircle: function (currentValue) {
|
|
var that = this;
|
|
var size = this.size;
|
|
this.getContext().then(function (context) {
|
|
if (!context) {
|
|
return;
|
|
}
|
|
context.clearRect(0, 0, size, size);
|
|
that.renderLayerCircle(context);
|
|
var formatValue = format(currentValue);
|
|
if (formatValue !== 0) {
|
|
that.renderHoverCircle(context, formatValue);
|
|
}
|
|
context.draw();
|
|
});
|
|
},
|
|
reRender: function () {
|
|
var that = this;
|
|
// tofector 动画暂时没有想到好的解决方案
|
|
var _a = this;
|
|
var value = _a.value;
|
|
var speed = _a.speed;
|
|
if (speed <= 0 || speed > 1000) {
|
|
this.drawCircle(value);
|
|
return;
|
|
}
|
|
this.clearMockInterval();
|
|
this.currentValue = this.currentValue || 0;
|
|
var run = function () {
|
|
that.interval = setTimeout(function () {
|
|
if (that.currentValue !== value) {
|
|
if (Math.abs(that.currentValue - value) < STEP) {
|
|
that.currentValue = value;
|
|
} else if (that.currentValue < value) {
|
|
that.currentValue += STEP;
|
|
} else {
|
|
that.currentValue -= STEP;
|
|
}
|
|
that.drawCircle(that.currentValue);
|
|
run();
|
|
} else {
|
|
that.clearMockInterval();
|
|
}
|
|
}, 1000 / speed);
|
|
};
|
|
run();
|
|
},
|
|
clearMockInterval: function () {
|
|
if (this.interval) {
|
|
clearTimeout(this.interval);
|
|
this.interval = null;
|
|
}
|
|
}
|
|
},
|
|
mounted: function () {
|
|
var that = this;
|
|
this.currentValue = this.value;
|
|
this.setHoverColor().then(function () {
|
|
that.drawCircle(that.currentValue);
|
|
});
|
|
},
|
|
destroyed: function () {
|
|
this.clearMockInterval();
|
|
},
|
|
watch: {
|
|
value: {
|
|
handler: function () {
|
|
var that = this;
|
|
// tofector 动画暂时没有想到好的解决方案
|
|
var _a = this;
|
|
var value = _a.value;
|
|
var speed = _a.speed;
|
|
if (speed <= 0 || speed > 1000) {
|
|
this.drawCircle(value);
|
|
return;
|
|
}
|
|
this.clearMockInterval();
|
|
this.currentValue = this.currentValue || 0;
|
|
var run = function () {
|
|
that.interval = setTimeout(function () {
|
|
if (that.currentValue !== value) {
|
|
if (Math.abs(that.currentValue - value) < STEP) {
|
|
that.currentValue = value;
|
|
} else if (that.currentValue < value) {
|
|
that.currentValue += STEP;
|
|
} else {
|
|
that.currentValue -= STEP;
|
|
}
|
|
that.drawCircle(that.currentValue);
|
|
run();
|
|
} else {
|
|
that.clearMockInterval();
|
|
}
|
|
}, 1000 / speed);
|
|
};
|
|
run();
|
|
},
|
|
|
|
immediate: true
|
|
},
|
|
|
|
size: {
|
|
handler: function () {
|
|
this.drawCircle(this.currentValue);
|
|
},
|
|
|
|
immediate: true
|
|
},
|
|
|
|
color: {
|
|
handler: function () {
|
|
var that = this;
|
|
this.setHoverColor().then(function () {
|
|
that.drawCircle(that.currentValue);
|
|
});
|
|
},
|
|
|
|
immediate: true
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
<style>
|
|
@import '../common/index.css';
|
|
.van-circle {
|
|
display: inline-block;
|
|
position: relative;
|
|
text-align: center;
|
|
}
|
|
.van-circle__text {
|
|
color: var(--circle-text-color, #323233);
|
|
left: 0;
|
|
position: absolute;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
width: 100%;
|
|
}
|
|
</style>
|
|
|