- 子元素使用了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,不会进入此循环
})