1210 今日总结
今日工作
- 开发一个 类似 企业微信的 图片查看器,需要支持以下功能:
- 弹框拖拽移动位置;
- 弹框放大缩小
- 弹框内图片移动位置
- 弹框内图片放大缩小旋转
- 底部预览列表展示
- 左右图片切换
不写不知道,写了才知道自己的很多 js 问题不足:
1-滥用事件没有及时清除,新旧事件互相干扰:
// window.getEventListeners(dom) 使用这个 API 查看这个 dom 上有多少个事件
const img = document.querySelector('#img')
window.getEventListeners(img)
// resolve
useEffect(() => {
// register
const evFn = () => {}
dom.addEventListerer('event', evFn)
return () => {
// remove
dom.removeEventListerer('event', evFn)
}
}, [])
2-使用正则匹配 transform: translate(x, y) scale(1.2) rotate(90deg)
,风险大;
场景:取出里面的属性数值,第一想法:使用正则,于是就有了以下:
// 正则-放大缩小的数值 scale(1.2)
const scalePattern = /scale\(([1-9]|[0-9]*(\.[0-9]{1,2})?)\)/;
// 正则-旋转角度的正则 rotate(90deg)
const rotatePattern = /rotate\((\-?\d+)deg\)/;
// 正则-图片偏移x, y 的正则 translate(x, y)
const offsetPatt = /translate\(((\-|\+)?\d+(\.\d+)?)px\, ((\-|\+)?\d+(\.\d+)?)px\)/;
暂且不说这些正则是否写错,但是不擅长写正则的我,这种处理方式确实风险很大;
随后,发现了新的思路:getComputedStyle
以及 matrix
矩阵
很明显,下面这种处理方式要好得多:
// matrix(scaleX, skew, rotate, scaleY, translateX, translateY)
// 'matrix( 1, 0, 999, 1, 0, 0 )' ======> [99, 100, 999, 1, 0, 0]
let arr = window
.getComputedStyle(dom)
.transform.replace('matrix(', '')
.replace(')', '')
.split(',')
.map(Number);
const [scale, _, rotate, _1, translateX, translateY] = arr;
3-被 transform
属性搞懵了;
对照 AntD 的 Image 组件,写到一半踩坑:
我的实现:
<div class="img-wrapper">
<img src="xxx" style="transform: translate(x, y) scale(1.2) rotate(90deg)">
</div>
错误的地方,在于我把 transform: translate(x, y) scale(1.2) rotate(90deg)
都作用在 img
标签上了,
问题就来了:
- 当 图片旋转后,进行拖拽,方向错误;
- 当图片放大后,拖拽图片,鼠标拖动距离和图片移动距离不一致
搞的晕头转向的;
参考 AntD 组件的 Image ,它是这么做的:
<div class="img-wrapper" style="transform: translate(x, y)">
<img src="xxx" style="transform: scale(1.2) rotate(90deg)">
</div>
使用 图层概念
- 图片图层只负责 缩放和旋转;
- 外层的 wrapper 负责 拖拽移动,这样就避开了 img 里面的各种问题;
相关资料:
- Get event listeners attached to node using addEventListener
- 原生JS图片拖动、缩放、边界等问题总结 关于图片拖动的边界问题写的很好,非常具有参考价值
- 对应代码:ysx-hidden/DOMStudy
- div内部实现图片旋转、放大、缩小、拖拽
- github-mszhtech/ImageView
- js 实现仿 pc 端微信查看图片功能
4- js 数字的精度问题
// 控制台输入
2.2 * 100
// 期待
// 220
// 结果
220.00000000000003
我的目的是最后只要 2 位小数,那么就应该在最后所有数学计算完成后再 toFixed(2)
今日心情
所见所想,有感而发
忙碌中...
感受到做技术攻关,克服了问题后的成就感;但是如果一直没有头绪的话,也很难受;
今日算法
今日学习:
今日复习:
手撕代码
防抖节流等各种手写,http和网络,浏览器原理,性能优化,Webpack
- query 参数解析成对象
最简单:
// input
// https://www.baidu.com/s?name=tom&age=12
const url1 = 'https://www.baidu.com/s?name=tom&age=12'
const transformQuery = (url) => {
const _url = new URL(url)
return Object.fromEntries(new URLSearchParams(_url.search))
}
transformQuery(url1)
// { name: 'tom', age: '12' }
其他方法:
const url1 = 'https://www.baidu.com/s?name=tom&age=12'
const transformQuery = (url) => {
const search = url.split("?")[1]
let res = {}
search.split("&").forEach(item => {
const [key, name] = item.split("=")
res[key] = name
})
// or
// return search.split("&").reduce((pre, cur) => (pre[cur.split('=')[0]] = cur.split('=')[1], pre), {})
return res
}
transformQuery(url1)
好文推荐
有感好文
- 「2021」我给Vue.js生态贡献代码的这一年 学习作者是如何为 vuejs 贡献代码的。
代码贡献思路:
其实,对于 React 生态链,Vuejs 生态链,各自都有 hook,以及各种 工具链,但是很多工具函数本质都是 js 函数,实际上,互相 转译一下,就可以为 对应对生态链做 建设了。
好比 Java 有微服务,那么新出来的 Go 语言,是不是可以按照 Java 微服务的方式也写一套对应的 Go 微服务,与之特点结合做一些特性改造。
项目/博客推荐
值得学习的项目/作者