@gizwits/vantui
Version:
机智云组件库
244 lines (237 loc) • 9.13 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.RingSlider = void 0;
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _components = require("@tarojs/components");
var _react = require("react");
var _taro = _interopRequireDefault(require("@tarojs/taro"));
var _jsxRuntime = require("react/jsx-runtime");
var RingSlider = function RingSlider(props) {
var _props$value = props.value,
value = _props$value === void 0 ? 0 : _props$value,
onChange = props.onChange,
_props$startAngle = props.startAngle,
startAngle = _props$startAngle === void 0 ? 45 : _props$startAngle,
_props$endAngle = props.endAngle,
endAngle = _props$endAngle === void 0 ? 315 : _props$endAngle,
_props$lineWidth = props.lineWidth,
lineWidth = _props$lineWidth === void 0 ? 15 : _props$lineWidth,
_props$strokeBgColor = props.strokeBgColor,
strokeBgColor = _props$strokeBgColor === void 0 ? '#EEEEEE' : _props$strokeBgColor,
_props$strokeTintColo = props.strokeTintColor,
strokeTintColor = _props$strokeTintColo === void 0 ? '#3FBEA2' : _props$strokeTintColo,
_props$width = props.width,
width = _props$width === void 0 ? 200 : _props$width,
_props$indicatorR = props.indicatorR,
indicatorR = _props$indicatorR === void 0 ? 0 : _props$indicatorR,
_props$indicatorLineW = props.indicatorLineWidth,
indicatorLineWidth = _props$indicatorLineW === void 0 ? 8 : _props$indicatorLineW,
_props$indicatorTintC = props.indicatorTintColor,
indicatorTintColor = _props$indicatorTintC === void 0 ? '#cccccc' : _props$indicatorTintC,
_props$showScale = props.showScale,
showScale = _props$showScale === void 0 ? false : _props$showScale,
_props$scaleColor = props.scaleColor,
scaleColor = _props$scaleColor === void 0 ? '#3FBEA2' : _props$scaleColor;
var ctxRef = (0, _react.useRef)(null);
var idxRef = (0, _react.useRef)("van-ring-slider_uni_".concat(+new Date()).concat(Math.ceil(Math.random() * 10000)));
(0, _react.useEffect)(function () {
setTimeout(function () {
var ctx = _taro.default.createCanvasContext(idxRef.current);
ctxRef.current = ctx;
draw(percent);
}, 100);
}, []);
var cx = width / 2;
var cy = width / 2;
var r = width / 2 - 8 * 2;
var _useState = (0, _react.useState)(value),
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
percent = _useState2[0],
setPercent = _useState2[1];
var preValRef = (0, _react.useRef)(percent);
var draw = function draw(newPercent) {
var ctx = ctxRef.current;
if (ctx == null) return;
if (showScale) {
var numberOfLines = 40;
var angleIncrement = (endAngle - startAngle) / numberOfLines;
var outerRadius = r + 10;
// 绘制刻度线
for (var i = 0; i <= numberOfLines; i++) {
var angle = startAngle + i * angleIncrement;
var adjustedAngle = d2r(angle, true);
var lineLength = 4;
if (i == 4 || i == 20 || i == 36) {
lineLength = 7;
}
// 计算刻度线的起点坐标(在外圆上)
var startX = cx + (outerRadius + lineLength) * Math.cos(adjustedAngle);
var startY = cy + (outerRadius + lineLength) * Math.sin(adjustedAngle);
// 计算刻度线的终点坐标(在内圆上)
var endX = cx + outerRadius * Math.cos(adjustedAngle);
var endY = cy + outerRadius * Math.sin(adjustedAngle);
ctx.beginPath();
ctx.moveTo(startX, startY);
ctx.lineTo(endX, endY);
ctx.strokeStyle = scaleColor;
ctx.lineWidth = 1;
if (i == 4 || i == 20 || i == 36) {
ctx.lineWidth = 2;
}
ctx.stroke();
}
}
var tintGradient = getGradientBy(strokeTintColor, ctx, width);
var bgGradient = getGradientBy(strokeBgColor, ctx, width);
// 绘制背景
ctx.setLineWidth(lineWidth);
ctx.setStrokeStyle(bgGradient);
ctx.setLineCap('round'); // 设置条的断点样式
ctx.beginPath();
ctx.arc(cx, cy, r, d2r(startAngle), d2r(endAngle));
ctx.stroke();
// 绘制进度
ctx.setLineWidth(lineWidth);
ctx.setStrokeStyle(tintGradient);
ctx.setLineCap('round');
ctx.beginPath();
var indicatorAngle = startAngle + newPercent / 100 * (endAngle - startAngle);
ctx.arc(cx, cy, r, d2r(startAngle), d2r(indicatorAngle));
ctx.stroke();
if (indicatorR && indicatorR > 0) {
// 渲染指示器
var _getXYBy = getXYBy(indicatorAngle),
_getXYBy2 = (0, _slicedToArray2.default)(_getXYBy, 2),
indicatorX = _getXYBy2[0],
indicatorY = _getXYBy2[1];
ctx.beginPath();
ctx.arc(indicatorX, indicatorY, indicatorR, 0, 2 * Math.PI, false);
ctx.lineWidth = indicatorLineWidth;
var indicatorGradient = getGradientBy(indicatorTintColor, ctx, width);
ctx.setStrokeStyle(indicatorGradient);
ctx.stroke();
}
ctx.draw();
};
function getPercentByAngle(angle) {
var endAngle = 360 - startAngle;
if (angle < startAngle) return 0;
if (angle > endAngle) return 100;
var normalizedAngle = angle;
while (normalizedAngle < startAngle) {
normalizedAngle += 360;
}
while (normalizedAngle > endAngle) {
normalizedAngle -= 360;
}
return (normalizedAngle - startAngle) / (endAngle - startAngle) * 100;
}
function getAngleByXY(mouseX, mouseY) {
var θ1 = Math.atan2(width - cx, 0);
var θ2 = Math.atan2(mouseY - cx, mouseX - cx);
var θ = θ2 - θ1;
if (θ < 0) {
θ += 2 * Math.PI;
}
var angleInDegrees = θ * 180 / Math.PI;
return angleInDegrees;
}
var setPercentByTouchEvent = function setPercentByTouchEvent(e, isMoving) {
var _e$touches;
var _e$touches$ = e === null || e === void 0 ? void 0 : (_e$touches = e.touches) === null || _e$touches === void 0 ? void 0 : _e$touches[0],
x = _e$touches$.x,
y = _e$touches$.y;
if (x && y) {
var newAngle = getAngleByXY(x, y);
var newPercent = getPercentByAngle(newAngle);
var diffVal = Math.abs(newPercent - preValRef.current);
// If the diff of percent is greater than 90, it means that the user is dragging the indicator corss the 0 degree
if (isMoving && diffVal > 90) return;
draw(newPercent);
// Cache preValRef to calculate the diff of percent
preValRef.current = percent;
setPercent(newPercent);
}
};
function getXYBy(angle) {
var fixedAngle = angle - 270;
// 根据角度计算坐标
var newX = cx + r * Math.cos(d2r(fixedAngle, false));
var newY = cy + r * Math.sin(d2r(fixedAngle, false));
return [newX, newY];
}
var handleTouchStart = function handleTouchStart(e) {
setPercentByTouchEvent(e);
};
var handleTouchMove = throttle(function (e) {
console.log("handleTouchMove", percent);
setPercentByTouchEvent(e, true);
}, 16.6);
var handleTouchEnd = function handleTouchEnd(e) {
onChange(percent);
};
var canvasRef = (0, _react.useRef)(null);
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Canvas, {
ref: canvasRef
// @ts-ignore
,
width: width
// @ts-ignore
,
height: width,
onTouchStart: handleTouchStart,
onTouchMove: handleTouchMove,
onTouchEnd: handleTouchEnd,
canvasId: idxRef.current,
nativeProps: {
width: width,
height: width
}
// type="2d"
,
style: 'width: ' + "".concat(width, "px") + ';height:' + "".concat(width, "px")
});
};
exports.RingSlider = RingSlider;
var _default = RingSlider;
/**============================================= util =========================================================== */
exports.default = _default;
function getColors(strokeTintColor) {
if (typeof strokeTintColor === 'string') return [strokeTintColor, strokeTintColor];
return strokeTintColor;
}
function getGradientBy(colors, ctx, width) {
var _getColors = getColors(colors),
_getColors2 = (0, _slicedToArray2.default)(_getColors, 2),
startColor = _getColors2[0],
endColor = _getColors2[1];
var gradient = ctx.createLinearGradient(0, 0, width, 0);
gradient.addColorStop(0, startColor);
gradient.addColorStop(1, endColor);
return gradient;
}
var d2r = function d2r(degree) {
var hasOffset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
/**
* 在canvas中,绘制弧度的起始方向是在3点钟,但这样不利于我们接下来的计算
* 将其修改至6点钟
*/
var offset = hasOffset ? 90 : 0;
return (offset + degree) * Math.PI / 180;
};
function throttle(fn, delay) {
// 上一次调用的时间
var lastTime = 0;
return function () {
// 获取当前时间
var currentTime = new Date().getTime();
// 如果当前时间与上一次调用的时间差大于等于 delay,则调用函数
if (currentTime - lastTime >= delay) {
fn.apply(this, arguments);
lastTime = currentTime;
}
};
}