一、微信自定义分享
1、问题:微信和浏览器间如何分享?
解决办法:首先,需要下载weixin-js-sdk库,并在分享文件中使用。在分享文件里面修改所需要的标题、图片、链接等信息,并引入到每个页面中。然后还需要在微信公众号平台配置网站链接等信息,这样就实现了微信内的分享。至于从浏览器分享到微信,则需要在index.html中配置名字、描述信息、网址、图片等meta头才可以实现。
代码:
//放在index.html里面(图片无效) <meta property="og:type" content="website" /> <meta name="title" content="为爱撑伞 一起防艾" /> <meta name="description" content="防艾大有爱!百度营销携手杰士邦带你开启防艾旅途" /> <meta name="url" content="https://jieshibang.jdpes.cn/h5/#/" /> <meta name="image" content="https://jieshibang.jdpes.cn/h5/static/share_icon.jpg" />
//放在utils文件夹里面 import wx from "weixin-js-sdk"; function weixinSDK() { let url = location.href.split("#")[0]; let title = "为爱撑伞 一起防艾"; let desc = "防艾大有爱!百度营销携手杰士邦带你开启防艾旅途"; let link = "https://jieshibang.jdpes.cn/h5/#/"; let imgUrl = "https://jieshibang.jdpes.cn/h5/static/share_icon.jpg"; uni.request({ url: "https://chunfeng.jdpes.cn/Wxshare/share", method: "POST", data: { url: url } }).then((e) => { const [err, data] = e; if (err) { //请求失败 } let response = data.data.data; // console.log(e); const config = { debug: false, appId: "wx79d2a8497dfd2a3c", // APPID timestamp: response.timestamp, // 上面main方法中拿到的时间戳timestamp nonceStr: response.nonceStr, // 上面main方法中拿到的随机数nonceStr signature: response.signature, // 上面main方法中拿到的签名signature jsApiList: [ "updateAppMessageShareData", "updateTimelineShareData", ], }; // console.log("config:::::::", config); wx.config(config); // ready wx.ready(function() { // 需在用户可能点击分享按钮前就先调用 // console.log("ready.............................................."); // 自定义“分享给朋友”及“分享到QQ”按钮的分享内容 wx.updateAppMessageShareData({ title: title, desc: desc, link: link, imgUrl: imgUrl, success: function() { console.log("设置成功"); }, }); // 自定义“分享到朋友圈”及“分享到QQ空间”按钮的分享内容 wx.updateTimelineShareData({ title: desc, desc: desc, link: link, imgUrl: imgUrl, success: function() { console.log("设置成功"); }, }); }); wx.error(function(err) { // alert(JSON.stringify(err)) console.log("出错啦!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", err); }); }); } export default weixinSDK;
2、问题:浏览器分享到微信时,在index.html中配置图片没有生效,分享链接不存在图片?
解决办法:给每个页面顶部设置一个1px的图片,浏览器就自动获取到首页第一个元素的图片,从而解决问题。
代码:
//给每个页面顶部设置一个1px的图片 <img class="share_icon" src="@/static/share_icon.jpg" /> .share_icon { width: 1px; height: 1px; }
二、移动端视频播放
1、问题一:因为百度等浏览器会挟持原生video标签,给它设置默认的、无法更改的样式和功能等,如果有别的需求的话,没办法改变video标签,因此需要使用一些不同的办法在微信内置浏览器、百度等其他浏览器上实现自定义视频样式的播放?
解决办法 :目前使用了三种办法来播放视频,分别针对微信内置浏览器(不分ios和android)、ios系统下的其他浏览器和安卓系统下的其他浏览器。
1、微信内置浏览器
微信浏览器可以直接使用video标签来播放视频,ios端和安卓端都可以适配。主要是通过微信内置的h5同层播放器来拜托浏览器对video标签的挟持,从而实现自定义video标签。代码如下:
<video class="video" poster="@/static/poster.jpg" :enable-progress-gesture="false" @ended="next" preload :controls="false" x-webkit-airplay="allow" :show-center-play-btn="false" x5-video-player-type="h5" x5-playsinline webkit-playsinline playsinline :src="videoSource" type="video/mp4">
2、ios系统
ios系统下的其他浏览器,需要使用canvas来不断绘制出video视频,再放到页面中去,这样就可以避免video标签被浏览器挟持的问题。
代码:
//ios设置视频的方法 iosPlay() { //创建Video标签 this.video = document.createElement('video'); this.video.src = 'https://jieshibang.oss-accelerate.aliyuncs.com/wait.mp4'; const container = document.getElementsByClassName("container"); this.canvas = document.createElement("canvas"); container[0].appendChild(this.canvas); // 初始化(创建)canvas if (this.canvas.getContext) { this.ctx = this.canvas.getContext('2d'); } this.video.width = 750; this.video.height = 1624; // 设置canvas的宽度,这个设置的越大,画面越清晰,最好是视频大小(相当于绘制的图像大,然后被css缩小) this.canvas.width = 750; this.canvas.height = 1624; //设置canvas宽高 this.canvas.style.width = '100vw'; this.canvas.style.height = 'auto'; this.render(); this.video.addEventListener('play', this.playCallBack); }, // 绘制视频 render() { //隐藏填充白屏的背景图 this.hidden(); //填充ios黑屏的背景 this.ctx.fillStyle = '#0fb1df'; // 绘制背景 this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); this.ctx.drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height); if (this.video.paused) { this.video.play() } else { this.video.pause() } }, playCallBack() { if (this.video.paused) { return; } this.ctx.drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height); setTimeout(this.playCallBack, 16.7); },
3、安卓系统
安卓端播放视频需要使用jsmpeg.min.js这个库来实现,引入这个库之后,需要把视频的地址和canvas标签赋给实例,然后再配置一些需要的参数(如:自动播放、结束时跳转的方法等等),需要注意的是,视频的地址需要和项目的地址是同源的,不然会产生跨域的问题,这是由JSMpeg内部的请求导致的,没办法改变。
代码:
androidPlay() { //这里必须使用同一个域名下的视频文件,不然会跨域,这是由JSMpeg内部的请求导致的 const url = "https://jieshibang.jdpes.cn/video/wait.ts"; const container = document.getElementsByClassName("container"); this.canvas = document.createElement("canvas"); container[0].appendChild(this.canvas); // 设置canvas的宽度,这个设置的越大,画面越清晰,最好是视频大小(相当于绘制的图像大,然后被css缩小) this.canvas.width = 750; this.canvas.height = 1624; //设置canvas宽高、裁剪视频,避免拉伸 this.canvas.style.width = "100vw"; this.canvas.style.height = "auto"; this.player = new JSMpeg.Player(url, { canvas: this.canvas, loop: false, autoplay: true, disableGl: false, onEnded: () => { this.next(); //视频结束时跳转 }, }); },
2、问题二:在视频开始播放时出现了短暂黑屏的现象?
解决办法:当第一次播放视频的时候ios端,如果网络慢,视频从开始播到能展现画面会有短暂的黑屏(处理视频源数据的时间),为了避免这个黑屏,可以在视频上加个div浮层(可以是视频的第一帧),然后用timeupdate方法监听,视频播放及有画面的时候再移除浮层。
代码:
this.videoNode.addEventListener('timeupdate', () => { // 当视频的currentTime大于0.1时表示黑屏时间已过,已有视频画面,可以移除浮层 if (this.videoNode.currentTime > 0.1 && !this.playing) { this.playing = true } }, false)
3、问题三:视频自动播放?
解决办法:在微信浏览器端,android始终不能自动播放;ios的话,微信提供了一个事件WeixinJSBridgeReady,在微信嵌入webview全局的这个事件触发后,视频仍可以自动播放,这个应该是现在在ios端微信的视频自动播放的比较靠谱的方式,至于其他浏览器,建议引导用户去触屏的行为操作比较好(比如添加一个按钮立即播放,引导用户点击操作)。
4、问题四:视频变形的问题?
解决办法:在设置好视频的大小和canvans的大小之后,为避免不同手机出现视频拉伸变形的现象。可以使用object-fit: cover,它可以对视频进行裁剪,解决拉伸问题。object-fit属性可以解决视频出现上下黑边,不能全屏的问题。
三、预加载
问题:h5资源(图片、音频、视频)太多,加载速度慢,进入每个页面时会有白屏卡顿的现象?
解决办法:封装一个方法,在里面使用link元素,把传入的资源和类型赋给link,利用link的预加载属性来实现资源的预加载。
代码:
preloadMedia('https://jieshibang.oss-accelerate.aliyuncs.com/wait.mp4', 'video'); preloadMedia('https://jieshibang.oss-accelerate.aliyuncs.com/bg_home.jpg', 'image'); preloadMedia('https://jieshibang.oss-accelerate.aliyuncs.com/bg_music.mp3', 'audio'); const preloadMedia = (url, type) => { var link = document.createElement('link'); // link.rel = 'preload'; link.rel = 'prefetch'; link.href = url; link.as = type; link.crossorigin = "anonymous"; // console.log(link.href); document.head.appendChild(link); } export default preloadMedia
四、rem适配的问题
问题:在使用rem适配方案时,ios和安卓在微信端的字体样式会产生差异 ?
解决办法:通过判断手机类型来改变字体样式。
代码:
isAndroid() { //判断手机类型改变按钮样式 let u = navigator.userAgent; if (u.indexOf("Android") > -1 || u.indexOf("Linux") > -1) { // console.log("安卓"); var ua = u.toLowerCase(); if (ua.match(/MicroMessenger/i) == 'micromessenger') { //安卓微信端 const showNum = document.getElementsByClassName("showNum"); const lastThank = document.getElementsByClassName("lastThank"); const save = document.getElementsByClassName("save"); showNum[0].style.fontSize = "12px"; lastThank[0].style.fontSize = '11px'; lastThank[0].style.paddingTop = '13rem'; save[0].style.fontSize = '10px'; save[0].style.paddingTop = '20rem'; } const share_button = document.getElementsByClassName("share_button"); share_button[0].style.height = "110rem"; } }
五、音频播放
问题:在播放背景音乐时,因为浏览器的限制无法自动播放,并且需要在离开页面时停止播放音乐,进入页面时播放音乐?
解决办法:下载howler插件,在需要播放的页面下,onLoad中使用,onHide时暂停播放,onShow时播放(在uniapp中开发)。在微信浏览器下,音频资源 load 之后通过微信桥接触发播放;在其他浏览器下通过play()播放。
代码:
// Web Audio 初始化 <script> onLoad() { this.soundBgm = new Howl({ src: [assetsBgm],//音频地址 loop: true, preload: true, }) // 音频资源 load 之后通过微信桥接触发播放 this.soundBgm.on('load', () => { //判断是否在微信浏览器(已封装) const iswx = isWx() if (iswx) { try { window.WeixinJSBridge.invoke('getNetworkType', {}, () => { this.soundBgm.play(); }, false); } catch (e) { // alert('error' + e.message) this.soundBgm.play(); } } else { this.soundBgm.play(); } }) }, onShow: function() { this.soundBgm?.stop(); this.soundBgm?.play(); }, onHide: function() { this.soundBgm?.stop(); }, </script>
六、弹幕
问题:如何让弹幕在屏幕上移动,但是不能重复,并且无限循环?
解决办法:主要就是通过使用animation,让文字在屏幕从0移动到100的宽度,先把所有的弹幕放在一个等待的数组里面,从数组取出第一个弹幕,然后让每条弹幕跟上一个弹幕的弹道错开(+1),再不断的放到显示的数组里面,当动画执行完成之后清空数组。
代码:
showNextBullet() { if (!this.waitBullets.length) { return; } // 先确定弹道,跟上一个弹道错开即可 this.currentLine = (this.currentLine % this.lines) + 1; // 从等待集合里取出第一个 const currentBullet = this.newlist.shift(); // 想要无限循环的话 this.isInfinite && this.newlist.push({ id: +currentBullet.id + getUUID(), label: currentBullet.label, line: 0 }); // 设置弹幕的弹道 currentBullet.line = this.currentLine; // 弹幕放进显示集合里,弹幕开始滚动 this.showingBullets.push(currentBullet); }, pxoveBullet(e) { this.showingBullets.shift(); }
七、生成海报
1、问题:如何把页面的dom结构转换成一张海报?
解决办法:通过引入html2canvas这个库,使用它的方法,先获取需要生成海报的dom节点,然后放入html2canvas(dom,{})这个方法中,然后再设置宽高、跨域等配置项,最后会生成一个在线的链接,放入页面中即可。
代码:
html2base64() { const dom = document.getElementById('osmdContainer'); html2canvas(dom, { width: dom.offsetWidth, height: dom.offsetHeight, dpi: 300, scale: 3, useCORS: true, }).then((canvas) => { this.base64Url = canvas.toDataURL("image/png", 1.0); }); },
2、注意:如果需要给生成的海报图片设置边框,需要使用内边框。因为生成海报的时候是按照dom元素的大小生成的,所以海报不能设置圆角,不然会有白边。
八、限制体验次数
问题:如何让每个人只能体验一次h5生成AI照片?
解决办法:使用localStorage存储生成的图片链接,然后在每个页面尝试取出图片链接,如果值为null,说明是第一次访问,就让用户跳转到首页去;如果值存在的话,就直接让用户跳转到结果页,直接查看图片即可。