目前Chrome瀏覽器依然沒有放開12px的限制,但Chrome仍然是使用人數最多的瀏覽器,
在筆者開發某個專案時突發奇想:如果實際需要11px的字體大小怎么辦?這在Chrome中是實作不了的,關于字體,一開始想到的就是rem等非px單位,但是rem只是為了回應式適配,并不能突破這一限制,
em、rem等單位只是為了不同解析度下展示效果提出的換算單位,常見的庫
px2rem也只是利用了js將px轉為rem,包括微信小程式提出的rpx單位也是一樣!
這條路走不通,就只剩下一個方法:改變視覺大小而非實際大小,
理論基礎
css中有一個屬性:transform: scale();
- 值的絕對值>1,就是放大,比如2,就是放大2倍
- 值的絕對值 0<值<1,就是縮小,比如0.5,就是原來的0.5倍;
- 值的正負,負值表示圖形翻轉,
默認情況下,scale(x, y):以x/y軸進行縮放;如果y沒有值,默認y==x;
也可以分開寫:scaleX() scaleY() scaleZ(),分開寫的時候,可以對Z軸進行縮放
第二種寫法:transform: scale3d(x, y, z)該寫法是上面的方法的復合寫法,結果和上面的一樣,
但使用這個屬性要注意一點:scale 縮放的時候是以“縮放元素所在空間的中心點”為基準的,
所以如果用在改變元素視覺大小的場景下,一般還需要利用另一個元素來“恢復位置”:
transform-origin: top left;
語法上說,transform-origin 擁有三個屬性值:
transform-origin: x-axis y-axis z-axis;
默認為:
transform-origin:50% 50% 0;
屬性值可以是百分比、em、px等具體的值,也可以是top、right、bottom、left和center這樣的關鍵詞,作用就是更改一個元素變形的原點,
實際應用
<div class="mmcce__info-r">
<!-- 一些html結構 -->
<div v-show="xxx" class="mmcce-valid-mj-period" :class="{'mmcce-mh': showStr}" @click="handleShowStr"> <!-- click中事件控制展示與否 -->
<div class="mmcce-valid-period-child">{{couponInfo.startTimeFormat}}-{{couponInfo.endTimeFormat}}</div><!-- 父級結構,點擊顯示下面內容 -->
<div class="mmcce-valid-pro" ref="mmcceW" :style="{opacity: showStr ? 1 : 0}">
<!-- 下面內容在后面有講解 -->
<div class="mmcce-text"
v-for="(item, index) in couponInfo.thresholdStr"
:key="index"
:index="index"
:style="{height: mTextH[index] + 'px'}"
>{{item}}</div>
</div>
</div>
</div>
.mmcce-valid-mj-period {
max-height: 15px;
transition: all .2s ease;
&.mmcce-mh {
max-height: 200px;
}
.mmcce-valid-pro {
display: flex;
flex-direction: column;
padding-bottom: 12px;
.mmcce-text {
width: 200%; // !
font-size: 22px;
height: 15px;
line-height: 30px;
color: #737373;
letter-spacing: 0;
transform : scale(.5);
transform-origin: top left;
}
}
}
.mmcce-valid-period-child {
position: relative;
width : 200%;
white-space: nowrap;
font-size : 22px;
color : #979797;
line-height: 30px;
transform : scale(.5);
transform-origin: top left;
//xxx
}

可以明確說明的是,這樣的 hack 需要明確規定縮放元素的height值 !!!
上面代碼中為什么.mmcce-valid-mj-period類中要用max-height ?為什么對展開元素中的文字類.mmcce-text中使用height?
我將類.mmcce-text中的height去掉后,看下效果:

(使用min-height是一樣的效果)
OK,可以看到,占高沒有按我們想的“被縮放”,影響到了下面的元素位置,
本質上是“視覺大小改變了但實際(占位)大小無變化”,
這時候,寬高實際也被縮放了的,這一點通過代碼中width:200%也可以看出來,或者你設定了overflow:hidden;也可以有相應的效果!
這一點需要注意,一般來說,給被縮放元素顯式設定一個大于等于其font-size的height值即可,
縮放帶來的其它問題
可能在很多人使用的場景中是不會考慮到這個問題的:被縮放元素限制高度以后如果元素換行那么會出現文字重疊的現象,

為此,我采用了在mounted生命周期中獲取父元素寬度,然后動態計算是否需要換行以及換行的行數,最后用動態style重新渲染每一條資料的height值,
這里有三點需要注意:
- 這里用的是一種取巧的方法:用
每個文字的視覺font-size值*字串長度,因為筆者遇到的場景不會出現問題所以可以這么用,在不確定場景中更推薦用canvas或dom實際計算每個字符的寬度再做判斷(需要知道文字、字母和數字的寬度是不一樣的); - 需要注意一些特殊機型的展示,比如三星的galaxy fold,這玩意是個折疊屏,它的計算會和一般的螢屏計算的不一致;
- 在vue生命周期中,mounted可以操作dom,但不能獲取實際dom元素;你可以通過
this.$el獲取元素,但要注意:在這個時期被獲取的元素不能用v-if(即:必須存在于虛擬tree中),這也是上面代碼中筆者使用v-show和opacity的原因,
關于第三點,這里有個時機問題,比如剛進入頁面時要展示彈窗,彈窗是一個組件,那你在index.vue中是獲取不到這個組件的,(這個和
v-if還是v-show沒有關系)但是你可以將比如header也拆分出來,然后在header組件的mounted中去呼叫彈窗組件暴露出的方法,
mounted(){
let thresholdStr = this.info.dropDownTextList;
let minW = false;
if(this.$el.querySelector('.mmcce-valid-pro').clientWidth < 140) { // 以iPhone5位準,再小于其中元素寬度的的機型就要做特殊處理了
minW = true
}
let mmcw = this.$el.querySelector('.mmcce-valid-pro').getBoundingClientRect().width;
let mmch = [];
for(let i=0;i<thresholdStr.length;i++) {
// 11是指縮放后文字的font-size值,這是一種取巧的方式
if(11*(thresholdStr[i].length) > mmcw) {
if(minW) {
mmch[i] = Math.floor((11*thresholdStr[i].length) / mmcw) * 15;
}else {
mmch[i] = Math.floor((11*(thresholdStr[i].length) + 40) / mmcw) * 15;
}
}else {
mmch[i] = 15;
}
}
this.mTextH = mmch;
},
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/389218.html
標籤:其他
上一篇:圖的深度優先遍歷
下一篇:每日寫題分享--關于位運算
