一、双指缩放的实现方式
方式一: 根据手势计算scale重新render生成视图
实现逻辑
优点
(1) 清晰度
通过js修改元素样式,缩放过程中一直很清晰。
(2) 兼容性
通过js修改修改元素样式并重新render,不存在兼容性问题。
(3) 报表冻结
可以实现冻结报表在缩小的过程中展示更多内容。
(4) 局部缩放
可以实现整个页面不缩放,只缩放页面局部元素的效果。
缺点
(1) 性能
在双指缩放的过程中频繁执行js代码,持续render,性能很差。
方式二: 根据手势计算scale修改元素scale()样式
实现逻辑
优点
(1) 性能
双指缩放的过程中不需要重新render,只修改DOM元素的scale,性能很好。
(2) 局部缩放
可以实现整个页面不缩放,只缩放页面局部元素的效果。
缺点
(1) 清晰度
放大过程中,在iOS设备浏览器中,清晰度降低。
(2) 报表冻结
难以实现冻结报表在缩小的过程中展示更多内容。
(3) 兼容性
不同系统、不同浏览器对transform:scale的CSS样式解析不同,兼容性不好。
(4) 父容器
在iOS设备浏览器中,被修改transform:scale元素(A)父元素(B)的滚动条以A元素的初始尺寸大小为准进行滚动条分配。如果元素A的scale增加了,则A在B中会滚不到头。除非同比例修改A的width和height,但这样在ios设备浏览器中又可能导致页面空白的bug。此问题未找到较好的解决办法,在android中没有此问题。
方式三: 浏览器默认实现
实现逻辑
通过动态修改"type=viewport"的meta标签的content属性值控制单页应用不同页面是否禁止双指缩放。
优点
(1) 性能
浏览器实现,性能最好
(2) 清晰度
浏览器实现,清晰度很好
(3) 兼容性
浏览器实现,兼容性一般
缺点
(1) 局部缩放
难以实现整个页面不缩放,只缩放页面局部元素的效果。
(2) 报表冻结
难以实现冻结报表在缩小的过程中展示更多内容。
方案对比
方案对比 | 根据手势计算scale重新render生成视图 | 根据手势计算scale修改元素scale()样式 | 浏览器默认实现 |
---|---|---|---|
清晰度 | 好 | iOS差 |
好 |
性能 | 差 |
好 | 好 |
兼容 | 好 | 差 |
差 |
冻结展示 | 可变 | 不可变 |
不可变 |
局部缩放 | 可以 | 可以 | 不可以 |
父容器 | 可变 | iOS不可变 |
可变 |
方案选择
最终方案
(1) iOS设备性能较好,使用“方式一”解决方案。
(2) Android非冻结报表使用“方式二”解决方案。
(3) Android冻结报表使用双指缩放过程“方式二”,双指松开使用“方式一”解决方案。
代码实现
/**
* 双指缩放
* @param evt
*/
onPinch(evt){
evt.stopPropagation();
if(Device.ios()) {
//重新render
const lastScale = this.scale;
const scale = lastScale * evt.scale;
this.setTableZoomScale(scale);
} else {
if(this._isAnyFrozenTable()) {
//缩放时修改CSS,松开时重新render
let cssScale = this._getReportNodeCssScale();
if(evt.scale / cssScale > 0.66 && evt.scale / cssScale < 1.5) {
this._setReportNodeCssScale(evt.scale);
}
} else {
//只修改CSS
const scale = this.cssScale * evt.scale;
this._setBodyTableCssScale(scale);
}
}
}
/**
* 多手指触摸释放事件
*/
onMultipointEnd(){
if(Device.ios()) {
this.scale = this.reportRef.tableManager.getScale();
} else {
if(this._isAnyFrozenTable()) {
//重新render
let cssScale = this._getReportNodeCssScale();
this.scale = cssScale * this.scale;
this.setTableZoomScale(this.scale, ()=> {
this._setReportNodeCssScale(1);
});
} else {
this._saveBodyTableCssScale();
}
}
}