<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【CSS】1809- 現(xiàn)代 CSS 解決方案:數(shù)學(xué)函數(shù) Round

          共 11063字,需瀏覽 23分鐘

           ·

          2023-09-25 16:16

          在 CSS 中,存在許多數(shù)學(xué)函數(shù),這些函數(shù)能夠通過簡單的計(jì)算操作來生成某些屬性值,現(xiàn)代 CSS 解決方案:CSS 數(shù)學(xué)函數(shù)[1]一文中,我們詳細(xì)介紹了:

          • calc():用于計(jì)算任意長度、百分比或數(shù)值型數(shù)據(jù),并將其作為 CSS 屬性值。
          • min() 和 max():用于比較一組數(shù)值中的最大值或最小值,也可以與任意長度、百分比或數(shù)值型數(shù)據(jù)一同使用。
          • clamp():用于將屬性值限制在一個(gè)范圍內(nèi),支持三個(gè)參數(shù):最小值、推薦值和最大值。

          現(xiàn)代 CSS 解決方案:CSS 原生支持的三角函數(shù)[2] 一文中,給大家介紹了從 Chrome 111 開始也逐漸開始原生支持的三角函數(shù):

          • sin()
          • cos()
          • tan()

          而本文,我們將介紹另外一個(gè)非常有意思的數(shù)學(xué)函數(shù) - round()。

          何為 round()?

          簡單來說,round() CSS 函數(shù)的作用就是根據(jù)選定的舍入策略返回舍入數(shù)。

          舉個(gè)例子,在 JavaScript 中,我們可以使用 Math.round() 返回一個(gè)數(shù)字四舍五入后最接近的整數(shù)。

          譬如:

          x = Math.round(20.49); //20
          x = Math.round(20.5); //21
          x = Math.round(-20.5); //-20
          x = Math.round(-20.51); //-21

          現(xiàn)在,CSS 借助 round() 函數(shù)也有了相同的能力:

          line-heightround(2.2, 1); /* 2 */
          line-heightround(14.82, 1); /* 15 */
          line-heightround(5.5, 1); /* 6 */

          也就是說,round(2.2, 1) 中的 2.2 四舍五入后,最后的計(jì)算值是 2。

          round() 完整語法

          round() 的完整語法規(guī)則還是比較復(fù)雜的。完整的介紹可以看 MDN - round()[3]

          使用它,可以完美實(shí)現(xiàn)類似于 JavaScript 中的如下幾個(gè)方法:

          1. Math.ceil()[4]
          2. Math.floor()[5]
          3. Math.round()[6]
          4. Math.trunc()[7]

          它的完整語法規(guī)則:

          <round()> = round( <rounding-strategy>?, <valueToRound> , <roundingInterval> )

          可以看到,它最多可以接收 3 個(gè)參數(shù),并且第一個(gè)參數(shù)是可選參數(shù):

          • <rounding-strategy>:可選參數(shù),表示舍入策略。這可能是以下值之一:
            • up: 相當(dāng)于 JavaScript Math.ceil() 方法,將 valueToRound 向上舍入到 roundingInterval 最接近的整數(shù)倍。這相當(dāng)于 JavaScript Math.ceil() 方法。
            • down:將 valueToRound 向下舍入為 roundingInterval 最接近的整數(shù)倍。這相當(dāng)于 JavaScript Math.floor() 方法。
            • nearest:將 valueToRound 舍入為 roundingInterval 的最接近的整數(shù)倍,該倍數(shù)可以高于或低于該值。如果 valueToRound 是上方和下方舍入目標(biāo)之間的一半,則會(huì)向上舍入。相當(dāng)于 JavaScript Math.round()。
            • to-zero:將 valueToRound 舍入為 roundingInterval 接近/接近零的最接近整數(shù)倍。這相當(dāng)于 JavaScript Math.trunc() 方法。
          • <valueToRound>:需要被四舍五入的值。必須是 <number><dimension><percentage>,或者解析為這些值之一的數(shù)學(xué)表達(dá)式。
          • <roundingInterval>:舍入的間隔規(guī)則。這是一個(gè) <number><dimension><percentage>,或者解析為這些值之一的數(shù)學(xué)表達(dá)式。

          基于此,舉幾個(gè)例子:

          <div class="box-1"></div>
          <div class="box-2"></div>
          <div class="box-3"></div>
          <div class="box-4"></div>
          <div class="box-5"></div>
          :root {
            --rounding-interval25px;
          }
          div {
            width100px;
            backgroundrgba(2551000, .8);
          }
          div.box-1 {
            heightround(nearest, 110px, var(--rounding-interval)); /* 最終計(jì)算值:100px */
          }
          div.box-2 {
            heightround(up, 110px, var(--rounding-interval)); /* 最終計(jì)算值:125px */
          }
          div.box-3 {
            heightround(down, 120px, var(--rounding-interval)); /* 最終計(jì)算值:100px */
          }
          div.box-4 {
            heightround(to-zero, 120px, var(--rounding-interval)); /* 最終計(jì)算值:100px */
          }
          div.box-5 {
            heightround(120px, var(--rounding-interval)); /* 最終計(jì)算值:125px */
          }

          結(jié)果如下:

          圖中背景一個(gè)格子的大小是 25px

          完整的 DEMO 可以看這里 CodePen Demo - CSS Math Function Round() Demo[8]

          round 能解決什么問題?

          OK,鋪墊了那么久,我們下面進(jìn)入實(shí)戰(zhàn)環(huán)節(jié)。

          那么,round() 函數(shù)在 CSS 中有什么具體的作用嗎?能應(yīng)用到什么地方?

          解決基于 transform 的模糊問題

          在之前的 疑難雜癥:運(yùn)用 transform 導(dǎo)致文本模糊的現(xiàn)象探究[9] 這篇文章中,我們介紹了一種基于transform 的模糊問題。

          我們來回顧一下問題現(xiàn)象:

          在我們的頁面中,經(jīng)常會(huì)出現(xiàn)這樣的問題,一塊區(qū)域內(nèi)的文本或者邊框,在展示的時(shí)候,變得特別的模糊,如下(數(shù)據(jù)經(jīng)過脫敏處理):

          正常而言,應(yīng)該是這樣的:

          emmm,可能大圖不是很明顯,我們?nèi)∫患?xì)節(jié)對(duì)比,就非常直觀了:

          那么?什么時(shí)候會(huì)觸發(fā)這種問題呢?在 Google 上,其實(shí)我們能搜到非常多類似的案例,總結(jié)而言:

          1. 當(dāng)文本元素的某個(gè)祖先容器存在 transform: translate() 或者 transform: scale()transform 操作時(shí),容易出現(xiàn)這種問題

          當(dāng)然,這只是必要條件,不是充分條件。繼續(xù)深入探究,會(huì)發(fā)現(xiàn),必須還得同時(shí)滿足一些其它條件:

          1. 元素作用了 transform: translate() 或者 transform: scale() 后的計(jì)算值產(chǎn)生了非整數(shù)

          譬如,上述案例觸發(fā)的 CSS 代碼如下:

          .container {
              position: absolute;
              width1104px
              height475px;
              top50%;
              transformtranslateY(-50%);
              // ...
          }

          由于元素的高度為 475px,translateY(-50%) 等于 237.5px,非整數(shù),才導(dǎo)致了內(nèi)部的字體模糊。

          但是,需要注意的是,并非所有產(chǎn)生的非整數(shù)都會(huì)導(dǎo)致了內(nèi)部的字體模糊。

          這里有個(gè)簡單的示意:

          還是上述的例子,當(dāng)高度從 477px 一直調(diào)整到 469px 的過程中,只有 477px475px 導(dǎo)致了模糊,而 473, 471, 469 則沒有。所以,這也只是引發(fā)模糊的一個(gè)必要條件。

          1. 文本內(nèi)容是否模糊還與屏幕有關(guān),高清屏(dpr > 2)下不容易觸發(fā),更多發(fā)生在普通屏幕下(dpr = 1)

          在我實(shí)測的過程中還發(fā)現(xiàn),這個(gè)現(xiàn)象基本只會(huì)發(fā)生在 dpr 為 1 的普通屏幕下。

          類似于 MAC 的高清屏幕則不太會(huì)觸發(fā)這個(gè)問題。

          dpr = 物理像素 / 設(shè)備獨(dú)立像素,表示設(shè)備像素比。這個(gè)與我們通常說的視網(wǎng)膜屏(多倍屏,Retina屏)有關(guān)。設(shè)備像素比描述的是未縮放狀態(tài)下,物理像素和設(shè)備獨(dú)立像素的初始比例關(guān)系。

          1. 并非所有瀏覽器都是這個(gè)表現(xiàn),基本發(fā)生在 chromium 內(nèi)核。

          那么,為何會(huì)發(fā)生這種現(xiàn)象?針對(duì)這個(gè)問題,沒有找到特別官方的回答,普遍的認(rèn)為是因?yàn)椋?/p>

          由于瀏覽器將圖層拆分到 GPU 以進(jìn)行 3D 轉(zhuǎn)換,而非整數(shù)的像素偏移,使得 Chrome 在字體渲染的時(shí)候,不是那么的精確。

          關(guān)于這個(gè)問題,感興趣的可以再看看這兩個(gè)討論:

          • Chromium Bugs -- Issue 521364: Transformed text at fractional offsets is very blurry.[10]
          • Serious bug: Slick Slider turns off subpixel font rendering on the entire site in Chrome #2275[11]

          使用 round() 函數(shù)解決模糊問題

          在之前,上面的這個(gè)基于 transform 的問題基本是無解的,想要不模糊,就需要替換掉 transfrom 方法。

          而在有了 round() 后,我們可以通過 round() 函數(shù),保證作用了 transform: translate() 或者 transform: scale() 后的計(jì)算值一定是正整數(shù),從而避免模糊問題。

          譬如,原本的 CSS 如下:

          .container {
              width50vw;
              height50vh;
              transformtranslate(-50%, -50%);
          }

          此時(shí),transform: translate() 的實(shí)際最終計(jì)算值是會(huì)出現(xiàn)小數(shù)的。因此,我們可以使用 round() 函數(shù)進(jìn)行取整:

          .container {
              width50vw;
              height50vh;
              transformtranslate(round(-50%1px), round(-50%1px));
          }

          我們可以使用如下 JavaScript 代碼,打印出 transform 實(shí)時(shí)的計(jì)算值。

          window.addEventListener("resize", () => {
              const transform = getComputedStyle(document.querySelectorAll("div")[0]).transform;
              console.log("transform:", transform);
          });

          如果使用 transform: translate(-50%, -50%) resize 整個(gè)頁面,可以看到如下打印值:

          可以看到,此時(shí),transform: matrix(1, 0, 0, 1, -50.5, -106.75) 的中的后兩位,其實(shí)就是 transform: translate(-50.5px, 106.75px),是存在小數(shù)值的。

          而使用了 transform: translate(round(-50%, 1px), round(-50%, 1px)) 后,將不會(huì)再出現(xiàn)小數(shù)值:

          完整的代碼,你可以戳這里試一試:CodePen Demo -- round() Demo[12]

          借由 round() 函數(shù),我們成功的解決了一直以來,Chrome 中非常棘手的一個(gè)模糊問題!

          使用 round() 模擬步驟緩動(dòng)動(dòng)畫

          round() 還有一個(gè)有趣用法。我們可以使用 round() 實(shí)現(xiàn)類似于 CSS Animation 中的 steps() 步驟動(dòng)畫的效果。

          我們來看這么一個(gè) DEMO:

          <div></div>
          @property --angle {
            syntax: '<angle>';
            inheritsfalse;
            initial-value: 0deg;
          }

          div {
              width200px;
              height200px;
              border-radius50%;
              backgroundconic-gradient(#fc0, #fc0 15deg, transparent 15deg, transparent 30deg);
              transformrotate(var(--angle));
              animation: propertyRotate 2s infinite linear;
          }

          @keyframes propertyRotate {
              100% {
                  --angle360deg;
              }
          }

          這里,我們實(shí)現(xiàn)了這么一個(gè)動(dòng)畫效果:

          我們可以利用 round(),把一個(gè)連貫動(dòng)畫,拆解成步驟動(dòng)畫:

          div {
             // ...
             // transformrotate(var(--angle));
             transformrotate(round(var(--angle), 30deg));
          }

          上面,我們使用 transform: rotate(round(var(--angle), 30deg)) 替換了 transform: rotate(var(--angle))。

          round(var(--angle), 30deg) 保證了其取值只能是 30deg 的倍數(shù)或者 0deg。因此,我們可以得到和使用 stpes() 步驟動(dòng)畫一樣的效果:

          上面使用了 round() 的動(dòng)畫,和如下的動(dòng)畫效果是一致的:

          div {
          transform: rotate(round(var(--angle), 30deg));
          }
          // 等同于
          div {
          transform: rotate(var(--angle));
          animation: propertyRotate 2s infinite steps(12);
          }

          因此,使用 round(),我們也可以輕松的實(shí)現(xiàn)類似如下的 Loading 動(dòng)畫效果:

          完整的代碼,你可以戳這里進(jìn)行了解:CodePen Demo -- CSS Math Function Round() Animation Demo[13]

          最后

          好了,本文到此結(jié)束,希望本文對(duì)你有所幫助 :)

          更多精彩 CSS 技術(shù)文章匯總在我的 Github -- iCSS[14] ,持續(xù)更新,歡迎點(diǎn)個(gè) star 訂閱收藏。

          如果還有什么疑問或者建議,可以多多交流,原創(chuàng)文章,文筆有限,才疏學(xué)淺,文中若有不正之處,萬望告知。

          參考資料

          [1]

          現(xiàn)代 CSS 解決方案:CSS 數(shù)學(xué)函數(shù): https://github.com/chokcoco/iCSS/issues/177

          [2]

          現(xiàn)代 CSS 解決方案:CSS 原生支持的三角函數(shù): https://github.com/chokcoco/iCSS/issues/233

          [3]

          MDN - round(): https://developer.mozilla.org/en-US/docs/Web/CSS/round

          [4]

          Math.ceil(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/ceil

          [5]

          Math.floor(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor

          [6]

          Math.round(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round

          [7]

          Math.trunc(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc

          [8]

          CodePen Demo - CSS Math Function Round() Demo: https://codepen.io/Chokcoco/pen/RwERZZp

          [9]

          疑難雜癥:運(yùn)用 transform 導(dǎo)致文本模糊的現(xiàn)象探究: https://github.com/chokcoco/iCSS/issues/160

          [10]

          Chromium Bugs -- Issue 521364: Transformed text at fractional offsets is very blurry.: https://bugs.chromium.org/p/chromium/issues/detail?id=521364

          [11]

          Serious bug: Slick Slider turns off subpixel font rendering on the entire site in Chrome #2275: https://github.com/kenwheeler/slick/issues/2275

          [12]

          CodePen Demo -- round() Demo: https://codepen.io/Chokcoco/pen/poqbdZd?editors=0110

          [13]

          CodePen Demo -- CSS Math Function Round() Animation Demo: https://codepen.io/Chokcoco/pen/gOZMxzX?editors=1100

          [14]

          Github -- iCSS: https://github.com/chokcoco/iCSS


          往期回顧

          #

          如何使用 TypeScript 開發(fā) React 函數(shù)式組件?

          #

          11 個(gè)需要避免的 React 錯(cuò)誤用法

          #

          6 個(gè) Vue3 開發(fā)必備的 VSCode 插件

          #

          3 款非常實(shí)用的 Node.js 版本管理工具

          #

          6 個(gè)你必須明白 Vue3 的 ref 和 reactive 問題

          #

          6 個(gè)意想不到的 JavaScript 問題

          #

          試著換個(gè)角度理解低代碼平臺(tái)設(shè)計(jì)的本質(zhì)

          回復(fù)“加群”,一起學(xué)習(xí)進(jìn)步

          瀏覽 155
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  肏屄视频看 | 免费三级网 | jzzjzz日本丰满成熟少妇 | 精品秘 无码一区二区三区老师 | 曰批免费视频 |