UNPKG

@toast-ui/chart

Version:

TOAST UI Application: Chart

125 lines (124 loc) 5.83 kB
import { isUndefined } from "./helpers/utils"; import { calculateRadianToDegree, withinRadian } from "./helpers/sector"; function withinRotationRect({ slope, yIntercept, mouseX, mouseY, modelXPositions, compX, compY, detectionSize = 0, }) { const [x1, x2] = modelXPositions; const posY = slope * (mouseX - compX) + yIntercept; const withinRadius = (x1 > x2 && mouseX >= compX + x2 && mouseX <= compX + x1) || (x1 < x2 && mouseX <= compX + x2 && mouseX >= compX + x1); const withinDetectionSize = posY - detectionSize + compY <= mouseY && mouseY <= posY + detectionSize + compY; return withinRadius && withinDetectionSize; } export const responderDetectors = { circle: (mousePosition, model, componentRect) => { const { x, y } = mousePosition; const { x: modelX, y: modelY, radius, detectionSize } = model; const { x: compX, y: compY } = componentRect; const radiusAdjustment = isUndefined(detectionSize) ? 10 : detectionSize; return (Math.pow((x - (modelX + compX)), 2) + Math.pow((y - (modelY + compY)), 2) < Math.pow((radius + radiusAdjustment), 2)); }, rect: (mousePosition, model, componentRect = { x: 0, y: 0, width: 0, height: 0 }) => { const { x, y } = mousePosition; const { x: modelX, y: modelY, width, height } = model; const { x: compX, y: compY } = componentRect; return (x >= modelX + compX && x <= modelX + compX + width && y >= modelY + compY && y <= modelY + compY + height); }, sector: (mousePosition, model, componentRect = { x: 0, y: 0, width: 0, height: 0 }) => { const { x, y } = mousePosition; const { x: modelX, y: modelY, radius: { outer, inner }, degree: { start, end }, drawingStartAngle, clockwise, } = model; const { x: compX, y: compY } = componentRect; const xPos = x - (modelX + compX); const yPos = y - (modelY + compY); const insideOuterRadius = Math.pow(xPos, 2) + Math.pow(yPos, 2) < Math.pow(outer, 2); const outsideInnerRadius = Math.pow(xPos, 2) + Math.pow(yPos, 2) > Math.pow(inner, 2); const withinRadius = insideOuterRadius && outsideInnerRadius; const detectionDegree = calculateRadianToDegree(Math.atan2(yPos, xPos), drawingStartAngle); return withinRadius && withinRadian(clockwise, start, end, detectionDegree); }, line: (mousePosition, model, componentRect = { x: 0, y: 0, width: 0, height: 0 }) => { const { x, y } = mousePosition; const { x: compX, y: compY } = componentRect; const { x: modelX, y: modelY, x2, y2, detectionSize = 3 } = model; const numerator = y2 - modelY; const denominator = x2 - modelX; let withinLine = false; if (numerator === 0) { const minX = Math.min(modelX, x2); const maxX = Math.max(modelX, x2); withinLine = x - compX >= minX && x - compX <= maxX && y >= modelY + compY - detectionSize && y <= modelY + compY + detectionSize; } else if (denominator === 0) { const minY = Math.min(modelY, y2); const maxY = Math.max(modelY, y2); withinLine = y - compY >= minY && y - compY <= maxY && x >= modelX + compX - detectionSize && x <= modelX + compX + detectionSize; } else { const slope = numerator / denominator; const xPos = x - (modelX + compX); const yPos = y - (modelY + compY); withinLine = slope * xPos === yPos; } return withinLine; }, boxPlot: (mousePosition, model, componentRect = { x: 0, y: 0, width: 0, height: 0 }) => { return ['rect', 'median', 'minimum', 'maximum', 'upperWhisker', 'lowerWhisker'].some((prop) => { if (!model[prop]) { return false; } return prop === 'rect' ? responderDetectors.rect(mousePosition, model[prop], componentRect) : responderDetectors.line(mousePosition, model[prop], componentRect); }); }, clockHand: (mousePosition, model, componentRect = { x: 0, y: 0, width: 0, height: 0 }) => { const { x, y } = mousePosition; const { x: compX, y: compY } = componentRect; const { x: centerX, y: centerY, x2, y2, detectionSize = 5 } = model; const numerator = y2 - centerY; const denominator = x2 - centerX; let withinClockHand = false; if (numerator === 0) { const minX = Math.min(centerX, x2); const maxX = Math.max(centerX, x2); withinClockHand = x - compX >= minX && x - compX <= maxX && y >= centerY + compY - detectionSize && y <= centerY + compY + detectionSize; } else if (denominator === 0) { const minY = Math.min(centerY, y2); const maxY = Math.max(centerY, y2); withinClockHand = y - compY >= minY && y - compY <= maxY && x >= centerX + compX - detectionSize && x <= centerX + compX + detectionSize; } else { const slope = numerator / denominator; const yIntercept = centerY - slope * centerX; withinClockHand = withinRotationRect({ slope, yIntercept, mouseX: x, mouseY: y, modelXPositions: [centerX, x2], compX, compY, detectionSize, }); } return withinClockHand; }, };