口算拍批
· 2 min read
目标 🎯:图书频道新增口算拍照批改功能,用户进入图书频道可以批改口算试题,给出批改结果和答案;
#
拍批流程- 打开客户端拍照页,等待拍好的照片回调
- 参数 photoId、path
- 将 base64 的照片转成 formData 格式,传给后端进行批改
- 判断拍批是否成功、以及有无剩余次数
- 后端返回批改结果,再处理结果
- 判断此次拍批是否过期
- 如果拍批成功跳转 拍批结果页
#
结果页#
需求 1: 我们需要圈出来错题 ❌、或者给对的题后面打对勾 ✅归一化: 目标检测中,为了方便记录数据格式,将图形坐标的 x、y 归一化到 0-1
# bbox -> feature map,把bbox的全局坐标系转换成相对于他所在的局部坐标系,左上角为原点。
bbox: [0.25229, 0.30104, 0.2806, 0.30161, 0.27748, 0.38805, 0.24917, 0.38748]left: bbox[0]top: bbox[1]width: bbox[2]-bbox[0]height: bbox[7]-bbox[1]
but! 用户拍出来的照片不可能都是水平的,所以需要前端转先转成从左向右,自上而下坐标系后,再旋转一个角度 >
#
需求 2: 点击错题 显示答案时 页面平滑的滚动 😴#
点击错题的红圈后,交互中的滚动顺序- 错题信息弹出层 弹出 (~ 0.3s)
- popup 中错题列表滚到选择的题目 (通过自定义 observer 观察)改变 observerStatus 为 true,通知后续滚动任务
- 背景图中红圈滚动到可视范围 改 observerStatus 为 false
为什么要设置个顺序?
- 在 ios 中滚动可以 3 个一起进行滚动
- 在 pc 和 andriod 中 后续滚动任务 会中断 前置滚动任务(导致第二步只滚动一部分,没有滚动到期待的位置)
- 所以使用的顺序滚动,第一步滚动结束(0.3s)、执行第二步滚动(通过自定义观察者观察 element 是否滚动到页面中)、再执行第三步
为什么自定义观察者,而不去用 Intersection Observer API
?
-
IntersectionObserver
ios 兼容性不好 只支持到 12.1+,所以自定义观察者(customObserver)
# 错题数字的滚动let ele = document.getElementById('hover')
const orientationHover = (ele: HTMLElement) => { ele.scrollIntoView({ behavior: 'smooth', inline: 'center', }) customObserver(ele)}
const customObserver = (ele: HTMLElement) => { requestAnimationFrame(() => { if (ele.getBoundingClientRect().x > 0 && ele.getBoundingClientRect().x < window.innerWidth) { console.log('滑到了屏幕中~') setObserverStatus(true) } else { customObserver(ele) } })}
useEffect(() => { if (ele) { orientationHover(ele) }}, [ele])
# 背景的滚动 useEffect(() => { if (observerStatus && pcrBg.current) { pcrBg.scrollTo({ top: errItem.bbox[1] * questionImage.height - pcrBg.clientHeight / 2, behavior: 'smooth', }) setObserverStatus(false) }}, [observerStatus])