Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Android/Chrome上提高touchmove性能?_Android_Performance_Vue.js_Google Chrome_Touch Event - Fatal编程技术网

如何在Android/Chrome上提高touchmove性能?

如何在Android/Chrome上提高touchmove性能?,android,performance,vue.js,google-chrome,touch-event,Android,Performance,Vue.js,Google Chrome,Touch Event,我正在开发一个使用触摸事件的自定义拖动UI。当页面上有滚动条时,ChromeAndroidtouchmove性能糟糕,事件每秒只会触发几次,导致极为剧烈的拖动。当没有滚动条或使用ChromeDevToolsEmulator进行测试时,问题不会重现 添加触摸事件:无CSS属性有助于解决这个问题,但也可以防止容器内部发生本机滚动,因此使用这种方法需要我重新实现像JS滚动一样的本机滚动 演示: Vue组件代码: <template> <div class="cont

我正在开发一个使用触摸事件的自定义拖动UI。当页面上有滚动条时,ChromeAndroid
touchmove
性能糟糕,事件每秒只会触发几次,导致极为剧烈的拖动。当没有滚动条或使用ChromeDevToolsEmulator进行测试时,问题不会重现

添加
触摸事件:无
CSS属性有助于解决这个问题,但也可以防止容器内部发生本机滚动,因此使用这种方法需要我重新实现像JS滚动一样的本机滚动

演示:

Vue组件代码:

<template>
    <div class="container">
        <div
            :class="containerClass"
            :style="containerStyle"
            @touchend="touchEndHandler"
            @touchmove="touchMoveHandler"
            @touchstart="touchStartHandler"
            @transitionend="transitionEndHandler"
            class="scroller-container"
        >
            <svg viewBox="0 0 100 20" always-swipeable="true" class="drag-handle">
                <polyline points="27,10 73,10" stroke-linecap="round"></polyline>
            </svg>
            <div class="scrollbox" ref="scrollbox">
                <div :key="item" class="item" v-for="item in items">
                    {{ item }}
                </div>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    data() {
        return {
            deltaY: 0,
            isDraggingByHandle: false,
            isTransitioning: false,
            items: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
            offsetHeight: 0,
            scrollboxHeight: 0,
            scrollTop: 0,
            touchAction: null,
            verticalStates: [
                {
                    translateY: 0,
                },
                {
                    translateY: window.innerHeight - 200,
                },
            ],
            verticalStateIndex: 0,
        }
    },

    computed: {
        activeVerticalState() {
            return this.verticalStates[this.verticalStateIndex]
        },
        containerClass() {
            return {
                'show-scrollbar': this.isScrollable,
                transition: this.isTransitioning,
            }
        },
        containerStyle() {
            return {
                transform: `translateY(${this.translateY}px)`,
            }
        },
        isAnySwipe() {
            return this.isDraggingByHandle || !this.isScrollable
        },
        isExpanded() {
            return this.verticalStateIndex === 0
        },
        isScrollable() {
            return this.isExpanded && this.scrollHeight > this.offsetHeight
        },
        isSwipeDown() {
            return this.deltaY > 0 && (this.isAnySwipe || this.scrollTop === 0)
        },
        isSwipeUp() {
            return (
                this.deltaY < 0 &&
                (this.isAnySwipe || this.offsetHeight + this.scrollTop === this.scrollHeight)
            )
        },
        scrollbox() {
            return this.$refs.scrollbox
        },
        translateY() {
            let translateY = this.activeVerticalState.translateY
            if (this.touchAction === 'verticalSwipe' && (this.isSwipeDown || this.isSwipeUp)) {
                translateY = translateY + this.deltaY
            }
            return translateY
        },
    },

    mounted() {
        this.updateScrollboxData()
    },

    methods: {
        touchStartHandler: function({touches, target}) {
            this.updateScrollboxData()
            this.isDraggingByHandle = Boolean(target.getAttribute('always-swipeable'))
            this.touchStartCoordinates = touches[0]
            this.touchAction = 'tap'
        },
        touchMoveHandler: function(event) {
            this.updateScrollboxData()
            this.deltaY = event.touches[0].clientY - this.touchStartCoordinates.clientY
            // promote touchAction to swipe or scroll depending on deltas and other variables
            if (this.touchAction === 'tap') {
                if (this.isSwipeDown || this.isSwipeUp) {
                    this.touchAction = 'verticalSwipe'
                } else {
                    this.touchAction = 'scroll'
                }
            }
        },
        touchEndHandler: function() {
            switch (this.touchAction) {
                case 'tap':
                    if (!this.isExpanded) {
                        this.verticalStateIndex = Math.max(this.verticalStateIndex - 1, 0)
                        this.isTransitioning = true
                    }
                    break
                case 'verticalSwipe':
                    if (this.isSwipeDown) {
                        this.verticalStateIndex = Math.min(
                            this.verticalStateIndex + 1,
                            this.verticalStates.length - 1
                        )
                    } else if (this.isSwipeUp) {
                        this.verticalStateIndex = Math.max(this.verticalStateIndex - 1, 0)
                    }
                    this.isTransitioning = true
                    this.deltaY = 0
                    break
            }
        },
        transitionEndHandler() {
            this.touchAction = null
            this.isTransitioning = false
            this.updateScrollboxData()
        },
        updateScrollboxData() {
            const {scrollHeight, offsetHeight, scrollTop} = this.scrollbox
            this.offsetHeight = offsetHeight
            this.scrollHeight = scrollHeight
            this.scrollTop = scrollTop
        },
    },
}
</script>

<style lang="scss" scoped>
.container {
    display: flex;
    justify-content: center;
    margin-top: 5vh;
    overflow: hidden;

    .scroller-container {
        pointer-events: all;
        width: 90vw;
        height: 100%;

        &.transition {
            transition: transform 0.15s ease-out;
        }

        .drag-handle {
            stroke-width: 5px;
            stroke: #bfbfc0;
            width: 100%;
            height: 30px;
            background: pink;
        }

        .scrollbox {
            overflow-y: hidden;
            pointer-events: none;
            background: green;
            height: 85vh;

            .item {
                margin-bottom: 20px;
                height: 150px;
                font-size: 36px;
                background: yellow;
            }
        }

        &.show-scrollbar .scrollbox {
            overflow-y: scroll;
            pointer-events: all;
        }
    }
}
</style>

{{item}}
导出默认值{
数据(){
返回{
德尔泰:0,
IsDragingByHandle:false,
isTransitioning:false,
项目:[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],
离地:0,
scrollboxHeight:0,
滚动顶端:0,
touchAction:null,
垂直状态:[
{
translateY:0,
},
{
translateY:window.innerHeight-200,
},
],
垂直状态索引:0,
}
},
计算:{
activeVerticalState(){
返回此.verticalStates[此.verticalStateIndex]
},
集装箱类(){
返回{
“显示滚动条”:this.iscrowllable,
转变:这是转变,
}
},
集装箱运输方式(){
返回{
transform:`translateY(${this.translateY}px)`,
}
},
isAnySwipe(){
返回此.IsDragingByHandle | | |!此.IsCrollable
},
isExpanded(){
返回此值。verticalStateIndex==0
},
可转换的{
返回this.isExpanded&&this.scrollHeight>this.offsetHeight
},
IsSweepDown(){
返回this.deltaY>0&(this.isAnySwipe | | this.scrollTop==0)
},
Isswipup(){
返回(
这是德尔泰<0&&
(this.isAnySwipe | | this.offsetHeight+this.scrollTop==this.scrollHeight)
)
},
滚动框(){
返回此。$refs.scrollbox
},
translateY(){
让translateY=this.activeVerticalState.translateY
if(this.touchAction==='verticalSwipe'&&(this.isSwipeDown | | this.isSwipeUp)){
translateY=translateY+this.deltaY
}
返回平移
},
},
安装的(){
this.updateScrollboxData()
},
方法:{
touchStartHandler:函数({touchs,target}){
this.updateScrollboxData()
this.isDragingByHandle=Boolean(target.getAttribute('always-swipeable'))
this.touchStartCoordinates=触摸[0]
this.touchAction='tap'
},
touchMoveHandler:函数(事件){
this.updateScrollboxData()
this.deltaY=event.touchs[0].clientY-this.touchStartCoordinates.clientY
//根据增量和其他变量,将touchAction升级为滑动或滚动
如果(this.touchAction==='tap'){
如果(this.isSwipeDown | this.isSwipeUp){
this.touchAction='verticalSwipe'
}否则{
this.touchAction='scroll'
}
}
},
touchEndHandler:函数(){
开关(此.touchAction){
案例“tap”:
如果(!this.isExpanded){
this.verticalStateIndex=Math.max(this.verticalStateIndex-1,0)
this.isTransitioning=true
}
打破
“垂直滑动”案例:
如果(此.isSwipeDown){
this.verticalStateIndex=Math.min(
此.verticalStateIndex+1,
此.verticalStates.length-1
)
}否则,如果(此.isswipup){
this.verticalStateIndex=Math.max(this.verticalStateIndex-1,0)
}
this.isTransitioning=true
此值为0.deltaY=0
打破
}
},
transitionEndHandler(){
this.touchAction=null
this.isTransitioning=false
this.updateScrollboxData()
},
updateScrollboxData(){
const{scrollHeight,offsetHeight,scrollTop}=this.scrollbox
this.offsetHeight=offsetHeight
this.scrollHeight=滚动高度
this.scrollTop=scrollTop
},
},
}
.集装箱{
显示器:flex;
证明内容:中心;
边缘顶部:5vh;
溢出:隐藏;
.滚动条容器{
指针事件:全部;
宽度:90vw;
身高:100%;
&.过渡{
转换:转换0.15秒缓解;
}
.拖动手柄{
笔画宽度:5px;
行程:#bfc0;
宽度:100%;
高度:30px;
背景:粉红色;
}
.滚动框{
溢出y:隐藏;
指针事件:无;
背景:绿色;
高度:85vh;
.项目{
边缘底部:20px;
高度:150像素;
字体大小:36px;
背景:黄色;
}
}
&.显示滚动条.滚动框{
溢出y:滚动;
指针事件