国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

如何用 js 獲取虛擬鍵盤高度?(適用所有平臺(tái))

li21 / 1704人閱讀

摘要:前言這是一個(gè)存在很久的歷史問題了,對(duì)于這樣一個(gè)具有普遍性的問題瀏覽器偏偏沒有給出解決方案,沒有方案還聊個(gè)什么別急,別急,接下來我們一起來扒一扒關(guān)于軟鍵盤高度和的問題我們先來看一個(gè)短片認(rèn)識(shí)一下這個(gè)問題問題描述當(dāng)操作者進(jìn)行輸入操作的時(shí)候,彈起的

前言

這是一個(gè)存在很久的歷史問題了,對(duì)于這樣一個(gè)具有普遍性的問題瀏覽器偏偏沒有給出解決方案,what?沒有方案還聊個(gè)什么?

別急,別急,接下來我們一起來扒一扒關(guān)于軟鍵盤高度和 input 的問題

我們先來看一個(gè)短片認(rèn)識(shí)一下這個(gè)問題

問題描述:當(dāng)操作者進(jìn)行輸入操作的時(shí)候,彈起的軟鍵盤把原本的輸入框遮擋了,導(dǎo)致操作者看不到操作結(jié)果

以往的解決方案

以往的解決方案:

修改網(wǎng)站的頁面布局,比如本例中 twitter 盡量把 input 放置在中部以上的位置,從布局上盡量避免此類問題

在一些指定設(shè)備和瀏覽器中異步獲取 window.innerHeight 進(jìn)行前后對(duì)比而得出鍵盤高度

再來看一下另一種常見輸入框的頁面布局:

在這個(gè)場景里,輸入框定位在頁面的最底部,當(dāng)軟鍵盤彈起時(shí)整個(gè)視圖窗口頁面向上卷動(dòng),到達(dá)最底部時(shí)停止。恰巧當(dāng)我們用 h5 來模擬這個(gè)效果的時(shí)候剛好勉強(qiáng)做到。

這是因?yàn)楫?dāng)你首次 fouse 到輸入框的時(shí)候軟鍵盤彈出,瀏覽器會(huì)使頁面會(huì)向上滾動(dòng),以確保 input 是可見的,該特性和 document.body.scrollIntoViewIfNeeded 方法是一致的,但是當(dāng)你 body 的可滾動(dòng)高度超過窗口高度時(shí)還會(huì)產(chǎn)生另一個(gè)問題:固定元素將隨頁面滾動(dòng) 如下圖

因此瀏覽器關(guān)心的只是 input 是否被覆蓋?實(shí)際上是 input 中的光標(biāo)位置!那么這就解釋了為什么輸入框在底部的時(shí)候剛好勉強(qiáng)完成了,因?yàn)?input 在頁面的底部時(shí),軟鍵盤彈出勢(shì)必會(huì)遮擋住 input,因而瀏覽器會(huì)向上滾動(dòng)至輸入框可見的位置。

但是如下圖的效果這樣就無法做到了,因?yàn)樵谳斎肟虻南旅孢€有一行工具欄,也就是說輸入框并非在最底部的位置,那么瀏覽器在滾動(dòng)到可視位置時(shí)只會(huì)確保到 input 可見,而對(duì)于工具欄是否可見則并不在瀏覽器的考慮范圍內(nèi)。

IOING 的解決方案分析

綜合來看上面兩種布局方案的問題,都不能完美解決輸入被鍵盤遮擋和底部 footer 不能被頂起的問題,那是不是就沒得法子了?

當(dāng)然號(hào)稱可以讓 HTML5 表現(xiàn)更接近 Native 的 IOING 引擎一定是有解決方案的

我們先來看一段 input 在 IOING 中的表現(xiàn)

我們可以看到在輸入過程中頁面通過滾動(dòng)來始終保持光標(biāo)位于可視區(qū)域的中心位置,因此在這里我們需要提一個(gè)知識(shí)點(diǎn):獲取輸入光標(biāo)的實(shí)時(shí)位置,當(dāng)然這也是一個(gè)曲折的過程,在這里我就不擴(kuò)算話題了,繼續(xù)來講原話題

前面說了三個(gè)主要的傳統(tǒng)解決方案:

第一個(gè)是通過把 input 布局盡量放在頁面頂部,顯然這個(gè)不是我們想要的,否決掉

把 input 放在最底部,用來完成 footer 固定的效果,但是要局限頁面高度不超過窗口高度,我們可以通過自制滾動(dòng)控件來解除這個(gè)限制,那現(xiàn)在需要解決的技術(shù)點(diǎn)就變?yōu)閷?shí)現(xiàn)一個(gè)模擬滾動(dòng)控件

通過比對(duì)軟鍵盤彈出前后的 window.innerHeight 的高度差來得到鍵盤高度,從而根據(jù)這個(gè)高度來實(shí)現(xiàn)底部定位和輸入劇中,但是該方法局限于不同設(shè)備平臺(tái)的支持

綜上所述我們總結(jié)一下我們要解決的思路和步驟

先來看一下下面的圖片

當(dāng)鍵盤彈出時(shí),鍵盤高度 = 不可見窗口高度
這個(gè)等式是有條件的,只有當(dāng) input 在對(duì)底部時(shí)該等式才成立 (這是上面講過的 scrollIntoViewIfNeeded 的原因)

思考:如果我們能讓該等式成立,且能夠獲取不可見位置高度,是否就能得出鍵盤高度了呢

我們整理好思路一步一步來實(shí)現(xiàn)

1.需要將內(nèi)容放置在虛擬滾動(dòng)中,在 IOING 像下面這樣就可以創(chuàng)建一個(gè)虛擬滾動(dòng)區(qū)域了



    頁面內(nèi)容

傳統(tǒng)頁面可以使用 WebKit 私有屬性“-webkit-overflow-scrolling: touch” 來允許獨(dú)立的滾動(dòng)區(qū)域和觸摸回彈,或者使用 iScroll.js 等第三方庫來完成,但是需要注意對(duì) iScroll 使用不當(dāng)可能會(huì)造成性能問題

2.獲取光標(biāo)位于屏幕中的位置

3.當(dāng)光標(biāo) fouce 時(shí),鍵盤彈起,若 input 被遮擋頁面會(huì)進(jìn)行滾動(dòng),但滾動(dòng)量不確定,因此我們可以強(qiáng)制滾動(dòng)到底端,即鍵盤完全彈出后主動(dòng)使窗口向上滾動(dòng)窗口高度的距離,而實(shí)際上窗口只能向上滾動(dòng)到最底部位置后就不能再向上滾動(dòng)了,此時(shí)獲取頁面的 top.scrollY 即為實(shí)際鍵盤高度

得出公式:

可視區(qū)域的中心位置 = 鍵盤高度 + (窗口高 - 鍵盤高度)/2
應(yīng)滾動(dòng)距離 = 可視區(qū)域的中心位置 - 光標(biāo)offsetTop - (光標(biāo)被遮擋 ?鍵盤高度 :0)

當(dāng)然實(shí)際操作需要更多的細(xì)節(jié),po 出 IOING 中該部分邏輯實(shí)現(xiàn)的源代碼:

// IOING 中部分源代碼
// dom 為 input 元素
// scroll 為滾動(dòng)容器的 Scroll 對(duì)象

function scrollTo (y, _y, t, s, r) {
    r = r == undefined ? 1 : r
    y = y == undefined ? top.scrollY : y
    if ( r == 1 ? y > _y : y < _y) return
    s = s == undefined ? Math.abs((_y - y) / t * 17.6) : s
    rAF(function () {
        top.scrollTo(0, y += r*s)
        scrollTo(y, _y, t, s, r)
    })
}

function visibility () {
    if ( this.moving || this.wheeling ) {
        var top = dom.offset().top
        var height = dom.offsetHeight
        var viewTop = keyboardHeight + scrollOffsetTop
        var viewBottom = factWindowHeight - scrollOffsetBottom

        if ( top + height <= viewTop || top >= viewBottom ) {
            dom.blur()
        }
    }
}

function refreshCursor () {
    rAF(function () {
        dom.getSelectionRangeInsert("")
    })
}

function getScroll () {
    var scroller = reactScroller || dom.closest("scroll")

    scroll = scroller ? scroller.scrollEvent : null

    if ( type == 1 ) {
        minScrollY = scroll.minScrollY
    }
}

function getViewOffset () {
    // android : (top.scrollY == 0 ? keyboardHeight : 0)
    viewOffset = viewCenter - rangeOffset.top - (top.scrollY == 0 ? keyboardHeight : 0) + (that.module.config.sandbox ? keyboardHeight : 0)
    
    return viewOffset
}

function keyboardUp (e) {
    getScroll(1)

    if ( !scroll ) return

    // refresh cursor {{

        if ( device.os.ios && device.os.iosVersion < 12 ) {
            scroll.on("scroll scrollend", refreshCursor)
        }

    // }}
    
    if ( normal ) return

    function upend (e) {

        window.keyboard.height = keyboardHeight = top.scrollY || factWindowHeight - top.innerHeight

        // change minScrollY

        scroll.minScrollY = minScrollY + keyboardHeight
        scroll.options.minScrollY = scroll.minScrollY

        // 光標(biāo)位置
        
        rangeOffset = dom.getSelectionRangeOffset()

        // 可見視圖的中心

        viewWrapper = factWindowHeight - keyboardHeight - scrollOffsetTop - scrollOffsetBottom
        viewCenter = keyboardHeight + viewWrapper / 2

        scroll.scrollBy(0, getViewOffset(), 600, null, false)

        // 滾動(dòng)到不可見區(qū)域時(shí) blur
        
        scroll.on("scroll", visibility)

        window.trigger("keyboardup", { 
            height : keyboardHeight 
        })

        if ( reactResize ) {
            scrollTo(null, 0, 300, null, -1)
        }
    }

    setTimeout(function () {

        top.one("scrollend", upend)

        // no scroll
        
        setTimeout(function () {
            if ( keyboardHeight == 0 ) upend() 
        }, 300)

        // ``` old
        
        var offset = 0

        if ( device.os.mobileSafari && device.os.iosVersion < 12 ) {
            offset = 24 * viewportScale
        }

        // scroll to bottom

        scrollTo(null, viewportHeight - offset, 300, null, 1)

    }, 300)
}

function keyboardDown () {
    getScroll()

    if ( !scroll ) return

    // ``` old : refresh cursor {{

        if ( device.os.ios && device.os.iosVersion < 11 ) {
            scroll.off("scroll scrollend", refreshCursor)
        }

    // }}

    if ( normal ) return
    if ( keyboardHeight == 0 ) return false

    top.scrollTo(0, 0)
    scroll.wrapper.scrollTop = 0
    
    // change minScrollY

    scroll.minScrollY = minScrollY
    scroll.options.minScrollY = minScrollY
    scroll.off("scroll", visibility)
    scroll._refresh()

    window.keyboard.height = keyboardHeight = 0
}

function selectionRange (e) {
    getScroll()

    if ( !scroll ) return

    // 非箭頭按鍵取消
    
    if ( e.type == "keyup" && ![8, 13, 37, 38, 39, 40].consistOf(e.keyCode) ) return

    // 重置光標(biāo)位置

    if ( reactOffset ) {
        rangeOffset = dom.getSelectionRangeOffset()
    } else if ( reactPosition ) {
        rangeOffset = dom.getSelectionRangePosition()
    }

    if ( reactOrigin && rangeOffset ) {
        rangeOffset.each(function (i, v) {
            scope.setValueOfHref(reactOrigin + "." + i, v)
        })
    }

    if ( normal ) return

    // 光標(biāo)居中

    if ( e.type == "input" && e.timeStamp - timeStamp < 2000 ) return
    if ( !scroll || !viewCenter ) return
    if ( !reactOffset ) {
        rangeOffset = dom.getSelectionRangeOffset()
    }

    timeStamp = e.timeStamp

    scroll.scrollBy(0, getViewOffset(), 400, null, false)
}

dom.on("click", checkChange)
dom.on("focus", keyboardUp)
dom.on("blur", keyboardDown)
dom.on("focus keyup input paste mouseup", selectionRange)
})

其它的小細(xì)節(jié)和注意事項(xiàng):

safari 會(huì)受到瀏覽器底部導(dǎo)航欄的影響,會(huì)產(chǎn)生20多像素誤差,需要針對(duì)考慮

safari 中的 input 光標(biāo)在執(zhí)行 transform 3d變換的時(shí)候會(huì)出現(xiàn)光標(biāo)停滯的現(xiàn)象,需要執(zhí)行光標(biāo)刷新操作

當(dāng) input 被操作者主動(dòng)滑出可視區(qū)域外時(shí)應(yīng)處罰鍵盤收起操作,否則在輸入時(shí) scrollIntoViewIfNeeded 效應(yīng)將導(dǎo)致窗口滾動(dòng)出現(xiàn)空白的問題

最后總結(jié):

獲取鍵盤高度只是我們的表象,真正解決 html5 帶來的各種問題才是我們的研究課題,也只有掃清這些布局殺手 h5 才能在追趕 Native 的道路上更近一步!

結(jié)尾

最后的最后我來 po 一下在 IOING 中完成這一步我們需要做什么?

就是這么簡單,IOING 中 input 默認(rèn)就能擁有自動(dòng)居中特性

如果你要取消這個(gè)特性,就像下面這樣寫

當(dāng)然也可以設(shè)置居中相對(duì)底部/相對(duì)于頂部的偏移位置


在輸入過程中能夠?qū)崟r(shí)輸出光標(biāo)位置,且將位置信息賦值給數(shù)據(jù)源對(duì)象


當(dāng)前光標(biāo)位置:left: {test.range.left}, top: {test.range.top}

用js 獲取鍵盤高度的方法

//鍵盤彈起時(shí)為鍵盤高度,未彈起時(shí)為0
console.log(window.keyboard.height)
// 通過鍵盤彈起事件獲取
window.on("keyboardup", function (e) {
    console.log(e.height)
})
// 鍵盤收起事件
window.on("keyboarddown", function (e) {
    console.log(e.height) // 0
})

詳細(xì)文檔傳送門:http://ioing.com/#docs-dom-input
GitHub 傳送門:https://github.com/ioing/IOING

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/112430.html

相關(guān)文章

  • 何用 js 獲取虛擬鍵盤高度?(適用所有平臺(tái)

    摘要:前言這是一個(gè)存在很久的歷史問題了,對(duì)于這樣一個(gè)具有普遍性的問題瀏覽器偏偏沒有給出解決方案,沒有方案還聊個(gè)什么別急,別急,接下來我們一起來扒一扒關(guān)于軟鍵盤高度和的問題我們先來看一個(gè)短片認(rèn)識(shí)一下這個(gè)問題問題描述當(dāng)操作者進(jìn)行輸入操作的時(shí)候,彈起的 前言 這是一個(gè)存在很久的歷史問題了,對(duì)于這樣一個(gè)具有普遍性的問題瀏覽器偏偏沒有給出解決方案,what?沒有方案還聊個(gè)什么? 別急,別急,接下來我們...

    terro 評(píng)論0 收藏0
  • 何用 js 獲取虛擬鍵盤高度?(適用所有平臺(tái)

    摘要:前言這是一個(gè)存在很久的歷史問題了,對(duì)于這樣一個(gè)具有普遍性的問題瀏覽器偏偏沒有給出解決方案,沒有方案還聊個(gè)什么別急,別急,接下來我們一起來扒一扒關(guān)于軟鍵盤高度和的問題我們先來看一個(gè)短片認(rèn)識(shí)一下這個(gè)問題問題描述當(dāng)操作者進(jìn)行輸入操作的時(shí)候,彈起的 前言 這是一個(gè)存在很久的歷史問題了,對(duì)于這樣一個(gè)具有普遍性的問題瀏覽器偏偏沒有給出解決方案,what?沒有方案還聊個(gè)什么? 別急,別急,接下來我們...

    Forest10 評(píng)論0 收藏0
  • 2017-09-07 前端日?qǐng)?bào)

    摘要:前端日?qǐng)?bào)精選機(jī)制詳解與中實(shí)踐應(yīng)用基礎(chǔ)與實(shí)踐如何用獲取虛擬鍵盤高度適用所有平臺(tái)和入門教程阮一峰的網(wǎng)絡(luò)日志編程技能提升指南中文到底什么是又是什么眾成翻譯調(diào)用模塊騰訊前端團(tuán)隊(duì)社區(qū)小書從一個(gè)簡單的例子講起小書教程小書優(yōu)化操作小書教 2017-09-07 前端日?qǐng)?bào) 精選 JavaScript Event Loop 機(jī)制詳解與 Vue.js 中實(shí)踐應(yīng)用 Redux 基礎(chǔ)與實(shí)踐如何用 js 獲取虛擬...

    沈儉 評(píng)論0 收藏0
  • 你不知道的h5

    摘要:目前,常用的模塊規(guī)范主要有兩種和。攔截全局請(qǐng)求一直接引入腳本攔截需要的回調(diào)或函數(shù)。深刻知道一個(gè)良好的命名規(guī)范的重要性,同時(shí)在項(xiàng)目中也會(huì)遇到一些命名的瓶頸。 基于 Three.js 的超快的 3D 開發(fā)框架:Whitestorm.js Whitestorm.js 是一款基于 Three.js 超快的 Web 應(yīng)用 3D 開發(fā)框架。它為普通的 Three.js 任務(wù)提供封裝、使搭建環(huán)境、...

    IntMain 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<