UNPKG

@gizwits/vantui

Version:

机智云组件库

244 lines (237 loc) 9.13 kB
"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; } }; }