victory-canvas
Version:
HTML5 Canvas Components for Victory
90 lines (88 loc) • 2.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.CanvasBar = void 0;
var _react = _interopRequireDefault(require("react"));
var _victoryBar = require("victory-bar");
var _useCanvasContext = require("./hooks/use-canvas-context");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const evaluateProps = props => {
/**
* Potential evaluated props of following must be evaluated in this order:
* 1) `style`
* 2) `barWidth`
* 3) `cornerRadius`
*/
const style = (0, _victoryBar.getStyle)(props.style, props);
const barWidth = (0, _victoryBar.getBarWidth)(props.barWidth, Object.assign({}, props, {
style
}));
const cornerRadius = (0, _victoryBar.getCornerRadius)(props.cornerRadius, Object.assign({}, props, {
style,
barWidth
}));
const modifiedProps = Object.assign({}, props, {
style,
barWidth,
cornerRadius
});
return modifiedProps;
};
const usePreviousValue = value => {
const ref = _react.default.useRef();
_react.default.useEffect(() => {
ref.current = value;
});
return ref.current;
};
const CanvasBar = props => {
const {
canvasRef
} = (0, _useCanvasContext.useCanvasContext)();
const modifiedProps = evaluateProps(props);
const {
polar,
style,
barWidth,
cornerRadius,
origin
} = modifiedProps;
const path2d = _react.default.useMemo(() => {
const p = polar ? (0, _victoryBar.getPolarBarPath)(modifiedProps, cornerRadius) : (0, _victoryBar.getBarPath)(modifiedProps, barWidth, cornerRadius);
return new Path2D(p);
}, [polar, barWidth, cornerRadius, modifiedProps]);
const previousPath = usePreviousValue(path2d);
const draw = _react.default.useCallback((ctx, path) => {
ctx.fillStyle = style.fill;
ctx.strokeStyle = style.stroke;
ctx.globalAlpha = style.fillOpacity;
ctx.lineWidth = style.strokeWidth;
if (polar) {
ctx.translate(origin?.x || 0, origin?.y || 0);
}
ctx.fill(path);
ctx.setTransform(1, 0, 0, 1, 0, 0);
}, [style, origin, polar]);
// This will clear the previous bar without clearing the entire canvas
const clearPreviousPath = _react.default.useCallback(ctx => {
if (previousPath) {
ctx.save();
// This ensures that the entire shape is erased
const strokeWidth = style.strokeWidth || 0;
ctx.lineWidth = strokeWidth + 2;
ctx.globalCompositeOperation = "destination-out";
draw(ctx, previousPath);
ctx.stroke(previousPath);
ctx.restore();
}
}, [draw, previousPath, style]);
_react.default.useEffect(() => {
const ctx = canvasRef.current?.getContext("2d");
if (!ctx) return;
clearPreviousPath(ctx);
draw(ctx, path2d);
}, [canvasRef, draw, polar, barWidth, cornerRadius, modifiedProps, path2d, clearPreviousPath]);
return null;
};
exports.CanvasBar = CanvasBar;