页面使用 scale 缩放实践

最近接到一个任务,需要把页面放大1.5倍显示。这里使用 css 里的 transform: scale(1.5) 来实现。

javascript 复制代码
document.body.setAttribute(
    'style',
    `transform: scale(1.5); transform-origin: left top; width: ${window.innerWidth / 1.5}px; height: ${window.innerHeight / 1.5}px;`
);

缩放后元素大小

width

API
clientWidth 583
offsetWidth 597
scrollWidth 700
window.getComputedStyle($0).width 596.5px
getBoundingClientRect().width 894.75

height

API
clientHeight 226
offsetHeight 240
scrollHeight 431
window.getComputedStyle($0).height 240px
getBoundingClientRect().height 360

通过以上数值比较,我们发现:

clientWidthclientHeightoffsetWidthoffsetHeightscrollWidthscrollHeightwindow.getComputedStyle 获取的值都是缩放前的;

getBoundingClientRect获取的值是缩放后的。

这里我们以 width 为例,我们先把 getBoundingClientRectwidth 换算成缩放前的值

javascript 复制代码
894.75 / 1.5 (缩放倍数) = 596.5

我们发现换算后的值跟 getComputedStyle 获取到的值一致,是缩放前宽度的值;clientWidthoffsetWidth 的值会进行取整。

计算宽高的时候我们优先选择 getBoundingClientRectgetComputedStyle

scroll

我们再来看下 scrollHeight,我们把滚动条滚动到最底部

API
clientHeight 226
offsetHeight 240
scrollHeight 431
scrollTop 205

我们发现

javascript 复制代码
clientHeight + scrollTop = scrollHeight

这里我们可以得出 scrollTopscrollLeftscrollHeightscrollWidth 也是缩放前的值。

因此在计算宽高的时候,我们优先选择 getComputedStyle,可以避免进行换算。

这里我们将其封装成方法,方便使用:

ts 复制代码
/** 获取元素大小 */
function getElementSize(el: Element) {
    const style = window.getComputedStyle(el);
    return {
        width: parseFloat(style.width),
        height: parseFloat(style.height),
    };
}

坐标

getBoundingClientRect

属性
width 894.75
height 360
left 213
top 224.90625
right 1107.75
bottom 584.90625
x 213
y 224.90625

getBoundingClientRect 获取到的宽高和坐标位置都是缩放后的(即实际显示值)。

MouseEvent

属性
clientX 213
clientY 225
pageX 213
pageY 225

MouseEvent 获取到的坐标系值也是缩放后的(即实际显示值)。

因此在和坐标位置有关的值进行计算时,推荐使用 getBoundingClientRect

这里有一点要注意的,我们使用坐标及getBoundingClientRect宽高计算出来的值,由于这些值是缩放后的,最终设置到元素上的时候需要除以放大倍数(这里是1.5倍),因为设置在元素上的值也会被缩放。例如:

javascript 复制代码
element.style.left = `${e.clientX / 1.5}px`;
element.style.width = `${element.getBoundingClientRect().width / 1.5}px`

获取 scale 的值

当我们使用坐标有关的值时避免不了进行换算,因此我们需要获取当前 scale 缩放倍数

ts 复制代码
function toNum(num: number) {
    return Number.isNaN(num) ? 1 : num;
}

function getScale(el: Element) {
    const eleRect: DOMRect = el.getBoundingClientRect();
    const computedStyle = window.getComputedStyle(el);
    const eleOutWidth = parseFloat(computedStyle.width);
    const eleOutHeight = parseFloat(computedStyle.height);

    const scaleX = toNum(Math.round((eleRect.width / eleOutWidth) * 1000) / 1000);
    const scaleY = toNum(Math.round((eleRect.height / eleOutHeight) * 1000) / 1000);

    return {
        scaleX,
        scaleY,
    };
}

这里我们封装了一个方法 getScale,传入当前元素的父元素,即可获取当前缩放倍数。例如:

javascript 复制代码
getScale(document.body)

得到的值为:

json 复制代码
{
    scaleX: 1.5
    scaleY: 1.5
}

我们得到当前水平缩放 1.5 倍,垂直缩放 1.5 倍。

总结

计算宽高的时候,优先选择 getComputedStyle

跟坐标位置有关的,使用 getBoundingClientRect,但是计算出的值需要除以 scale 放大倍数。

相关推荐
aa小小10 小时前
uniApp离线数据不丢失方案
前端
代码小学僧10 小时前
从 0 到 1,记录我的第一个出海 SaaS 独立开发项目
前端·rpc·音视频开发
Aaswk11 小时前
从 HTML/CSS/JS 到 Vue + Axios 的一篇实战笔记
前端·css·vue.js·html
IMPYLH11 小时前
HTML 的 <span> 标签
前端·html
计算机魔术师11 小时前
纽约时报诉案曝光:微软高管私下承认,AI抓取是史上最大劳动盗窃
前端
晓得迷路了11 小时前
栗子前端技术周刊第 147 期 - React Router 8.4、Vite 云服务攻击、pnpm 12.4...
前端·javascript·react.js
SEO_juper11 小时前
2026年用Python检测网站薄内容与重复页:用向量相似度找出“搜索引擎眼中一样“的页面(附完整代码)
开发语言·前端·seo·独立站·谷歌优化
IT_陈寒11 小时前
Vite这坑我踩了,说说静态资源加载那些事儿
前端·人工智能·后端
梦曦i12 小时前
uni-app x 0.7.0重磅升级:插件实例化,原生编译彻底打通
前端·uni-app x
开开心心就好12 小时前
C盘空间不够用?一键扫描清理系统垃圾
前端·javascript·安全·支持向量机·语音识别·etcd·模拟退火算法