优化点
1、当顶部有其他元素或组件时,画板笔画起笔不在落笔位置,如添加backHome组件
2、更改清除画图时,起笔长度变长问题
BackHome.js
import React, {useImperativeHandle} from 'react' import { useHistory } from 'react-router-dom' import { useLocation } from 'react-router-dom' import { Button, Divider } from 'antd' // 使用forwardRef 可以在父组件中获取到ref const BackHome = React.forwardRef((props, ref) => { useImperativeHandle(ref, () => ({ ref: ref.current })); const location = useLocation(); const history = useHistory(); const toHome = () => { history.push('/') } let name = (location.state && location.state.name) || location.pathname.slice(1, location.pathname.length) return ( <div ref={ref}> <Button onClick={toHome}>返回首页</Button> <div style={{'padding': '1px 0'}}> <Divider orientation="center"> 当前:{name} </Divider> </div> </div> ) }) export default BackHome;
Autograph.js
import React, { Component } from 'react' import { Button, Divider, Row, Col } from 'antd' import BackHome from '../component/BackHome' class Autograph extends Component { state = { base: '' // base64形式的图片 } ref=React.createRef(); componentDidMount () { this.initCanvasEvent() } initCanvas () { // 自适应设置画布大小 const vWidth = document.body.clientWidth const can = document.getElementById('canvas') can.width = vWidth can.height = vWidth // 画布准备 const context = can.getContext('2d') // 添加背景色 context.fillStyle = '#ccc' context.fillRect(0, 0, can.width, can.height) // 笔尖设置 context.strokeStyle = '#000' // 笔尖颜色 context.lineWidth = 6 // 笔尖粗度 return { can, context } } initCanvasEvent () { // 获取canvas 及 context const { can, context } = this.initCanvas() // 顶部组件的高,解决笔记不在落笔的位置 // console.log(this.ref.current.ref.clientHeight) const refHeight = this.ref.current.ref && this.ref.current.ref.clientHeight // 监听触屏事件 can.addEventListener('touchstart', (e) => { context.beginPath() context.moveTo(e.touches[0].pageX, e.touches[0].pageY - refHeight) }) can.addEventListener('touchmove', (e) => { e.preventDefault(); // 阻止页面拖动,如部分移动端,上下左右滑动手势,等 context.lineTo(e.touches[0].pageX, e.touches[0].pageY - refHeight) context.stroke() }) can.addEventListener('touchend', () => { context.closePath() }) } blankCanvas () { const blank = document.createElement('canvas') const canImg = document.getElementById('canvas') blank.width = canImg.width blank.height = canImg.height // 为使空画布与现有画图相同 (可根据实际需要修改) const context = blank.getContext('2d') context.fillStyle = '#ccc' context.fillRect(0, 0, blank.width, blank.height) // 为true 则为空画图 // console.log(canImg.toDataURL() === blank.toDataURL()); return canImg.toDataURL() === blank.toDataURL() } getCanvasImg () { const isFull = this.blankCanvas() if (isFull) { // 根据项目ui组件自行更改设置 alert('请签名') return } // 获取到base64代码 // console.log(document.querySelector('canvas').toDataURL()); this.setState({ base: document.querySelector('canvas').toDataURL() }) } clearCanvas () { // canvas每当高度或宽度被重设时,画布内容就会被清空,所以会导致之前画的圆都被删除,所以重新抽离出 initCanvas ,与事件分开 this.initCanvas() } render () { return ( <div> <BackHome ref={this.ref} /> <canvas id='canvas' disable-scroll="true"></canvas> <Divider orientation="center">手写签名</Divider> <Row justify="space-around" align="middle"> <Col> <Button onClick={this.getCanvasImg.bind(this)}>提交签名</Button> </Col> <Col> <Button onClick={this.clearCanvas.bind(this )}>清除签名</Button> </Col> </Row> <div style={{'wordBreak': 'break-all'}}> base64图片: <br/> {this.state.base} </div> </div> ) } } export default Autograph /* https://www.w3school.com.cn/tags/html_ref_canvas.asp https://blog.csdn.net/Luckyzhoufangbing/article/details/87784843 https://blog.csdn.net/weixin_30471561/article/details/97082558 */