登录
getBoundingClientRect 方法返回元素的大小及其相对于视口的位置,返回的是 DOMRect 对象,此方式获取的元素尺寸和位置信息更方便。
语法:Element.getBoundingClientRect()
let htmlPositionInfo = document.querySelector('.p').getBoundingClientRect()
console.log(JSON.stringify(htmlPositionInfo))
打印以下对象,能清楚的看到某个元素的尺寸和位置信息:
{
"x": 8,
"y": 92,
"width": 1973,
"height": 44,
"top": 92,
"right": 1981,
"bottom": 136,
"left": 8
}
CSSStyleDeclaration 对象是一个 CSS 声明块,CSS 属性键值对的集合,它暴露了样式信息和各种与样式相关的方法和属性。
CSSStyleDeclaration 对象中的 css 规则的键名是驼峰命名的写法。
以下三种方式,拿去到的都是 CSSStyleDeclaration 对象:
Element.style
:只能读取到该 dom 节点的的行内样式声明的属性,可读可写,但写完后,也是写在了行内的样式中。getComputedStyle(Element)
:获取该 dom 节点的所有 css 样式属性计算后生成的 CSSStyleDeclaration,但是一个只读的对象。CSSStyleSheet API
:不常用,比如,document.styleSheets[0].cssRules[0].style 会返回文档中第一个样式表中的第一条 CSS 规则所以一般情况:
需要写时,使用第一种方法(HTMLElement.style
),只有这个才有写的功能。
需要读时:使用上面第二种中方法(getComputedStyle(Element)
)获取,可以读取到该 Dom 的全部的 css 样式值。
css的变量功能,主流浏览器均已经支持。
下面这段代码的功能,能够实现和scss变量类似的功能。
而且,使用js是可以读取和设置css变量的。
/* 页面默认引入的css文件中设置 */
:root {
--boxWidth: 1200px;
}
div {
--backgroundRed: red;
}
@media screen and (max-width: 1400px) {
:root {
--boxWidth: 1000px;
}
}
/* 任意某个css文件中使用 */
div.box {
width: var(--boxWidth, 20px); /* 第二个参数选填,为缺省值 */
background: var(--backgroundRed);
}
css 中:
:root {
--color: red;
}
js 中:
// 【读】
// 首先获取 html 这个 dom 的可读完整 css 属性的 CSSStyleDeclaration
let htmlComputedStyleRead = getComputedStyle(document.querySelector('html'))
// 获取变量值
let varColor = htmlComputedStyleRead.getPropertyValue('--color').trim() // 获取后会有空格(写css时冒号后的空格)
console.log(varColor) // red
// 【写】
// 首先获取 html 这个 dom 的可写完整 css 属性的 CSSStyleDeclaration
let htmlComputedStyleWrite = document.querySelector('html').style
htmlComputedStyleWrite.setProperty('--color', 'rgb(0, 255, 255)') // 设置
let newColor = htmlComputedStyleWrite.getPropertyValue('--color') // 由于本来就是设置在了行内,所以可以直接用它来获取即可
console.log(newColor) // rgb(0, 255, 255)
使用vue或react时,大多都会使用 scope来限制样式的生效范围,保证不影响全局或子组件的样式,但有时偏偏就需要样式穿透,修改子组件的样式。
而使用 css\less\scss 时,样式穿透的写法是不同的:
贝斯尔曲线是使用 js 或 css 制作动画时,很有用的一个工具,但它的使用还是有一定门槛的,看不懂公式和配置。
下面这个网站,可以所见即所得的,拖拽小球配置曲线,然后自动生成贝斯而曲线的配置,复制使用,很有用的工具:https://cubic-bezier.com/
以下是贝塞尔曲线的js实现,把上面网站的参数传入此函数,即可得到一个方法,一个传入进程值就能得到位置的方法
// 贝塞尔曲线实现
export function cubicBezier(p1x, p1y, p2x, p2y) {
const ZERO_LIMIT = 1e-6;
const ax = 3 * p1x - 3 * p2x + 1;
const bx = 3 * p2x - 6 * p1x;
const cx = 3 * p1x;
const ay = 3 * p1y - 3 * p2y + 1;
const by = 3 * p2y - 6 * p1y;
const cy = 3 * p1y;
function sampleCurverDerivativeX(t) {
return (3 * ax * t + 2 * bx) * t + cx;
}
function sampleCurveX(t) {
return ((ax * t + bx) * t + cx) * t;
}
function sampleCurveY(t) {
return ((ay * t + by) * t + cy) * t;
}
function solveCurveX(x) {
var t2 = x;
var derivative;
var x2;
//https://trac.webkit.org/browser/trunk/Source/WebCore/platform/animation
//First try a few iterations of Newton's method -- normally very fast
// http://en.wikipedia.org/wiki/Newton's_method
for (let i = 0; i < 8; i++) {
// f(t) - x = 0
x2 = sampleCurveX(t2) - x;
if (Math.abs(x2) < ZERO_LIMIT) {
return t2;
}
derivative = sampleCurverDerivativeX(t2);
// == 0, failure
if (Math.abs(derivative) < ZERO_LIMIT) {
break;
}
t2 -= x2 / derivative;
}
//Fall back to the bisection method for reliability
//bisection
//http://en.wikipedia.org/wiki/Wifi/bisection_method
var t1 = 1;
var t0 = 0;
t2 = x;
while (t1 > t0) {
x2 = sampleCurveX(t2) - x;
if (Math.abs(x2) < ZERO_LIMIT) {
return t2;
}
if (x2 > 0) {
t1 = t2;
} else {
t0 = t2;
}
t2 = (t1 + t0) / 2;
}
// Failure
return t2;
}
function solve(x) {
return sampleCurveY(solveCurveX(x));
}
return solve;
}
使用实例
// 几种常见动画的方程
export const ease = cubicBezier(0.25, 0.1, 0.25, 1);
export const easeIn = cubicBezier(0.42, 0, 1, 1);
export const easeOut = cubicBezier(0, 0, 0.58, 1);
export const easeInOut = cubicBezier(0.42, 0, 0.58, 1);
/* 滚动条整体部分,其中的属性有width,height,background,border等(就和一个块级元素一样 */
div {
&::-webkit-scrollbar {
width: 4px;
height: 4px;
background: transparent;
/* background: #202535; */
/* box-shadow: inset 0 1px 3px 0 rgba(0,0,0,0.50); */
}
/*定义滚动条*/
&::-webkit-scrollbar-thumb {
height: 4px;
border-radius: 4px;
background: rgba(255,255,255,0.3);
/* box-shadow: inset 0 1px 3px 0 rgba(6,9,16,0.20); */
}
/* 两头的按钮 */
&::-webkit-scrollbar-button {
display: none;
background: transparent;
background-color: transparent;
}
}
html, body, div, span, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
abbr, address, cite, code,
del, dfn, em, img, ins, kbd, q, samp,
small, strong, sub, sup, var,
b, i,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, figcaption, figure,
footer, header, hgroup, menu, nav, section, summary,
time, mark, audio, video {
margin:0;
padding:0;
border:0;
outline:0;
font-size:100%;
vertical-align:baseline;
background:transparent;
}
html, body, * {
line-height: 1.2em;
margin: 0;
padding: 0;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
outline: none;
}
article,aside,canvas,details,figcaption,figure,footer,header,hgroup,menu,nav,section,summary {
display:block;
}
ul, li {
list-style:none;
}
blockquote, q {
quotes:none;
}
blockquote:before, blockquote:after,q:before, q:after {
content:'';
content:none;
}
a {
margin:0;
padding:0;
border:0;
font-size:100%;
vertical-align:baseline;
background:transparent;
cursor: pointer;
text-decoration: none;
color: inherit;
}
a:hover {
color: inherit;
}
ins {
background-color:#ff9;
color:#000;
text-decoration:none;
}
mark {
background-color:#ff9;
color:#000;
font-style:italic;
font-weight:bold;
}
del {
text-decoration: line-through;
}
abbr[title], dfn[title] {
border-bottom:1px dotted #000;
cursor:help;
}
table {
border-collapse:collapse;
border-spacing:0;
}
hr {
display:block;
height:1px;
border:0;
border-top:1px solid #cccccc;
margin:0;
padding:0;
}
input, select {
vertical-align:middle;
}
button {
outline: none;
border: 0;
background-color: none;
background: none;
cursor: pointer;
}