Weex实现炫酷的侧滑菜单效果

最近在在bindingX,使用bindingX结合weex手势可以比较轻松实现很炫酷的富交互效果,且性能很好,这里实现一个侧滑菜单的效果。weex中集成并使用bindingX看篇BindingX在weex中使用

老规矩,先上效果图

侧滑菜单效果图​​​​

侧滑组件源码:

<!--侧滑菜单实现-->
<template>
   <div class="container" :style="{backgroundColor:backgroundColor}">
       <div ref="left"   class="left" :style="{height:height,left:-leftWidth,width:leftWidth*2}">
            <slot name="left"></slot>
       </div>
       <div ref="right" @touchstart="touchstart" class="right" :style="{height:height}">
           <slot name="right"></slot>
       </div>
   </div>
</template>

<script>
    var modal=weex.requireModule('modal');
    var binding = weex.requireModule('binding');
    import { parse } from 'bindingx-parser'
    export default {
        name: "slider-menu",
        props:{
            timeFunction:{
                default:"linear",
                type:String
            },
            animationT:{
                default:200,
                type:Number
            },
            leftWidth:{
                default:200,
                type:Number
            },
            backgroundColor:{
                default:"#ffa00f",
                type:String
            },
        },
        data(){
            return{
                height:0,
                dx:0,
                endX:0,
                scaleLeft:0,
                scaleRght:1,
                isSlide:false,
                animationIng:false,
                token:0
            }
        },
        methods:{
            bindRight(){
                let self=this;
                let rightRef=self.$refs.right.ref;
                let leftRef=self.$refs.left.ref;
                let translate_x_expression="";
                let scale_expression='';
                let translate_x_expression_l='';
                let scale_expression_l='';
                if (!self.isSlide){
                    translate_x_expression=`x>0?x+0:x-x`;
                    scale_expression=`x>0?1-(x/1200):1`;
                    translate_x_expression_l=`x>0?x+0:x-x`;
                    scale_expression_l=`x>0?0+(x/${self.leftWidth}):0`;
                }else{
                    translate_x_expression=`x+${this.leftWidth}`;
                    scale_expression=`x>0?${self.scaleRght}-(x/1200):${self.scaleRght}-((1-${self.scaleRght})/200)*x`;
                    translate_x_expression_l=`x+${this.leftWidth}`;
                    scale_expression_l=
                        `x>0?${self.scaleLeft}+(x/${self.leftWidth}):${self.scaleLeft}+((${self.scaleLeft})/${self.leftWidth})*x`;;
                }
               self.token=binding.bind({
                    anchor:rightRef,
                    eventType:'pan',
                    props:[
                        {
                            element:rightRef,
                            property:'transform.translateX',
                            expression:parse(translate_x_expression)
                        },
                        {
                            element:rightRef,
                            property:'transform.scale',
                            expression:parse(scale_expression)
                        },
                       
                        {
                            element:leftRef,
                            property:'transform.translateX',
                            expression:parse(translate_x_expression_l)
                        },
                        {
                            element:leftRef,
                            property:'transform.scale',
                            expression:parse(scale_expression_l)
                        },
                       
                    ]
                },function (event) {
                    if(event.state==='end'){
                        self.dx=event.deltaX;
                        // modal.alert({message:self.scale })
                        if (!self.isSlide){
                            if(self.dx<0){
                                return;
                            }
                        }
                        self.scaleRght = self.scaleRght-event.deltaX/1200;
                        self.scaleLeft = self.scaleLeft+event.deltaX/self.leftWidth;
                        self.exeAnimation();
                    }
                }).token;
            },
            touchstart(e){
                let self=this;
                if(this.animationIng){
                    return;
                }
                self.bindRight();
            },
            //生成表达式
            getExpression(type){
                let self=this;
                let final_x=0;
                let final_scale=0;
                let changed_x=0;
                let translate_x_expression="";
                let scale_expression='';
                let final_x_l=0;
                let final_scale_l=0;
                let changed_x_l=0;
                let translate_x_expression_l="";
                let scale_expression_l='';
                if(type){
                    self.dx=0;
                    self.isSlide=false;
                    final_x = 0;
                    final_scale = 1;
                    changed_x = -this.leftWidth-self.dx;
                    let changed_scale=1-self.scaleRght;
                    translate_x_expression = self.timeFunction+ `(t,${this.leftWidth+self.dx},${changed_x},${self.animationT})`;
                    scale_expression=self.timeFunction+`(t,${self.scaleRght},${changed_scale},${self.animationT})`;

                     final_x_l=0;
                     final_scale_l=0;
                     changed_x_l=-this.leftWidth-self.dx;
                     let changed_scale_l=0-self.scaleLeft;
                     translate_x_expression_l= self.timeFunction+ `(t,${this.leftWidth+self.dx},${changed_x_l},${self.animationT})`;
                     scale_expression_l=self.timeFunction+`(t,${self.scaleLeft},${changed_scale_l},${self.animationT})`;

                    return {
                        translate_x_expression:translate_x_expression,
                        scale_expression:scale_expression,
                        final_scale:final_scale,
                        translate_x_expression_l:translate_x_expression_l,
                        scale_expression_l:scale_expression_l,
                        final_scale_l:final_scale_l,
                    }
                }
                //如果不是收起状态
                if (!self.isSlide){
                    if(Math.abs(self.dx)<this.leftWidth) { // 复位
                        self.isSlide=false;
                        final_x = 0;
                        final_scale = 1;
                        changed_x = final_x-self.dx;
                        let changed_scale=final_scale-self.scaleRght;
                        translate_x_expression = self.timeFunction+"(t,"+self.dx+","+changed_x+","+self.animationT+")";
                        scale_expression=self.timeFunction+`(t,${self.scaleRght},${changed_scale},${self.animationT})`;

                        final_x_l=0;
                        final_scale_l=0;
                        changed_x_l=final_x_l-self.dx;
                        let changed_scale_l=final_scale_l-self.scaleLeft;
                        translate_x_expression_l= self.timeFunction+"(t,"+self.dx+","+changed_x_l+","+self.animationT+")";
                        scale_expression_l=self.timeFunction+`(t,${self.scaleLeft},${changed_scale_l},${self.animationT})`;
                    } else if(Math.abs(self.dx) >this.leftWidth) { // 执行
                        self.isSlide=true;
                        final_x =this.leftWidth;
                        changed_x =final_x-Math.abs(self.dx);
                        final_scale = (1-400/1200);
                        let changed_scale=final_scale-self.scaleRght;
                        translate_x_expression = self.timeFunction+"(t,"+self.dx+","+changed_x+","+self.animationT+")";
                        scale_expression=self.timeFunction+`(t,${self.scaleRght},${changed_scale},${self.animationT})`;

                        final_x_l =this.leftWidth;
                        final_scale_l=1;
                        changed_x_l=final_x_l-self.dx;
                        let changed_scale_l=final_scale_l-self.scaleLeft;
                        translate_x_expression_l= self.timeFunction+"(t,"+self.dx+","+changed_x_l+","+self.animationT+")";
                        scale_expression_l=self.timeFunction+`(t,${self.scaleLeft},${changed_scale_l},${self.animationT})`;
                    }
                }else{
                    if(self.dx<0) { // 复位
                        self.isSlide=false;
                        final_x = 0;
                        final_scale= 1;
                        changed_x = -this.leftWidth-self.dx;
                        let changed_scale=1-self.scaleRght;
                        translate_x_expression = self.timeFunction+ `(t,${this.leftWidth+self.dx},${changed_x},${self.animationT})`;
                        scale_expression=self.timeFunction+`(t,${self.scaleRght},${changed_scale},${self.animationT})`;

                        final_x_l =0;
                        final_scale_l=0;
                        changed_x_l = -this.leftWidth-self.dx;
                        let changed_scale_l=final_scale_l-self.scaleLeft;
                        translate_x_expression_l=  self.timeFunction+ `(t,${this.leftWidth+self.dx},${changed_x_l},${self.animationT})`;
                        scale_expression_l=self.timeFunction+`(t,${self.scaleLeft},${changed_scale_l},${self.animationT})`;
                    } else if(self.dx>0) { // 执行
                        self.isSlide=true;
                        final_x = this.leftWidth;
                        changed_x = -self.dx;
                        final_scale = (1-400/1200);
                        let changed_scale=final_scale-self.scaleRght;
                        translate_x_expression = self.timeFunction+`(t,${this.leftWidth+self.dx},${changed_x},${self.animationT})`;
                        scale_expression=self.timeFunction+`(t,${self.scaleRght},${changed_scale},${self.animationT})`;

                        final_x_l =this.leftWidth;
                        final_scale_l=1;
                        changed_x_l = -self.dx;
                        let changed_scale_l=final_scale_l-self.scaleLeft;
                        translate_x_expression_l = self.timeFunction+`(t,${this.leftWidth+self.dx},${changed_x_l},${self.animationT})`;
                        scale_expression_l=self.timeFunction+`(t,${self.scaleLeft},${changed_scale_l},${self.animationT})`;
                    }
                }
                return {
                    translate_x_expression:translate_x_expression,
                    scale_expression:scale_expression,
                    final_scale:final_scale,
                    translate_x_expression_l:translate_x_expression_l,
                    scale_expression_l:scale_expression_l,
                    final_scale_l:final_scale_l,
                }
            },
            //执行动画
            exeAnimation(userDo){
                let self=this;
                this.animationIng=true;
                let rightRef=self.$refs.right.ref;
                let leftRef=self.$refs.left.ref;
                let { translate_x_expression,
                    scale_expression,
                    final_scale,
                    translate_x_expression_l,
                    scale_expression_l,
                    final_scale_l,
                     } =
                    this.getExpression(userDo);
                binding.bind({
                    eventType:'timing',
                    exitExpression: parse(`t>${this.animationT}`),
                    props:[
                        {
                            element:rightRef,
                            property:'transform.translateX',
                            expression:parse(translate_x_expression)
                        },
                        {
                            element:rightRef,
                            property:'transform.scale',
                            expression:parse(scale_expression)
                        },
                      
                        {
                            element:leftRef,
                            property:'transform.translateX',
                            expression:parse(translate_x_expression_l)
                        },
                        {
                            element:leftRef,
                            property:'transform.scale',
                            expression:parse(scale_expression_l)
                        },
                       
                    ]
                },function (event) {
                    if(event.state === 'end'||event.state === 'exit') {
                        self.scaleRght = final_scale;
                        self.scaleLeft = final_scale_l;
                        self.animationIng=false;
                        binding.unbindAll();
                    }
                })
            },
        },
        created(){
            let height=weex.config.env.deviceHeight;
            let width=weex.config.env.deviceWidth;
            this.height= height/width*750+60;``
            // modal.alert({message:this.height})
        }
    }
</script>

<style scoped>
     .container{
         width: 1200px;
         flex-direction: row;
     }
    .left{
        width: 200px;
        position: absolute;
        top:0;
    }
    .right{
        width: 1200px;
        background-color: #ffffff;
    }

</style>

使用方法:

<template>
    <div>
        <slider-menu  ref="menue" :left-width="250" timeFunction="easeOutBounce">
            <div slot="left" >
                <div @click="selectItem" style="width: 250px;height: 100px;align-items: center;justify-content: center;margin-top: 400px">
                     <text style="font-size: 34px;font-weight: bold;color: white">菜单一</text>
                </div>
                <div @click="selectItem" style="width: 250px;height: 100px;align-items: center;justify-content: center">
                    <text style="font-size: 34px;font-weight: bold;color: white">菜单二</text>
                </div>
                <div @click="selectItem" style="width: 250px;height: 100px;align-items: center;justify-content: center">
                    <text style="font-size: 34px;font-weight: bold;color: white">菜单三</text>
                </div>
            </div>
            <div slot="right">
                 <head title="测试slider-menu "></head>
            </div>
        </slider-menu>
    </div>
</template>

<script>
    import SliderMenu from "../components/sliderMenu.vue";
    import Head from "../components/head.vue";
    export default {
        components: {
            Head,
            SliderMenu},
        name: "slider-menu-demo",
        data() {
            return {

            }
        },
        methods:{
            selectItem(){
                this.$refs.menue.exeAnimation(1);
            }
        }
    }
</script>

<style scoped>

</style>

 在代码简洁以及动画表现方面还有一些提升空间, 还有需要改进的地方,后续会进行修改和优化。

 示例代码均在我的开源项目中,可以随时查看https://github.com/liuxinyea/IWeex

发布了49 篇原创文章 · 获赞 19 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_33718648/article/details/90213040
今日推荐