web h5踩坑及解决办法(z-index,滚动到底部,同步滚动等)

  • 子元素使用了position:absolute,但未给其相对父元素设置非static定位,导致不同手机浏览器展示不同定位注意: 子绝父相
	.signImage_exector{//非执行人同步签字画面
       height: calc(100% - 32px);
       width: calc(100% - 32px);
       position:relative;
       .toast{
         position:absolute;
         top:45%;
         opacity: 0.81;
       }
     }

  • z-index对于ios的safari浏览器是无效的解决办法:为safari浏览器单独设置transform: translateZ(1000px);
.toast_container {
  opacity: 0.79;
  position: absolute;
  top: 50%;
  left: 65%;
  //transform: translate(-50%, -50%);
  z-index:1010;
  //transform: translateZ(1000px);//专门为safari设置
  transform: translate3d(-50%, -50%,1000px);
  • 微信内置浏览器设置绝对定位后,出现层级问题,z-index无效,经实践尝试,发现设置transform: translateZ(1000px)管用
  • 监听滑动到底部问题:png文件可以通过clientHeight + scrollTop >=scrollHeight来判断,但是对于html文件,采用iframe标签来加载,如加载内容跨源,则无法获取内容,就无法监听是否滑动到底部了(如果能解决跨源问题也是可以的)解决办法:换个思路,在iframe的下面添加一个同级元素,并设置height = 3px
//html:
<div class="img_parent" id="img_parent">
    <div id="iframePage" v-show="heTongType=='html'" style="width:100%;height:100%;overflow:auto;">
      <iframe id='linkedFrame' height='3500' width='100%' :src="hetongUrl[0]" frameborder='0' ></iframe>
      <div id='bottom-line' style="height:3px;width:100%"></div>
    </div>
    <div class="pdfImage" id="pdfImage" v-show="heTongType=='png'">
      <img  v-for="(item, index) in hetongUrl" :key="index" :src="item" class="imgHetong" :id="'imgHetong' + index" alt="" />
      <div id='bottom-line2' style="height:3px;width:100%"></div>
    </div>
  </div>
</div>
//js:
methods:{
	// 判断元素是否在可视
    isInViewPortOfTwo (el) {
      if(!el) return false;
      let domPdf = document.getElementsByClassName("img_parent")[0];
      const viewPortHeight = domPdf.innerHeight || domPdf.clientHeight || document.body.clientHeight;
      // 元素相对于视口的位置的位置
      const top = el.getBoundingClientRect() && el.getBoundingClientRect().top
      const left = el.getBoundingClientRect() && el.getBoundingClientRect().left
      if(this.isReverse){//isReverse是横竖屏的判断 true:竖屏  false:横屏
        return left >= 50 //底部高度
      }else{
        return top <= viewPortHeight+60
      }
    },
}
let domPdf = document.getElementsByClassName("img_parent")[0];
domPdf.addEventListener("touchmove", (e) => {
  let el
  if(this.heTongType=='html'){
    el = document.getElementById('bottom-line')
  }else if(this.heTongType=='png'){
    el = document.getElementById('bottom-line2')
  }
  this.isInView = this.isInViewPortOfTwo(el);
  console.log(this.isInView)
  if (this.isInView) {
    console.log("到底");
    this.isDisabledbtn = false; //到底时处理
  }
});

  • 在手机端浏览器,滑动屏幕触发的不是scoll事件,而是touchmove事件,当连续出示两个图片文件时,第二个文件就有可能不是从第一张图片开始出示的解决办法
document.getElementById("pdfImage").style.transform = "translateX(0px) translateY(0px) scale(1)"
  • 多端同步滚动问题:
//.events.js文件
import {EventEmitter} from 'events';//引入events模块
export default new EventEmitter();//导出
//.vue文件
mounted(){
 emitter.on('syncMove', (ev)=> { 
    let pHeight = document.getElementById("pdfImage").clientHeight
    let pWidth = document.getElementById("pdfImage").clientWidth
    let moveX = ev.moveX;
    let moveY = ev.moveY;
    let scale = ev.scale;
    let message = {
      pX:moveX/(pWidth*scale),
      pY:moveY/(pHeight*scale),
      scale:1,
    }
    let percent = Math.abs(-moveY-this.currentScroll)
    if(percent>=30){//每次滑动比例大于1%才发同步消息
      this.currentScroll=-moveY;
      //console.log(data,'data')
      this.sendEvent("DIY", {//发送socket消息,同步给其他端
        type:"SYNC_MOVE_EVENT",
        customerType:this.selfcustomerType,
        message:message
      });
    }
  });
},
methods:{
	 recordEventHandler(e) {
      console.log("自定义recordEventHandler", e.data);
      let isSelfMessage = e.data.data.customerType == this.selfcustomerType;
      if (this.sessionId == e.data.data.sessionId) {
        switch (e.data.data.type) {
          case "SYNC_MOVE_EVENT": //自定义消息
            if (!isSelfMessage) {
              let pHeight = document.getElementById("pdfImage").clientHeight;
              let pWidth = document.getElementById("pdfImage").clientWidth;
              if(this.heTongType == 'html'){
                let iframe = document.getElementById('iframePage');
                let linkedFrame = document.getElementById('linkedFrame');
                const scrollOption = {
                  top: -e.data.data.message.pY*linkedFrame.height,
                  left: 0,
                  behavior: "smooth",
                };
                this.$nextTick(() => {
                  iframe.scrollTo(scrollOption)
                })
              }else{
                //更新事件
                emitter.emit('touchEvent', {
                  scale:e.data.data.message.scale,
                  moveX:e.data.data.message.pX*pWidth,
                  moveY:e.data.data.message.pY*pHeight,
                });
              }
            }
            break;
          case "SYNC_HTML_SIZE_EVENT": //自定义消息
            let w = e.data.data.message.width;
            let h = e.data.data.message.height;
            let iframe = document.getElementById('iframePage');
            let linkedFrame = document.getElementById('linkedFrame');
            //收到客户端发过来的html页面高度,设置给iframe
            console.log(e.data.data.message,'SYNC_HEIGHT_EVENT')
            linkedFrame.height=h;
            // 监听iframe父元素的滚动事件
            console.log(this.isCurrentExecRole,'this.isCurrentExecRole')
            if(this.isCurrentExecRole){
              iframe.addEventListener("scroll", (e) => {
                console.log(iframe.scrollTop,'iframe.scrollTop');
                let percent = Math.abs(iframe.scrollTop-this.currentScroll)
                if(percent>=30){//每次滑动比例大于1%才发同步消息
                  this.currentScroll=iframe.scrollTop;
                  // 给服务端同步发送滚动高度
                  this.sendEvent("DIY", {
                    type:"SYNC_MOVE_EVENT",
                    customerType:this.selfcustomerType,
                    message:{
                      pX:0,pY:-iframe.scrollTop/h,scale:1
                    }
                  });
                }
                let el = document.getElementById('bottom-line')
                this.isInView = this.isInViewPortOfTwo(el);
                console.log(this.isInView)
                if (this.isInView) {
                  console.log("到底");
                  this.isDisabledbtn = false; //到底时处理
                }
              });
            }
            break;
        }
      }
    },
}


//utils/index.js文件
export function zoomElement(el, Reverse) {
  let isReverse = Reverse;
  function point2D(x, y) {
    return { x: x, y: y };
  }
  // 判断 正数,负数,不是数字
  function checkNumType(num) {
    var reg = new RegExp("^-?[0-9]*.?[0-9]*$");
    if (reg.test(num)) {
      // 用于检测一个字符串是否匹配某个模式
      var absVal = Math.abs(num); // 如果参数是非负数,则返回该参数;如果参数是负数,则返回该参数的相反数。
      return num == absVal ? true : false;
    } else {
      console.log("this is not number");
    }
  }
  function exChangeNum(num, reNum) {
    let flag = checkNumType(num);
    let reFlag = checkNumType(reNum);
    let realNum = 0;
    if (!flag && reFlag) {
      realNum = Number("-" + reNum);
    } else {
      realNum = Number(reNum);
    }
    return realNum;
  }
  var reqAnimationFrame = (function () {
    return (
      window[Hammer.prefixed(window, "requestAnimationFrame")] ||
      function (callback) {
        window.setTimeout(callback, 1000 / 60);
      }
    );
  })();
  var ticking = false;
  var tMatrix = [1, 0, 0, 1, 0, 0]; //x缩放,无,无,y缩放,x平移,y平移
  var initScale = 1; //初始化scale
  var mc = new Hammer.Manager(el);
  var nowScale = 0;
  var poscenter = point2D(0, 0); // 缓存双指的中心坐标
  var duration = ""; // 设置过渡效果,用于双击缩放效果
  var lastTranslate = point2D(0, 0); // 记录上次的偏移值
  var lastcenter = point2D(el.offsetWidth / 2, el.offsetHeight / 2); // 图像的中心点,用于对比双指中心点
  var center = lastcenter; // 初始化为图片中心点
  // 添加缩放事件
  mc.add(new Hammer.Pan({ threshold: 0, pointers: 1 }));
  mc.add(new Hammer.Pinch({ threshold: 0 }));
  mc.add(new Hammer.Tap({ event: "doubletap", taps: 2 }));
  mc.on("pinchstart", onPinchStart); // 双指缩放
  mc.on("pinchmove", onPinch); // 双指移动
  mc.on("panmove", onPan);
  mc.on("panstart", onPanStart);
  mc.on("doubletap", doubletap);
  function doubletap() {
    tMatrix[0]= tMatrix[3]=1;
    tMatrix[4]= tMatrix[5]=0;
    console.log("双击");
    nowScale = 1;
    requestElementUpdate("onpan");
    // el.style.transform = "translateX(0px) translateY(0px) scale(1)";
  }
  // 缩放开始
  function onPinchStart(ev) {
    duration = "";
    lastTranslate = point2D(tMatrix[4], tMatrix[5]); //记录上一次的偏移值 0 0
    initScale = tMatrix[0] || 1;
    // 手势中心点
    poscenter = point2D(ev.center.x, ev.center.y);
    // 图像中心点  = 初始化图像中心点  + 上一次偏移量的中心点
    lastcenter = point2D(
      center.x + lastTranslate.x,
      center.y + lastTranslate.y
    ); //重新计算放大后的中心坐标
    // 手势中心点 = 缩放中心点 - 图像中心点
    poscenter = point2D(ev.center.x - lastcenter.x, ev.center.y - lastcenter.y);
    requestElementUpdate("onpinchStart");
  }
  // 缩放途中
  function onPinch(ev) {
    // 缩放倍数 这里的缩放倍数
    nowScale = initScale * ev.scale;
    // 如果倍数小于1 则等于1
    if (nowScale <= 1) {
      nowScale = 1;//当倍数小于等于1时,不在进行缩放操作
      return
    }
    if (nowScale >= 3) {
      nowScale = 3;
    }
    
    // 缩放倍数
    tMatrix[0] = tMatrix[3] = nowScale;
    let x = Number((1 - ev.scale) * poscenter.x + lastTranslate.x);
    let y = Number((1 - ev.scale) * poscenter.y + lastTranslate.y);
    let tempPosX =
      el.getBoundingClientRect().width / 2 -
      point2D(el.offsetWidth / 2, el.offsetHeight / 2).x;
    let tempPosY =
      el.getBoundingClientRect().height / 2 -
      point2D(el.offsetWidth / 2, el.offsetHeight / 2).y;
    if (Math.abs(x) > Math.abs(tempPosX)) {
      x = exChangeNum(x, tempPosX);
    }

    if (Math.abs(y) > Math.abs(tempPosY)) {
      y = exChangeNum(y, tempPosY);
    }
    tMatrix[4] = x;
    tMatrix[5] = y;
    
    requestElementUpdate("onpinch");
  }
  // 开始拖动
  function onPanStart() {
    lastTranslate = point2D(tMatrix[4], tMatrix[5]); // 缓存上一次的偏移值
  }
  // 拖动过程
  function onPan(ev) {
    // console.log(ev,'ev')
    tMatrix[0] = tMatrix[3] = nowScale || initScale;
    // 拖动的动画 1.6
    duration = "1.6";
    // console.log(ev, ev.deltaX, ev.deltaY);
    let x = Number(lastTranslate.x + ev.deltaX);
    let y = Number(lastTranslate.y + ev.deltaY);
    if (isReverse) {
      x = Number(lastTranslate.x + ev.deltaY);
      y = Number(lastTranslate.y - ev.deltaX);
    }

    let parentDiv = document.getElementsByClassName("img_parent")[0];
    let scale = nowScale || initScale;
    let elWidth = el.offsetWidth;
    let elHeight = el.offsetHeight;
    let xLBorder = (elWidth * scale) / 2 - elWidth / 2;
    let xRBorder = (elWidth * scale) / 2 - parentDiv.offsetWidth + elWidth / 2;
    let yTopBorder = (elHeight * scale) / 2 - elHeight / 2; // 缩放后的高的一半,减去缩放前的高的一半
    // 缩放后的高的一半,加上缩放前的高的一半,减去容器高度
    let yBottomBorder =
      (elHeight * scale) / 2 - parentDiv.offsetHeight + elHeight / 2;

    if (x <= -xLBorder) {
      //左右边界限定
      x = -xLBorder;
    } else if (x >= xRBorder) {
      //元素在最右边时的判定,屏幕的宽度减去元素自身的宽度
      x = xRBorder;
    }
    if (y <= -yBottomBorder) {
      //上下边界限定
      y = -yBottomBorder;
    } else if (y >= yTopBorder) {
      //元素在最下边时的判定,屏幕的高度减去元素自身的高度
      y = yTopBorder;
    }
    tMatrix[4] = x;
    tMatrix[5] = y;
    requestElementUpdate("onpan");
  }
  // 每次都会·更新 因为是在移动端 所以都采用rem 否则可以直接用matrix
  function updateElementTransform() {
    el.style.transition = duration;
    var tmp = tMatrix.join(",");
    el.style.transform = "matrix(" + tmp + ")";
    el.style.WebkitTransform = "matrix(" + tmp + ")";
    el.style.msTransform = "matrix(" + tmp + ")";
    ticking = false;
  }
  function requestElementUpdate() {
    //更新事件
    emitter.emit('syncMove', {
      scale:tMatrix[3],
      moveX:tMatrix[4],
      moveY:tMatrix[5],
    }); 
    if (!ticking) {
      reqAnimationFrame(updateElementTransform);
      ticking = true;
    }
  }
  /**
  初始化设置
  */

  requestElementUpdate();
  //监听收到的消息,并处理
  emitter.on('touchEvent', (e)=> { 
    console.log(e,'eeeeeeeeeeeeeeee')
    tMatrix[0] = tMatrix[3] = e.scale //缩放比例
    tMatrix[4] = e.moveX; //移动位置
    tMatrix[5] = e.moveY; //移动位置
    //处理参数
    reqAnimationFrame(updateElementTransform);
  }); 
}

  • Flex布局
    display:flex布局,
    问题:父元素设置了display:flex等布局,子元素设置了flex:1但是实际结果:子元素并不是等分的,
    解决办法:给子元素设置width:0或min-width:0
  • safari浏览器的弹弹乐问题,滚动到最上面或者最下面就无法滑动,再次滚动就可以滑动了
    解决办法:暂无,待补充
  • css的border
    问题场景:给元素设置做边框,并且为虚线样式,发现safari浏览器浏览时边框不显示,其他浏览器正常
    写法:border:2px dashed red
    解决办法:
    换一种设置元素边框的方式,代码如下:
.line{
  flex:1;
  border: 2px solid #000;
  // border: 2px dashed #384785;
  border-image-source: url('./../../assets/selfLine_2x.png');//引用图像的路径
  border-image-slice: 1;//指定图像的边界向内偏移
  border-width: 0;
  border-left-width:1px;//边框的宽度
  border-image-repeat: repeat;//根据需要还可设置为repeat、round
}
  • 两个元素分别占30%,70%的屏幕宽度,但是中间会留白,(很窄的一条)
    解决办法:
    把其中一个的宽设的多一点,比如:30.01%

  • ios微信浏览器底部小箭头:
    解决办法:
    将路由跳转的方式由push改成replace,
    注:如果页面中有使用iframe嵌套H5文件的,会导致再次出现小箭头,甚至可能遮挡页面内容,解决办法:给iframe添加key属性,用来唯一标识,

<iframe id='linkedFrame' :key="hetongUrl[0]" height='3500' width='100%' :src="hetongUrl[0]" frameborder='0' ></iframe>
  • <>van-filed或el-input只允许输入英文和数字时,当输入中文,个别ios手机浏览器输入框会有阴影出现,现象如下图所示:
    在这里插入图片描述

解决办法:
设置字体颜色为透明或者白色,并设置透明度opacity:0
ps:如果要调整input输入框中文字的间距,可设置letter-spacing:10px,大小可根据实际距离来设置

  • 手动改变一个可滑动元素的scrollTop,不会触发scroll事件
window.addEventListener('scroll',()=>{
	//如果手动改变了scrollTop,不会进入此循环
})
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值