移動端字體大小調節器實現

最近在一個微信H5項目中須要用到字體大小調節器,就看了一下QQ中的功能,就作了一個類似的,方法也不止一種,並且都不難。javascript

img1

方法1

html

<div class="wrap">
    <div class="line"></div>
    <ul class="font-adjust">
        <li data-size="14px" class="selected"></li>
        <li data-size="16px"></li>
        <li data-size="18px"></li>
        <li data-size="20px"></li>
        <li data-size="22px"></li>
    </ul>
</div>
<article style="font-size: 14px">
    聖誕已過<br>再加上看過各個大牌出的辣眼睛狗年限定之後<br>我覺得將來的幾個月應該是沒有什麼東西<br>能騙到個人錢了<br>直到...看到了ysl的春季限定...<br>我知道<br>錢包又要完。蛋 。了。
</article>

style

<style type="text/css">
* {
    margin: 0;
    padding: 0;
    border: none;
    box-sizing: border-box;
}
.wrap {
    position: relative;
    padding: 0 50px;
    border: 1px solid #000;
}
.line {
    width: calc(100% - 100px);
    height: 1px;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    background-color: #ccc;
}
.font-adjust {
    display: flex;
    justify-content: space-between;
    align-items: center;
    height: 50px;
}
.font-adjust li {
    position: relative;
    list-style: none;
    width: 1px;
    height: 10px;
    background-color: #ccc;
}
.font-adjust li::after {
    content: '';
    display: block;
    position: absolute;
    width: 20px;
    height: 20px;
    top: 50%;
    left: 50%;
    border-radius: 50%;
    transform: translate(-50%, -50%);
    background-color: transparent;
}
.font-adjust li.selected::after {
    background-color: #fff;
    border: 1px solid #eee;
    box-shadow: 0 1px 1px 0 #999;
}
article {
    text-align: center;
}
</style>

咱們獲得這樣的頁面:css

img2

javascript

最簡單的單擊目標點能夠設置對應字體大小:html

$('.font-adjust li').on('click', function(e) {
    $('article').attr('style', `font-size: ${$(this).attr('data-size')}`); // 設置字體大小
    $('.font-adjust li').removeClass('selected');
    $(this).addClass('selected');
})

在QQ的字體設置中,只要點擊起始點在調節區域,以後在整個窗口左右滑動也能夠達到調節字體的目的,我這裏用的是 touchmove 事件,利用它返回的位置信息,判斷當前距離哪一個點的水平位置最近,就使用哪一個字體大小,代碼以下:java

var fontModel = ['14px', '16px', '18px', '20px', '22px']; // 可供選擇的字體序列
var current = 0; // 當前使用的字體在序列中的位置下標
var fontModelsPos = $('.font-adjust li').map(function (index) { // 得到每一個標記點的位置 x
    return $('.font-adjust li').eq(index)[0].offsetLeft;
})

$('.font-adjust').on('touchmove', function (e) {
    e.preventDefault();
    var min = {
        i: 0,
        dis: Math.abs(fontModelsPos[0] - e.changedTouches[0].clientX)
    };
    for(var i = 1; i < 5; i++){ // 得到最近標記點
        var dis = Math.abs(fontModelsPos[i] - e.changedTouches[0].clientX); // 計算觸控點和各標記點的距離
        if (dis < min.dis) { // 找出最近的那個
            min = { i: i, dis: dis }
        }
    }
    if (min.i != current) { // 字體大小改變
        current = min.i;
        $('.font-adjust li').removeClass('selected');
        $('.font-adjust li').eq(min.i).addClass('selected');
        $('article').attr('style', `font-size: ${fontModel[min.i]}`)
    }
})

效果:web

img3

方法2

emmmmm,後來隱約記得有個元素能夠充當這個來調節器來用,是它,是它,就是它:inputinput 中有一個屬性 type="range" ,使用它能夠更方便的完成上述功能。瀏覽器

html

<div class="wrap">
    <input type="range" min="0" max="4" step="1" value="0" id="adjust_font">
    <!-- 如下模擬橫線和定位點 -->
    <div class="line"></div>
    <ul class="range-simulate">
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
</div>

這裏仍是保留了上面的部分代碼(5個定位點和1條橫線),由於 input 是沒有這些點的,橫線能夠經過更改默認滑軌的樣式成爲一條細線,可是當滑塊在兩端時,橫線的頂點並不在滑塊中央,不介意的話問題也不大。微信

以下的透視圖展現的就是頂點在滑塊正中央:app

img4

style

<style type="text/css">
* {
    margin: 0;
    padding: 0;
    border: none;
    box-sizing: border-box;
}
.wrap {
    position: relative;
    padding: 10px 50px;
    border: 1px solid #000;
}
input[type=range] {
    -webkit-appearance: none;
    width: 100%;
    background-color: transparent;
}
input[type=range]::-webkit-slider-runnable-track { // 滑軌
    height: 20px;
}
input[type=range]::-webkit-slider-thumb { // 滑塊
    -webkit-appearance: none;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background-color: #fff;
    border: 1px solid #eee;
    box-shadow: 0 1px 1px 0 #999;
}
input[type=range]:focus {
    outline: none;
}
.line {
    width: calc(100% - 120px);
    margin: 0 10px;
    height: 1px;
    position: absolute;
    z-index: -1;
    top: 50%;
    transform: translateY(-50%);
    background-color: #ccc;
}
.range-simulate {
    width: calc(100% - 120px);
    margin: 0 10px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    position: absolute;
    z-index: -1;
    top: 50%;
    transform: translateY(-50%);
}
.range-simulate li {
    position: relative;
    list-style: none;
    width: 1px;
    height: 10px;
    background-color: #ccc;
}
article {
    text-align: center;
}
</style>

javascript

這裏的 js 部分就很簡單了,簡直是送分題:ide

var fontModel = ['14px', '16px', '18px', '20px', '22px'];
var article = document.getElementById('article');

document.getElementById('adjust_font').addEventListener('input', function (e) {
    article.setAttribute('style', `font-size: ${fontModel[e.target.value]}`);
}, false);

總結

兩種方法實現起來看起來都挺簡單,可是綜合考慮仍是第二種方法優先,我考慮的方面主要有三點:字體

  • 當各字體的5個標記點不是一條豎線,而是一個圓或者其餘形狀的時候,咱們須要計算圓的中心點,而衆所周知移動端咱們可能會用 rem 或者其餘單位,這時候計算起來比較棘手了;
  • 在 touchmove 事件中處理了不少計算問題,比較消耗資源,有可能會形成用戶體驗不佳;
  • touchmove 事件的兼容性,Safari 暫不支持,有可能會形成困擾。

第三點在我目前的項目中,在微信瀏覽器是不須要考慮的。

該文章首發於https://blog.bingqichen.me/

相關文章
相關標籤/搜索