UNPKG

react-custom-roulette-rtl

Version:

Customizable React roulette wheel with spinning animation RTL

141 lines (140 loc) 8.59 kB
import React, { createRef, useEffect } from 'react'; import { WheelCanvasStyle } from './styles'; import { clamp, getQuantity } from '../../utils'; var drawRadialBorder = function (ctx, centerX, centerY, insideRadius, outsideRadius, angle) { ctx.beginPath(); ctx.moveTo(centerX + (insideRadius + 1) * Math.cos(angle), centerY + (insideRadius + 1) * Math.sin(angle)); ctx.lineTo(centerX + (outsideRadius - 1) * Math.cos(angle), centerY + (outsideRadius - 1) * Math.sin(angle)); ctx.closePath(); ctx.stroke(); }; var drawWheel = function (canvasRef, data, drawWheelProps) { var _a, _b, _c, _d, _e; /* eslint-disable prefer-const */ var outerBorderColor = drawWheelProps.outerBorderColor, outerBorderWidth = drawWheelProps.outerBorderWidth, innerRadius = drawWheelProps.innerRadius, innerBorderColor = drawWheelProps.innerBorderColor, innerBorderWidth = drawWheelProps.innerBorderWidth, radiusLineColor = drawWheelProps.radiusLineColor, radiusLineWidth = drawWheelProps.radiusLineWidth, fontFamily = drawWheelProps.fontFamily, fontWeight = drawWheelProps.fontWeight, fontSize = drawWheelProps.fontSize, fontStyle = drawWheelProps.fontStyle, perpendicularText = drawWheelProps.perpendicularText, prizeMap = drawWheelProps.prizeMap, textDistance = drawWheelProps.textDistance, isRTL = drawWheelProps.isRTL, selectedOption = drawWheelProps.selectedOption, selectedOptionBackgroundColor = drawWheelProps.selectedOptionBackgroundColor; var QUANTITY = getQuantity(prizeMap); outerBorderWidth *= 2; innerBorderWidth *= 2; radiusLineWidth *= 2; var canvas = canvasRef.current; if (canvas === null || canvas === void 0 ? void 0 : canvas.getContext('2d')) { var ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, 500, 500); ctx.strokeStyle = 'transparent'; ctx.lineWidth = 0; var startAngle = 0; var outsideRadius = canvas.width / 2 - 10; var clampedContentDistance = clamp(0, 100, textDistance); var contentRadius = (outsideRadius * clampedContentDistance) / 100; var clampedInsideRadius = clamp(0, 100, innerRadius); var insideRadius = (outsideRadius * clampedInsideRadius) / 100; var centerX = canvas.width / 2; var centerY = canvas.height / 2; for (var i = 0; i < data.length; i++) { var _f = data[i], optionSize = _f.optionSize, style = _f.style; var arc = (optionSize && (optionSize * (2 * Math.PI)) / QUANTITY) || (2 * Math.PI) / QUANTITY; var endAngle = startAngle + arc; ctx.fillStyle = i === selectedOption ? selectedOptionBackgroundColor : (style && style.backgroundColor); ctx.beginPath(); ctx.arc(centerX, centerY, outsideRadius, startAngle, endAngle, false); ctx.arc(centerX, centerY, insideRadius, endAngle, startAngle, true); ctx.stroke(); ctx.fill(); ctx.save(); // WHEEL RADIUS LINES ctx.strokeStyle = radiusLineWidth <= 0 ? 'transparent' : radiusLineColor; ctx.lineWidth = radiusLineWidth; drawRadialBorder(ctx, centerX, centerY, insideRadius, outsideRadius, startAngle); if (i === data.length - 1) { drawRadialBorder(ctx, centerX, centerY, insideRadius, outsideRadius, endAngle); } // WHEEL OUTER BORDER ctx.strokeStyle = outerBorderWidth <= 0 ? 'transparent' : outerBorderColor; ctx.lineWidth = outerBorderWidth; ctx.beginPath(); ctx.arc(centerX, centerY, outsideRadius - ctx.lineWidth / 2, 0, 2 * Math.PI); ctx.closePath(); ctx.stroke(); // WHEEL INNER BORDER ctx.strokeStyle = innerBorderWidth <= 0 ? 'transparent' : innerBorderColor; ctx.lineWidth = innerBorderWidth; ctx.beginPath(); ctx.arc(centerX, centerY, insideRadius + ctx.lineWidth / 2 - 1, 0, 2 * Math.PI); ctx.closePath(); ctx.stroke(); // CONTENT FILL ctx.translate(centerX + Math.cos(startAngle + arc / 2) * contentRadius, centerY + Math.sin(startAngle + arc / 2) * contentRadius); var contentRotationAngle = startAngle + arc / 2; if (data[i].image) { // CASE IMAGE contentRotationAngle += data[i].image && !((_a = data[i].image) === null || _a === void 0 ? void 0 : _a.landscape) ? Math.PI / 2 : 0; ctx.rotate(contentRotationAngle); var img = ((_b = data[i].image) === null || _b === void 0 ? void 0 : _b._imageHTML) || new Image(); ctx.drawImage(img, (img.width + (((_c = data[i].image) === null || _c === void 0 ? void 0 : _c.offsetX) || 0)) / -2, -(img.height - (((_d = data[i].image) === null || _d === void 0 ? void 0 : _d.landscape) ? 0 : 90) + // offsetY correction for non landscape images (((_e = data[i].image) === null || _e === void 0 ? void 0 : _e.offsetY) || 0)) / 2, img.width, img.height); } else { contentRotationAngle = startAngle + arc / 2; if (isRTL) { contentRotationAngle += Math.PI; ctx.textAlign = 'center'; ctx.direction = 'rtl'; } else { contentRotationAngle += perpendicularText ? Math.PI / 2 : 0; ctx.textAlign = 'center'; ctx.direction = 'ltr'; } ctx.rotate(contentRotationAngle); var text = data[i].option; if (data[i].option) { var fontFamilyFallback = isRTL ? 'Vazirmtn, system-ui' : fontFamily; var fontConfig = "".concat((style === null || style === void 0 ? void 0 : style.fontStyle) || fontStyle, " ").concat((style === null || style === void 0 ? void 0 : style.fontWeight) || fontWeight, " ").concat(((style === null || style === void 0 ? void 0 : style.fontSize) || fontSize) * 2, "px ").concat((style === null || style === void 0 ? void 0 : style.fontFamily) || fontFamilyFallback); ctx.font = fontConfig; ctx.fillStyle = (style && style.textColor); ctx.textBaseline = 'middle'; ctx.fillText(text || '', 0, 0); } } ctx.restore(); startAngle = endAngle; } } }; var WheelCanvas = function (_a) { var width = _a.width, height = _a.height, data = _a.data, outerBorderColor = _a.outerBorderColor, outerBorderWidth = _a.outerBorderWidth, innerRadius = _a.innerRadius, innerBorderColor = _a.innerBorderColor, innerBorderWidth = _a.innerBorderWidth, radiusLineColor = _a.radiusLineColor, radiusLineWidth = _a.radiusLineWidth, fontFamily = _a.fontFamily, fontWeight = _a.fontWeight, fontSize = _a.fontSize, fontStyle = _a.fontStyle, perpendicularText = _a.perpendicularText, prizeMap = _a.prizeMap, rouletteUpdater = _a.rouletteUpdater, textDistance = _a.textDistance, _b = _a.isRTL, isRTL = _b === void 0 ? false : _b, selectedOption = _a.selectedOption, selectedOptionBackgroundColor = _a.selectedOptionBackgroundColor; var canvasRef = createRef(); var drawWheelProps = { outerBorderColor: outerBorderColor, outerBorderWidth: outerBorderWidth, innerRadius: innerRadius, innerBorderColor: innerBorderColor, innerBorderWidth: innerBorderWidth, radiusLineColor: radiusLineColor, radiusLineWidth: radiusLineWidth, fontFamily: fontFamily, fontWeight: fontWeight, fontSize: fontSize, fontStyle: fontStyle, perpendicularText: perpendicularText, prizeMap: prizeMap, rouletteUpdater: rouletteUpdater, textDistance: textDistance, isRTL: isRTL, selectedOption: selectedOption, selectedOptionBackgroundColor: selectedOptionBackgroundColor, }; useEffect(function () { drawWheel(canvasRef, data, drawWheelProps); }, [canvasRef, data, drawWheelProps, rouletteUpdater]); return React.createElement(WheelCanvasStyle, { ref: canvasRef, width: width, height: height }); }; export default WheelCanvas;