可设置canvas的width、height属性动态设置画布大小,不要通过css设置画布的宽高,不然可能导致画布变形
import React, { useRef, useEffect } from "react";
import "./index.less";
/*
* 签名组件
@params width 画布宽度
@params height 画布高度
@params fillStyle 绘制图形的填充色
@params strokeStyle 绘制图形的描边色
@params lineWidth 线宽
@params lineCap 线条末端样式
@params lineJoin 线条间连接样式
*/
export default function Signature(props) {
const {
width = 300,
height = 150,
fillStyle = "#fff",
strokeStyle = "#000",
lineWidth = 1,
lineCap = "butt",
lineJoin = "miter",
onChange = () => {}
} = props;
const canvasRef = useRef(); // canvas
const ctxRef = useRef(); // canvas的2d上下文
useEffect(() => {
const init = () => {
let moveing = false;
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");
ctxRef.current = ctx;
canvas.addEventListener("mousedown", (e) => {
if (!moveing) {
ctx.moveTo(e.offsetX, e.offsetY);
moveing = true;
}
});
canvas.addEventListener(
"mousemove",
(e) => {
if (moveing) {
ctx.lineTo(e.offsetX, e.offsetY);
ctx.fillStyle = fillStyle;
ctx.strokeStyle = strokeStyle;
ctx.lineWidth = lineWidth < 1 ? 1 : lineWidth;
ctx.lineCap = lineCap;
ctx.lineJoin = lineJoin;
ctx.stroke();
}
},
false
);
canvas.addEventListener(
"mouseup",
() => {
moveing = false;
// 将canvas转换成base64的url
const url = canvas.toDataURL("signature/png");
onChange(url);
},
false
);
canvas.addEventListener(
"mouseleave",
() => {
moveing = false;
},
false
);
};
init();
}, []);
// 清除画布
const onClearHandler = () => {
const ctx = ctxRef.current;
ctx.clearRect(0, 0, width, height);
ctx.beginPath();
onChange("");
};
return (
<div className="signatureWrapper">
<canvas className="signatureBox" ref={canvasRef} width={width} height={height}>
Your browser not support!
</canvas>
<span className="signature-clear" onClick={() => onClearHandler()}>
CLEAR
</span>
</div>
);
}
.signatureWrapper {
position: relative;
width: fit-content;
.signatureBox {
box-shadow: 0 1px 8px rgb(0, 0, 0, 0.3);
}
.signature-clear {
position: absolute;
right: 30px;
bottom: 10px;
padding: 2px 8px;
cursor: pointer;
color: red;
}
}