ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

JavaScript.info 实战:用元素几何属性把小球精确居中到场地中心

JavaScript.info 实战:用元素几何属性把小球精确居中到场地中心 文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载本篇技术指南围绕 Modern JavaScript Tutorialjavascript.info中Place the ball in the field center这一实战任务展开演示如何不借助 CSS纯用 JavaScript 的元素几何属性clientWidth/clientHeight、offsetWidth/offsetHeight计算坐标把任意尺寸的小球精确放入任意尺寸场地的正中心。读完你可以掌握position:absolute定位坐标系、内容区尺寸读取以及图片未加载时offsetWidth为 0 的经典陷阱与规避方案。任务背景与要求题目原文见 task.md页面上有一个绿色场地#field里面放着一张图片小球#ball。任务是计算场地中心的坐标并用 JavaScript 把小球移动到正中心。题目给出了三条硬性约束元素必须由 JavaScript 移动不能用 CSS完成居中代码必须适配任意小球尺寸如10、20、30像素和任意场地尺寸不能写死给定数值这是一次热身后续章节会遇到更多必须用 JavaScript 处理定位的复杂场景本题先把几何属性基础打牢。仓库中围绕该任务提供了三份可直接运行对照的文件source.view/index.html —— 题目初始状态ball-half/index.html —— 常见错误实现球的左上角居中solution.view/index.html —— 正确实现。前置知识本题用到的三个几何属性要理解解法先要清楚 Element size and scrolling 一章中与本任务直接相关的几何属性。clientWidth/clientHeight元素边框内部区域的大小即内容宽度加上内边距、但不含滚动条。本章原文档明确指出如果没有内边距clientWidth/clientHeight就是边框和滚动条之内的内容区大小。这正是我们求场地可用内部尺寸的抓手。offsetWidth/offsetHeight元素的外部尺寸即包含边框在内的完整宽高。对本题的小球来说它就是球的渲染尺寸。offsetParent与left/top的坐标系offsetParent是浏览器在渲染时用来计算元素坐标的最近祖先满足以下条件之一CSS 定位元素absolute、relative、fixed、sticky、td/th/table、或body。position:absolute元素的left/top正是相对这个祖先来测量的。解题思路坐标从哪里开始算观察初始 HTMLsource.view/index.htmlstyle #field { width: 200px; border: 10px groove black; background-color: #00FF00; position: relative; } #ball { position: absolute; } /style div idfield img srchttps://en.js.cx/clipart/ball.svg idball ... /div关键点有两条小球#ball设置了position:absolute因此它的left/top坐标是相对最近的已定位祖先来测量的场地#field设置了position:relative正好充当了这个定位祖先。于是小球的坐标原点就是场地的内边框左上角(0,0)而不是场地包含边框在内的外缘。如 field.svg 所示场地内部尺寸就是clientWidth/clientHeight中心坐标自然是centerX field.clientWidth / 2 centerY field.clientHeight / 2注意这里必须用clientWidth/clientHeight而不是offsetWidth/offsetHeight因为后者包含 10px 边框会把中心点算偏到边框上。常见错误把球的左上角放进了中心如果直接写下ball.style.left Math.round(field.clientWidth / 2) px; ball.style.top Math.round(field.clientHeight / 2) px;得到的结果并非球心居中而是球的左上角落在了场地中心——小球整体偏到右下。这正是 ball-half/index.html 演示的效果let ball document.getElementById(ball) let field document.getElementById(field) ball.style.left Math.round(field.clientWidth / 2) px ball.style.top Math.round(field.clientHeight / 2) px原因在于left/top定位的是元素的左上角而不是几何中心。坐标系原点是左上角坐标值语义是左上角离原点的偏移这一点很容易被忽略。正确实现整体左移、上移半个球要让球心与场地中心重合只需在上面的坐标上再减去小球自身宽高的一半。完整解法见 solution.mdball.style.left Math.round(field.clientWidth / 2 - ball.offsetWidth / 2) px; ball.style.top Math.round(field.clientHeight / 2 - ball.offsetHeight / 2) px;公式拆解field.clientWidth / 2—— 场地中心横坐标内部内容区不含边框ball.offsetWidth / 2—— 小球宽度的一半用于把左上角基准平移回球心两者相减得到left值top同理。由于尺寸全部来自属性实时读取公式天然满足题目的第二条约束无论球是10、20、30像素场地是 200px 还是 2000px都能正确居中。Math.round用于避免出现0.5px之类的非整数偏移。关键陷阱图片没有尺寸时 offsetWidth 为 0在 solution.md 中特别标注了警告如果img没有显式给出width/height上述代码在首次加载时会算错。img srcball.png idball原因浏览器在图片加载完成前不知道它的宽高会把图片当作0×0处理此时ball.offsetWidth为0ball.offsetHeight也是0于是ball.offsetWidth / 2等于0公式退化成左上角居中与错误实现完全一样。首次加载后浏览器通常会缓存图片刷新时尺寸立刻可用但第一次访问必然踩坑。两种修复方式任选其一方式一给img加width/height属性solution.view/index.html 采用此法img srchttps://en.js.cx/clipart/ball.svg width40 height40 idball方式二用 CSS 声明尺寸#ball { width: 40px; height: 40px; }两种方式都让浏览器在脚本执行前就确定了图片的渲染尺寸offsetWidth/offsetHeight不再是 0公式才能稳定成立。从源码验证完整的正确实现对照 solution.view/index.html可以看到完整可运行的组合HTML 中img带width40 height40脚本位于元素之后直接计算并设置坐标script // ball.offsetWidth0 before image loaded! // to fix: set width ball.style.left Math.round(field.clientWidth / 2 - ball.offsetWidth / 2) px ball.style.top Math.round(field.clientHeight / 2 - ball.offsetHeight / 2) px /script脚本里保留了注释提醒读者这就是那个图片尺寸为 0的坑以及设置宽度这一修复手段。运行这段代码即可看到小球稳稳落在绿色场地正中央。总结这道题浓缩了三个可复用的知识点知识点要点仓库依据定位坐标系position:absolute元素的left/top相对最近定位祖先position:relative的#field的内左上角测量source.view/index.html内容区尺寸场地内部尺寸用clientWidth/clientHeight不含边框、不含滚动条不要用含边框的offsetWidtharticle.md中心对齐公式left field.clientWidth/2 − ball.offsetWidth/2top同理solution.md图片尺寸陷阱img无width/height时offsetWidth为 0需用属性或 CSS 提前声明尺寸solution.md、solution.view/index.html核心公式一句话用clientWidth/clientHeight拿场地内部尺寸除以 2 得中心再各自减去ball.offsetWidth/offsetHeight的一半把左上角基准平移到球心。这个中心 容器内部尺寸/2 − 元素自身尺寸/2的套路是后续所有 JavaScript 动态定位拖拽、动画、弹窗居中的基础。赞分享文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载相关推荐G6 聚焦元素交互focus-element完全指南点击将元素居中到视图中心G6 聚焦元素交互focus element完全指南点击将元素居中到视图中心 导读 本文以 G6 内置的 focus element 交互行为为核心讲数据可视化前端图表库SQLAlchemy Indexable 扩展实战用 index_property 把 JSON / ARRAY / HSTORE 的元素变成列级属性SQLAlchemy Indexable 扩展实战用 index_property 把 JSON / ARRAY / HSTORE 的元素变成列级属性 本数据库后端ORMjavascript.info 日期章节实战用 getSecondsToTomorrow() 精确计算到明天的剩余秒数javascript.info 日期章节实战用 getSecondsToTomorrow 精确计算到明天的剩余秒数 本篇技术指南基于 Modern JavaS文档/教程前端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表