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?

相关文章
相关标签/搜索