Vue能不能寫一個Android版QQ?

vue-mobile-qq

週末嘗試用vue寫了一個android版QQ客戶端的Web App demo。暫時只寫了首頁消息這個界面,幾個小圖標是用sketch畫的svg。側滑欄的背景圖終於祭出了個人ps。底部導航圖標由於實在不太會用sketch,先放棄了。javascript

DEMO地址

請使用最新版chrome + mobile emulator 訪問vue

github.com/hilongjw/vu…java

手勢

想來說下手勢識別的實現的思路,代碼在這裏(目前還不完善)android

listen (type, $el, func) {
    let rect
    if (!$el) {
        rect = null
    } else {
        let tmp = $el.getBoundingClientRect()
        rect = {
            x: tmp.left,
            y: tmp.top,
            width: tmp.width,
            height: tmp.height
        }
    }

    let token = Math.random() * 9999 + type
    this.queue[type].push({
        $el: $el,
        token: token,
        func: func,
        rect: rect
    })
}複製代碼

首先個人思路是監聽窗口的touch事件,以組件自身的像素區域來派發事件,調用listen的時候傳入想要監聽事件的類型和指望觸發該事件的Element, 還有就是加上觸發的函數回調。若是不傳入Element的話,就會接收到所有的事件觸發。git

這裏首先是註冊訂閱該組件固然的像素區域,那麼若是滑動頁面以後改怎麼辦?github

update () {
    let keys = Object.keys(this.queue)
    let tmp
    for (let key of keys) {
        this.queue[key].forEach(item => {
            if (item.$el) {
                tmp = item.$el.getBoundingClientRect()
                item.rect = {
                    x: tmp.left,
                    y: tmp.top,
                    width: tmp.width,
                    height: tmp.height
                }
            }
        })
    }
}複製代碼

這裏的update就須要在body 或者其上級節點 scroll的時候調用來更新組件的註冊區域。chrome

init () {
    if (this._hasTouch) {
        window.document.body.addEventListener('touchstart', this.touchStart.bind(this), false)
        window.document.body.addEventListener('touchmove', this.touchMove.bind(this), false)
        window.document.body.addEventListener('touchend', this.touchEnd.bind(this), false)
        window.document.body.addEventListener('touchcancel', this.touchCancel.bind(this), false)
    }
}複製代碼

這裏是註冊全局的touch監聽dom

touchStart (e) {
    this.state.swiping = true
    this.touch.start = this.getPosition(e)[0]
}

touchMove (e) {
    this.touch.end = this.getPosition(e)[0]
    this.notice('swiping', this.getRect(this.touch.end, this.touch.start))
}複製代碼

這裏是對swiping 在touchmove時不斷派發事件,可能須要優化一下加上節流。若是在加上滑動路徑和趨勢分析就更好了。svg

touchEnd (e) {
    this.notice('swiped', this.getRect(this.touch.end, this.touch.start))
    this.state.swiping = true
    let angle = this.getAngle(this.touch.end, this.touch.start)
    if (angle > -45 && angle < 45) {
        this.notice('swipe-left', this.getRect(this.touch.end, this.touch.start))
    }
    if (angle < -135 || angle > 135) {
        this.notice('swipe-right', this.getRect(this.touch.end, this.touch.start))
    }
    if (angle > 45 && angle < 135) {
        this.notice('swipe-up', this.getRect(this.touch.end, this.touch.start))
    }
    if (angle < -45 && angle > -135) {
        this.notice('swipe-down', this.getRect(this.touch.end, this.touch.start))
    }
}

touchCancel (e) {
    console.log(e)
}複製代碼

這裏就是對一次touch過程的方向判斷,而後派發事件函數

notice (type, rect) {
    let rectTmp = {}
    let once = true
    let tmpFunc = null
    for (let i = 0, len = this.queue[type].length; i < len; i++) {
        rectTmp = this.queue[type][i].rect
        if (!rectTmp) {
            tmpFunc = this.queue[type][i].func
        } else {
            if (this.rectIn(rect, rectTmp) && !this.state.global) {
                this.queue[type][i].func(this.touch.start, this.touch.end)
                once = false
            }
        }
    }
    if (once && tmpFunc) {
        tmpFunc(this.touch.start, this.touch.end)
    }
}複製代碼

這裏是派發的函數實現,爲了此次demo的實現,我把全局手勢優先級設置爲低於指定區域的優先級。

用例

export default {
        props: {
            message: Object
        },
        data () {
            return {
                closeToken: '',
                swiping: 0,
                menu: false
            }
        },
        ready () {
            this.add()
        },
        methods: {
            add () {
                this.$swipe.listen('swipe-left', this.$el, () => {
                    this.swiping = -160
                    this.menu = true
                    this.closeToken = this.$swipe.listen('swipe-right', this.$el, () => {
                        this.swiping = 0
                        this.menu = false
                        this.$swipe.leave('swipe-right', this.closeToken)
                    })
                })

                this.$swipe.listen('swiping', this.$el, (start, end) => {
                    if (start.x > end.x && this.swiping > -160) {
                        this.swiping = -(start.x - end.x)
                    }
                })
                this.$swipe.listen('swiped', this.$el, (start, end) => {
                    if (!this.menu) {
                        this.swiping = 0
                    }
                })
            }
        }
    }複製代碼

這是在消息組件所有代碼。 目前還沒(bu)計(xiang)劃(xie)整合爲vue指令。

github 不給來個star?

相關文章
相關標籤/搜索