H5问题记录

132 阅读5分钟

图片禁用长按保存属性 pointer-events: none;

juejin.cn/post/690940…

可以采用第一种 给img全局设置属性,然后那些在img上绑定事件处理的可以在外面包一层div把handle 提到父级,然后那些需要分享的只需要加个class即可

// 分享页可保存
  .able-save {
    pointer-events: auto;
  }
  // 长按图片禁止保存
  img {
    pointer-events: none;
  }
复制代码
// 长按图片禁止保存
  .disable-save {
    pointer-events: none;
  }
复制代码

css实现宇宙同心圆动态


  // 宇宙背景动画
  .round1 {
    height: 10rem;
    width:10rem;
    border:1px solid rgba(255,255,255,0.13);
    border-radius:50%;
    position:absolute;
    top: 10%;
    left:-50%;
    animation:rotate1 16s linear infinite;
  }

  // keyframes值为animation值的第一项
  @keyframes rotate1 {
    0% {transform : rotate(0deg);}
    100% {transform : rotate(360deg);}
  }

  .round1-child {
    height:10px;
    width:10px;
    position:absolute;
    background-color:#999999;
    border-radius:50%;
    top:3.9rem;
  }
  
  <div className="round1">
        <div className="round1-child" />
  </div>
复制代码

query带有特殊字符的参数

一定要先encodeURIComponent 再# decodeURIComponent 否则会造成参数丢失拿不到 比如+这样的字符

ios手机左上角返回按钮触发后H5页面没有重新加载问题

解决办法:在上一页useEffect中添加

window.addEventListener('pageshow', event => {
   if (event.persisted) {
      location.reload()
   }
})
复制代码

即可实现页面刷新

juejin.cn/post/684490…

Jsbridge

/* eslint-disable no-unused-ex
// eslint-disable-next-line import/no-mutable-exports

const isAndroid = /android/.test(navigator.userAgent.toLowerCase())
const isiOS = /ios|iphone|ipad|ipod/.test(navigator.userAgent.toLowerCase())
const successCode = 1

/**
  * initJSBridge 初始化
  * @param {*} callback
  * @returns
  */
export function initJSBridge(callback) {
  if (isAndroid) {
    if (window.WebViewJavascriptBridge) {
      callback(window.WebViewJavascriptBridge)
    } else {
      document.addEventListener(
        'WebViewJavascriptBridgeReady',
        () => {
          callback(window.WebViewJavascriptBridge)
        },
        false,
      )
    }
  } else if (isiOS) {
    if (window.WebViewJavascriptBridge) {
      return callback(window.WebViewJavascriptBridge)
    }
    if (window.WVJBCallbacks) {
      return window.WVJBCallbacks.push(callback)
    }
    window.WVJBCallbacks = [callback]
    const WVJBIframe = document.createElement('iframe')
    WVJBIframe.style.display = 'none'
    WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__'
    document.documentElement.appendChild(WVJBIframe)
    setTimeout(() => {
      document.documentElement.removeChild(WVJBIframe)
    }, 0)
  }
}

/**
  * 仅供安卓初始化
  * @param {*} bridge
  */
export function androidInit(bridge) {
  window.JSBridge = bridge
  if (isAndroid) {
    window.JSBridge.init((message, responseCallback) => {
      const data = { 'Javascript Responds': message }
      if (responseCallback) {
        responseCallback(data)
      }
    })
  }
}

/**
  * 注册方法
  * @param {*} typeArr 多种注册类型
  * @param {*} fn 回调使用
  * @param {*} openShare 仅供安卓使用
  * openShare:{
  *    title
  *    shareImg
  *    shareUrl
  *    shareDes
  *    shareType
  * }
  */
export function registerHandler(typeArr, fn, openShare) {
  window.JSBridge.registerHandler('nativeToJs', message => {
    if (message) {
      // 直接获取newMsg, 如贴片
      const newMsg = JSON.parse(message)
      if (!typeArr) {
        fn(newMsg)
        return
      }
      // 安卓注册初始化、设置头部、右上角分享、头部事件配置、页面前后台切换等
      if (Array.isArray(typeArr)) {
        typeArr.forEach(item => {
          if (newMsg.optionType === 'onInit' && isAndroid && openShare) {
            // 安卓使用jsbridge,必须重新接收右上角...分享功能
            window.JSBridge.call('setHeadMenu', {
              rightOption: [{
                optionType: 'h5HandleShare',
              }],
            }, () => { })
          } else if (newMsg.optionType === item) {
            if (openShare && isAndroid) {
              // 安卓使用jsbridge,必须重新接收右上角...分享功能
              const newShareConfig = {}
              newShareConfig.title = openShare.title
              newShareConfig.imgUrl = openShare.shareImg
              newShareConfig.shareUrl = openShare.shareUrl
              newShareConfig.description = openShare.shareDes
              newShareConfig.shareType = openShare.shareType || 0
              window.JSBridge.call('openShare', newShareConfig, () => { })
            } else {
              fn(item)
            }
          }
        })
      }
    }
  })
}

/**
  * 保存图片至相册
  * @param {*} imgUrl
  * @param {*} Toast
  * @param {*} toastConfig
  * @returns
  */
export async function JSBSaveImage(imgUrl, Toast, toastConfig) {
  if (!imgUrl) {
    Toast.fail(toastConfig ? toastConfig.fail : '保存失败')
    return
  }
  Toast.loading(`${toastConfig ? toastConfig.loading : '保存中...'}`, 0)
  if (window.BluedJSBridge) {
    window.BluedJSBridge.call('saveImage', {
      imgUrl,
    }, res => {
      if (res) {
        Toast.hide()
        const newData = JSON.parse(res)
        if (newData.code === successCode) {
          Toast.success(toastConfig ? toastConfig.success : '保存成功')
        } else {
          Toast.fail(toastConfig ? toastConfig.fail : '保存失败')
        }
      } else {
        console.log('\n[🍒JSBLOG] ——> 🌻🙏🌻 JSBSaveImage error 👉', res)
      }
    })
  }
}





import { initJSBridge, androidInit, registerHandler } from '@utils/jsbridge'

const { env, shareConfig } = window.CONFIG

useEffect(() => {
  // ================= 引用jsbridge开始 ===================
  if (env === 'native') {
    initJSBridge(bridge => {
      androidInit(bridge)

      // 需要setHeadMenu头部 可以在此位置写,不需要可不写。
      // 比如 BluedJSBridge.call('setHeadMenu', {}) 具体用法参看下面step2


      const typeArr = ['onInit', 'h5HandleShare'] //registerHandler使用
      registerHandler(typeArr, (res) => {
        // tips: 此处也可以setHeadMenu头部,只是只有iOS生效,安卓不生效

        // do something 自定义逻辑

      }, shareConfig) // shareConfig,安卓重新配置右上角...分享使用,不使用可不传
    })
  }
}, [])

网页分享微信配置经验记录

一、问题介绍

  1. 从端内App分享H5网页到微信,再从微信进行二次分享,出现如下图非理想状态的卡片:
  2. 从微信进行二次分享,应出现如下图理想状态的卡片:

二、原因分析 因迁移至腾讯云,导致H5链接的出口IP,未配置到公众号管理后台IP白名单,导致获取微信分享access_token失败,影响到微信的二次分享。

三、解决方案

  1. 配置IP白名单: 登录您授权的公众号管理后台(mp.weixin.qq.com),在左侧导航下拉到最底找到【开发-基本配置】,点击IP白名单【配置】。
  2. 在IP白名单配置框里,输入如下两个IP地址,点击确认修改即可。(注:多个IP地址需用回车隔开)

upload组件视频上传显示为音频解决方案

问题描述 upload上传MP4视频,页面展示为音频播放器,并且仅能播放声音,没有画面显示,如图

问题原因

MP4有三种编码方式,分别为:mpg4(xdiv),mpg4(xvid),avc(h264/h265) H5 标签仅提供了一种解码器:h.264 解码

其他平台需要查看依赖包提供的解码器种类 

问题定位 - 需要获取问题视频的 原视频 ,获取原视频时 不要 使用微信,飞书等聊天工具直接传输,建议压缩包传输(直接传输,部分聊天工具为了可以正常播放,会进行有损转码) - 查看原视频文件后缀是否为 .mp4 - 查看原视频是否可以在本机播放器中正常播放

以上情况均符合的情况下,大概率是视频编码问题,查看视频编码方式如下 
mac: 右键视频文件 -> 显示简介 

Linux & windows 目前没有直接显示方案,只能借助 vlc 播放器 或 ffmpeg 进行查看 

#ffmpeg 查看命令 
ffmpeg -i [videoPath]/[videoName] 
#例如 
ffmpeg -i C:\Users\Admin\Desktop\video.mp4 

如 Stream 或 encoder 字段显示的不是 h264 编码,例如 
则可以确定是视频编码问题,通知业务方或自行转码。转码方式可以使用格式工厂,或直接使用 ffmpeg 

#ffmpeg 视频转码命令 
ffmpeg -i [videoPath] -vcodec h264 -preset fast -b:v 2000k [outputPath] 
#例如 
ffmpeg -i Downloads/video.mp4 -vcodec h264 -preset fast -b:v 2000k Downloads/output.mp4 
# -preset: 清晰度参数,从左到右清晰度依次增加,转码速度依次降低 
# ultrafast、superfast、veryfast、faster、fast、medium、slow、slower、veryslow 

目前 js 层面不支持视频/音频文件解码器类型判断,也不支持音视频转码操作,如有音视频编解码方式判断需求,需要使用 nodejs 调用 ffmpeg 库进行操作,不建议在当前业务场景中使用




使用html2canvas的躲坑经验

  1. 图片跨域问题 useCORS:true,allowTaint:false

    若同时设置为 allowTaint: true ,会认为画布已被污染而不可用。在IphoneSE手机上会走不进去html2canvas的then方法。

  2. 图片显示半截或者图片无法显示问题

  • 截取部分尽量少用或者不用absolute定位。

  • 图片全部加载完成后,再调用生成图片方法。

  • 适当加延迟再调用html2canvas。

  • UI给的图要求不能过大.我的活动400多k就会有问题。

    后续: html2canvas大家使用过程中遇到奇怪的问题,也可以从issue里面翻翻解决办法~附上地址:github.com/niklasvh/ht…