<template>
    <view class="wrap">
        <view
            class="draft"
            :style="{
                left: draftLeft,
                transform: draftTranslate,
            }"
            @touchstart="onTouchStart"
            @touchmove="onTouchMove"
        >
            <slot></slot>
        </view>
        <view class="inner">
            <template
                v-for="(item, index) in actions"
            >
                <view
                    v-if="actionType === 'text'"
                    :key="index"
                    class="inner-btn c-font-15"
                    :style="{
                        opacity: innerOpacity,
                        background: item.bgColor,
                    }"
                    hover-class="inner-hover"
                    @tap="onTap(item)"
                >{{ item.text }}</view>
                <view
                    v-else-if="actionType === 'icon'"
                    :key="index"
                    class="inner-icon"
                    @tap="onTap(item)"
                >
                    <image
                        class="inner-icon-img" :src="item.icon"
                        lazy-load
                    />
                </view>
            </template>
        </view>
    </view>
</template>

<script>
/**
 * @file 横滑
 * @author chenshuo04
 * @categories 业务组件
 * @tags [component]
 */
export default {
    config: {
        component: true
    },
    props: {
        /* 操作样式 */
        actionType: {
            type: String,
            default: 'text'
        },
        /* 操作 */
        actions: {
            type: Array,
            default: () => [{text: '删除', bgColor: '#ff6050', type: 'delete'}]
        },
        /* 展示 */
        showIndex: {
            type: Number,
            default: -1
        },
        /* 当前 index */
        index: {
            type: Number,
            default: 0
        }
    },
    data() {
        const distance = this.actionType === 'icon' ? 90 : 80;
        return {
            point: {
                startX: 0,
                startY: 0,
                endX: 0,
                endY: 0
            },
            aspectEmun: {
                up: 1,
                down: 2,
                left: 3,
                right: 4
            },
            minLimit: 10, // 滑动最小阈值，小于此值，滑动层不滑动
            distance: distance, // 覆盖层滑动最大距离
            delay: 1500, // 滑动后1.5s+未操作，滑动还原
            draftLeft: 0,
            draftTranslate: 'translate(0)',
            innerOpacity: 0
        };
    },
    watch: {
        showIndex(newVal, oldVal) {
            if (newVal !== this.index) {
                this.reset();
            }
        }
    },
    methods: {
        onTouchStart(e) {
            const touch = e.touches[0];
            // 记录起始点
            this.point.startX = touch.clientX;
            this.point.startY = touch.clientY;
        },
        onTouchMove(e) {
            // 计算滑动距离
            e = e || event;
            const touch = e.touches[0];
            this.point.endX = touch.clientX;
            this.point.endY = touch.clientY;
            // 滑动方向
            const offsetx = this.point.endX - this.point.startX;
            const aspect = this.getAspect(this.point.startX, this.point.startY, this.point.endX, this.point.endY);
            // 左滑
            if (aspect === this.aspectEmun.left || aspect === this.aspectEmun.right) {
                e.cancelable && e.preventDefault();
                e.stopPropagation && e.stopPropagation();
            }
            if (Math.abs(offsetx) < this.minLimit) {
                // 最小滑动阈值，防止页面上线滑动时，带出删除按钮
                return null;
            }
            if (aspect === this.aspectEmun.left) {
                /* 修改index */
                this.$emit('onSetIndex', this.index);
                this.$set(this, 'draftTranslate', 'translateX(-' + this.distance * this.actions.length + 'px)');
                this.$set(this, 'draftLeft', aspect + 'px');
                this.$set(this, 'innerOpacity', 1);
            } else if (aspect === this.aspectEmun.right) {
                this.reset();
            }
        },
        onTap(data) {
            /* 点击事件 */
            this.$emit('onTap', data);
        },
        getAspect(startx, starty, endx, endy) {
            const angx = endx - startx;
            const angy = endy - starty;
            const aspectEmun = this.aspectEmun;
            let result = 0;
            // 如果滑动距离太短
            if (Math.abs(angx) < 2 && Math.abs(angy) < 2) {
                return result;
            }
            const angle = Math.atan2(angy, angx) * 180 / Math.PI;
            if (angle >= -135 && angle <= -45) {
                result = aspectEmun.up;
            } else if (angle > 45 && angle < 135) {
                result = aspectEmun.down;
            } else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) {
                result = aspectEmun.left;
            } else if (angle >= -45 && angle <= 45) {
                result = aspectEmun.right;
            }
            return result;
        },
        reset() {
            this.$set(this, 'draftTranslate', 'translateX(0)');
            this.$set(this, 'draftLeft', 0);
            this.$set(this, 'innerOpacity', 0);
            Object.getOwnPropertyNames(this.point).map(name => {
                this.point[name] = 0;
                return name;
            });
        }
    }
};
</script>
<style lang="less" scoped>
.wrap {
    position: relative;
}
.draft {
    position: relative;
    z-index: 5;
    transition: .3s;
}
.inner {
    color: #fff;
    position: absolute;
    right: 0;
    top: 0;
    bottom: 0;
    height: 100%;
    text-align: center;
    display: flex;
    justify-content: center;
    align-items: center;
    transition: .3s;
    font-weight: bold;
}
.inner-btn {
    width: 80px;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}
.inner-icon {
    display: flex;
    justify-content: center;
    align-items: center;
    width: .5rem;
    height: .5rem;
    border-radius: .5rem;
    background: #fff;
    margin-right: .1rem;
    &-img {
        width: .2rem;
        height: .2rem;
    }
}
.inner-hover {
    opacity: .9;
}
.empty-img {
    display: inline-block;
    width: 40px;
    margin-bottom: 15px;
}
.font-link {
    color: #02b7ca;
}
</style>
