84961 拖拽浮标、vant导航栏吸顶、vant弹窗、vant列表懒加载

https://huodong.fanli.com/h5/jdsellactivity.html

html

<?php
    $title = '京东11.11全球热爱季';
    $cssList = array(implode(",", array(
        '//static2.51fanli.net/static/?f=webapp/css/base.css',
        'common/libs/vant/index.css',
        'huodong/jdsellactivity/css/index.css'
        ))
    );
    $jsList = array(implode(",", array(
        '//static2.51fanli.net/static/?f=webapp/js/base.js',
        'common/js/fanli/trace/ubt.js',
        'common/libs/fmu/js/core/fmu.js',
        'common/libs/fmu/js/core/widget.js',
        'common/libs/fmu/js/extend/jquery.extend.js',
        'webapp/js/common/hybridapi/nativefunction_v2.js',
        'common/libs/vue/vue-lazyload.js',
        'common/libs/fmu/js/vendors/vue/vue-2.6.14.js',
        'common/libs/vant/index.js',
        'huodong/jdsellactivity/js/index.js'
        ))
    );
?>

<include file="$header" remwidth="750" remswitch="1" />
 
<div id="app">
  <template>
    <div v-if="topCfg" class="top-pic">
      <img class="top-pic-bg" :src="topCfg.bg_img" alt="">
      <div class="rule-btn" @click="showRuleDialog"></div>
      <div
        v-for="(item, index) of topCfg.hotAreaList"
        :key="index" class="hot-area"
        :style="{ width: (item.w)/100+'rem', height: (item.h)/100+'rem', left: (item.x)/100+'rem', top: (item.y)/100+'rem'}"
        @click="topPicHotLinkJump(item.link)"
      ></div>
    </div>
    <div class="huichang-pic">
      <img class="huichang-pic-bg" :src="huichangCfg.bg_img" alt="">
      <div
        v-for="(item, index) of huichangCfg.hotAreaList"
        :key="index"
        class="hot-area"
        :style="{ width: (item.w)/100+'rem', height: (item.h)/100+'rem', left: (item.x)/100+'rem', top: (item.y)/100+'rem'}"
        @click="huichangHotLinkJump(item.link,index)"
      ></div>
    </div>
    <van-dialog
      class="dialog-box"
      v-model="showDialog"
      title="活动规则"
    >
      <div class="dialog-content" v-if="gaeaCfg">
        <div v-for="(item, index) of gaeaCfg.rule[0].data1.split('\n')" v-html="item"></div>
      </div>
      <van-icon name="close" class="dialog-close-btn" @click="closeRuleDialog"/>
    </van-dialog>
    <div v-if="navCfg">
      <!-- 导航 -->
      <van-tabs
        :v-model="0"
        :color="navCfg.backcolor"
        :background="navCfg.backcolor"
        :title-active-color="navCfg.selected_color"
        :title-inactive-color="navCfg.no_select_color"
        :ellipsis="false"
        sticky
        @click="changeNavTab"
      >          
        <van-tab v-for="(nav, navIndex) of navTitleArr" :key="navIndex" :title="nav">
          <div class="container">
            <van-list
              v-model="loading"
              :finished="finished"
              finished-text="没有更多了"
              :immediate-check="false"
              @load="loadingMore"
            > 
              <div v-if="listData.length>0">
                <div class="pro-item-box" v-for="(item, index) of listData" :key="index" @click="goShop(item.skuId, item.popup_link)">
                  <div class="pro-item-left">
                    <img class="pic-img" :src="item.imgUrl" alt="">
                  </div>
                  <div class="pro-item-right">
                    <div class="item-title">{{ item.skuName }}</div>
                    <div class="quan-box">
                      <span class="cut-price" v-if="item.preAmountDeposit">付定金减{{ item.preAmountDeposit }}元</span>
                      <span class="quan" v-if="item.coupon_amount!=0">{{ item.coupon_amount }}元券</span>
                    </div>
                    <div class="price-box">
                      <span class="text" v-if="item.earnest">预售价</span>
                      <span class="text" v-else>到手价</span>
                      <span class="yuan">¥</span>
                      <span class="pre-num-one" v-if="item.prePrice && !item.prePrice.split('.')[1]" style="margin-right: 0.1rem;">{{ item.prePrice.split('.')[0] }}</span>
                      <span class="pre-num-one" v-if="item.prePrice && item.prePrice.split('.')[1]">{{ item.prePrice.split('.')[0] }}.</span>
                      <span class="pre-num-two" v-if="item.prePrice && item.prePrice.split('.')[1]">{{ item.prePrice.split('.')[1] }}</span>
                      <span class="old-price" v-if="item.prePrice<item.price">¥{{ item.price }}</span>
                    </div>
                    <div class="dj-btn" v-if="item.earnest">立即付{{ item.earnest }}元定金</div>
                    <div class="dj-btn" v-else>立即购买</div>
                  </div>
                </div>
              </div>
              <div v-else style="height: 50vh;"></div>
            </van-list>
          </div>
        </van-tab>
      </van-tabs>
    </div>
    <!-- 可拖拽的浮标 -->
    <img
      v-if="gaeaCfg"
      :src="gaeaCfg.float[0].img"
      class="moveable-float-window"
      @touchstart="wtouchstart"
      @touchmove="wtouchmove"
      @touchend="wtouchend"
      @mousedown="wonmousedown"
      @mousemove="wonmousemove"
      @mouseup="wonmouseup"
      @click="floatWinJump"
    />
  </template>
</div>

<input id="J_bg_color" type="text" value="{$gaea['background'][0].data1}" hidden>
<include file="$footer"/>

less:

// out: ../css/
html, body, div, span, img {
  box-sizing: border-box;
}
html, body {
  width: 100%;
  overflow-x: hidden;
}
#app{width: 100%;height: 100%;position: relative;}
.van-tabs__nav--line.van-tabs__nav--complete {
  display: flex;
  align-items: center;
}
.van-tab--active {
  width: auto;
}
.van-tab--active > span {
  display: inline-block;
  width: auto;
  height: .6rem;
  text-align: center;
  border-radius: .1rem;
  padding: .05rem .3rem;
  font-size: .26rem;
  display: flex;
  align-items: center;
  background-color: #1f8bf9;
  white-space: nowrap;
}
.van-tab__text {
  font-size: 0.26rem;
}
.van-dialog {
  overflow: visible;
}
.van-dialog__header {
  padding: .2rem 0 0.1rem;
}
.van-dialog__footer {
  display: none;
}
.container {
  width: 7.1rem;
  margin: 0 auto;
  padding-bottom: 0.3rem;
}
.top-pic {
  width: 7.5rem;
  height: auto;
  position: relative;
  .top-pic-bg {
    width: 7.5rem;
    height: auto;
  }
  .rule-btn {
    width: 1.2rem;
    height: .4rem;
    border-radius: 0.2rem 0 0 0.2rem;
    position: absolute;
    top: .1rem;
    right: 0;
  }
  .hot-area {
    position: absolute;
    z-index: 100;
  }
}
.huichang-pic {
  width: 7.5rem;
  height: auto;
  position: relative;
  .huichang-pic-bg {
    width: 7.5rem;
    height: auto;
  }
  .hot-area {
    position: absolute;
    z-index: 100;
  }
}
.dialog-box {
  width: 5.4rem;
  position: fixed;
  z-index: 1002;
  background-color: #fff;
  border-radius: 0.2rem;
  .dialog-content {
    max-height: 9rem;
    overflow-y: auto;
    border-radius: .2rem;
    padding: 0.14rem 0.28rem 0.22rem;
    color: #555;
    font-size: 0.25rem;
    word-break: break-all;
    position: relative;
  }
  .dialog-close-btn {
    font-size: .6rem;
    color: #fff;
    position: absolute;
    top: -0.74rem;
    right: 0;
  }
}
.pro-item-box {
  width: 7.1rem;
  height: 2.98rem;
  background: #FFFFFF;
  border-radius: 0.1rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.2rem 0.22rem;
  margin: 0.2rem auto;
  .pro-item-left {
    width: 2.6rem;
    height: 2.6rem;
    overflow: hidden;
    .pic-img {
      width: 2.6rem;
      height: 2.6rem;
    }
  }
  .pro-item-right {
    width: 3.97rem;
    height: 2.6rem;
    position: relative;
    .item-title {
      width: 3.97rem;
      height: 0.71rem;
      line-height: 0.36rem;
      font-size: 0.28rem;
      font-weight: bold;
      color: #111111;
      margin-bottom: 0.14rem;
      word-break: break-all;
      text-overflow: -o-ellipsis-lastline;
      overflow: hidden;
      text-overflow: ellipsis;
      display: -webkit-box;
      -webkit-line-clamp: 2;
      line-clamp: 2;
      -webkit-box-orient: vertical;
    }
    .quan-box {
      display: flex;
      justify-content: flex-start;
      align-items: flex-end;
      span {
        display: inline-block;
        width: auto;
        height: .3rem;
        line-height: .3rem;
        font-size: .22rem;
        border-radius: .05rem;
        margin-right: .16rem;
        color: #fff;
        padding: 0.04rem 0.08rem;
        display: flex;
        align-items: center;
      }
      .cut-price {
        background: #3BB3F0;
      }
      .quan {
        background: #F1450C;
      }
    }
    .price-box {
      font-size: 0.24rem;
      color: #F10C10;
      display: flex;
      height: 0.56rem;
      align-items: flex-end;
      span {
        display: inline-flex;
        height: 0.56rem;
        align-items: flex-end;
      }
      .text {
        white-space: nowrap;
        position: relative;
        top: 0.03rem;
      }
      .yuan {
        font-weight: bold;
        margin: 0 0.02rem;
      }
      .pre-num-one {
        font-size: 0.4rem;
        font-weight: bold;
        position: relative;
        top: 0.04rem;
      }
      .pre-num-two {
        font-weight: bold;
        margin-right: 0.1rem;
      }
      .old-price {
        color: #8A8A8A;
        text-decoration: line-through;
      }
    }
    .dj-btn {
      width: 3.97rem;
      height: 0.6rem;
      line-height: 0.6rem;
      text-align: center;
      background-image: linear-gradient(-89deg, #F15665 0%, #EF4361 100%);
      border-radius: 0.3rem;
      color: #fff;
      font-size: 0.28rem;
      position: absolute;
      right: 0;
      bottom: 0;
      display: flex;
      justify-content: center;
      align-items: center;
    }
  }
}
.moveable-float-window {
  width: 0.9rem;
  height: 0.9rem;
  position: fixed;
  right: 0rem;
  top: 70%;
  z-index: 500;
}

js:

;
(function(){
  document.body.style.backgroundColor = $('#J_bg_color').val()
  var baseUrl = 'https://huodong.fanli.com/h5/jdsellactivity';

  Vue.use(VueLazyload, {
    preLoad: 4,
    loading: '//static2.51fanli.net/common/images/loading/spacer.png'
  });

  new Vue({
    el: '#app',
    data: {
      showDialog: false,
      gaeaCfg: '',
      topCfg: '',
      huichangCfg: '',
      navCfg: '',
      navTitleArr: [ '实时热销', '品质家电', '全球热卖', '商超好货' ],
      navName: '',
      pageNum: 0,
      pageSize: 5,
      listData: [],
      loading: false,
      finished: false,
      ubtNavIndex: 1,
      bgColor: '', // 页面背景色
      mouseStartX: 0,
      mouseStartY: 0,
      currX: 0,
      currY: 0,
      pcDownFlag: false
    },
    mounted () {
      UBT.track("page_name.h5.pty-homepv~std-84961")
      this.initPage()
      this.changeNavTab(0)
    },
    methods: {
      initPage: function() {
        var that = this;
        $.getJSON(baseUrl + "/gaeaCfg", function(res) {
          if(res.code === 1) {
            that.gaeaCfg = res.data.gaeaCfg
            that.topCfg = res.data.top
            that.huichangCfg = res.data.huichang
            that.navCfg= res.data.tab_style
          }
        })
      },
      showRuleDialog: function () {
        UBT.track("page_name.h5.pty-rule~std-84961")
        this.showDialog = true
      },
      closeRuleDialog: function () {
        this.showDialog = false
      },
      loadingMore: function () {
        var that = this;
        that.pageNum++
        $.getJSON(baseUrl + "/productList", {
          name: that.navName,
          page: that.pageNum,
          size: that.pageSize
        }, function(res) {
          if(res.code === 1) {
            for (var i = 0; i < res.list_data.length; i++) {
              that.listData.push(res.list_data[i])
            }
            that.loading = false;
            if (res.list_data.length === 0) {
              that.finished = true;
            }
          }
        })
      },
      changeNavTab: function (index) {
        this.ubtNavIndex = index + 1
        UBT.track("spm=page_name.h5.pty-tabdj~tab-"+ this.ubtNavIndex +"~std-84961")
        if (index == 0) {
          this.navName = 'ssrx'
        } else if (index == 1) {
          this.navName = 'pzjd'
        } else if (index == 2) {
          this.navName = 'qqrm'
        } else {
          this.navName = 'schh'
        }
        this.pageNum = 0
        this.listData = []
        this.loading = true
        this.finished = false
        this.loadingMore()
      },
      topPicHotLinkJump: function (link) {
        window.location.href = link
      },
      huichangHotLinkJump: function (link, index) {
        var ubtIndex = index + 1
        UBT.track("page_name.h5.pty-addj~data-" + ubtIndex + "~std-84961")
        window.location.href = link
      },
      floatWinJump: function () {
        window.location.href = this.gaeaCfg.float[0].link
      },
      goShop: function (id, link) {
        UBT.track("page_name.h5.pty-plist~tab-" + this.ubtNavIndex + "~pid-" + id + "~std-84961")
        window.location.href = link
      },
      // 移动端事件 touch start
      wtouchstart(e){
        // 相对于父元素的右上角座标为 x=0,y=0
        this.mouseStartX = e.changedTouches[0].pageX //获取鼠标点击的X坐标
        this.mouseStartY = e.changedTouches[0].pageY //获取鼠标点击的Y坐标
        this.currX = e.changedTouches[0].target.offsetLeft //相对于当前窗口X轴的偏移量
        this.currY = e.changedTouches[0].target.offsetTop //相对于当前窗口Y轴的偏移量
      },
      // 移动端事件 touch move
      wtouchmove(e){
        var currDom = e.changedTouches[0].target
        e.preventDefault();
        moveX=e.changedTouches[0].pageX;//移动过程中X轴的坐标
        moveY=e.changedTouches[0].pageY;//移动过程中Y轴的坐标
        var leftX = this.mouseStartX-this.currX  //鼠标所能移动的最左端是当前鼠标距div左边距的位置
        var rightX = currDom.parentNode.clientWidth-currDom.clientWidth+leftX  //鼠标所能移动的最右端是当前窗口距离减去鼠标距div最右端位置
        var topY = this.mouseStartY-this.currY  //鼠标所能移动最上端是当前鼠标距div上边距的位置
        var bottomY = currDom.parentNode.clientHeight-currDom.clientHeight+topY //鼠标所能移动最下端是当前窗口距离减去鼠标距div最下端位置
        // console.log(bottomY)
        if(moveX<leftX){moveX=leftX;}
        if(moveX>rightX){moveX=rightX;}
        if(moveY<topY){moveY=topY;}
        if(moveY>bottomY){moveY=bottomY;}
        currDom.style.left = (moveX+ this.currX-this.mouseStartX) + 'px'
        currDom.style.top = (moveY+this.currY-this.mouseStartY) + 'px'
      },
      // 移动端事件 touch end
      wtouchend(e){
        const currDom = e.changedTouches[0].target
        e.preventDefault();
        moveX=e.changedTouches[0].pageX;//移动过程中X轴的坐标
        moveY=e.changedTouches[0].pageY;//移动过程中Y轴的坐标
        if (currDom.offsetTop >= window.screen.height - 200) {
          currDom.style.top = (window.screen.height - 200) + 'px'
        }
        if(this.currX == currDom.offsetLeft && this.currY == currDom.offsetTop){
          // div座标未移动,认为它是点击事件
          window.location.href = this.gaeaCfg.float[0].link
        }else{
          var left = moveX+ this.currX-this.mouseStartX
          // 以下是左右吸边计算
          var subX = currDom.parentNode.clientWidth - currDom.clientWidth
          if(left >= subX/2){
            currDom.style.left = subX + 'px'
          }else{
            currDom.style.left = 0 + 'px'
          }
        }
      },
      // 电脑端 onmouse down
      wonmousedown (e){
        // 相对于父元素的右上角座标为 x=0,y=0
        this.mouseStartX = e.pageX //获取鼠标点击的X坐标
        this.mouseStartY = e.pageY //获取鼠标点击的Y坐标
        this.currX = e.target.offsetLeft //相对于当前窗口X轴的偏移量
        this.currY = e.target.offsetTop //相对于当前窗口Y轴的偏移量
        this.pcDownFlag = true
      },
      // 电脑端 onmouse move
      wonmousemove(e){
        if(!this.pcDownFlag){ //这是移动端touch和mouse方法唯一的区别了,试着可以注释掉,就知道原因了
          return
        }
        var currDom = e.target
        e.preventDefault();
        moveX=e.pageX;//移动过程中X轴的坐标
        moveY=e.pageY;//移动过程中Y轴的坐标
        var leftX = this.mouseStartX-this.currX  //鼠标所能移动的最左端是当前鼠标距div左边距的位置
        var rightX = currDom.parentNode.clientWidth-currDom.clientWidth+leftX  //鼠标所能移动的最右端是当前窗口距离减去鼠标距div最右端位置
        var topY = this.mouseStartY-this.currY  //鼠标所能移动最上端是当前鼠标距div上边距的位置
        var bottomY = currDom.parentNode.clientHeight-currDom.clientHeight+topY //鼠标所能移动最下端是当前窗口距离减去鼠标距div最下端位置
        if(moveX<leftX){moveX=leftX;}
        if(moveX>rightX){moveX=rightX;}
        if(moveY<topY){moveY=topY;}
        if(moveY>bottomY){moveY=bottomY;}
        currDom.style.left = (moveX+ this.currX-this.mouseStartX) + 'px'
        currDom.style.top = (moveY+this.currY-this.mouseStartY) + 'px'
      },
      // 电脑端 onmouse up
      wonmouseup(e){
        this.pcDownFlag = false
        const currDom = e.target
        e.preventDefault();
        moveX=e.pageX;//移动过程中X轴的坐标
        moveY=e.pageY;//移动过程中Y轴的坐标
        if(this.currX == currDom.offsetLeft && this.currY == currDom.offsetTop){
          // div座标未移动,认为它是点击事件
          console.log('点击事件');
        }else{
          var left = moveX+ this.currX-this.mouseStartX
          // 以下是左右吸边计算
          var subX = currDom.parentNode.clientWidth - currDom.clientWidth
          if(left >= subX/2){
            currDom.style.left = subX + 'px'
          }else{
            currDom.style.left = 0 + 'px'
          }
        }
      }
    }
  })
})();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值