1. 整体技术计划的设计
1. 目录构造
├──vv-musiclive-v
│ └── templates
│ ├── article.html 文章末级页 pc
│ ├── article_h5.html 文章末级页 h5
│ ├── error
│ │ ├── 404_h5.htm h5 报错页
│ │ └── 404.htm pc 报错页
│ ├── hot
│ │ └── hot_category V 篇举荐页
│ ├── include
│ │ ├── article 文章(pc)
│ │ │ ├──ad.htm 广告图模块
│ │ │ ├──admire.htm 赞叹模块
│ │ │ ├──bottomShare.htm 底部分享模块
│ │ │ ├──comment.htm 评论模块
│ │ │ ├──content.htm v 篇内容
│ │ │ ├──detail_1.htm 文章详情一信息(浏览,点赞,评论,分享等)│ │ │ ├──detail.htm 文章详情信息(浏览,点赞,评论,分享等)│ │ │ ├──download.htm 下载弹框
│ │ │ ├──errorRight.htm 报错页右侧
│ │ │ ├──fixedShare.htm 分享模块(端内)│ │ │ ├──likeList.htm 点赞列表
│ │ │ ├──musicBg.htm 背景音乐
│ │ │ ├──rightList.htm v 篇右侧
│ │ │ ├──title.htm 文章题目
│ │ │ ├──user_img.htm 用户头像
│ │ │ ├──web_code 返回顶部和下载二维码
│ │ │ └──webShare.htm 分享模块(端外)│ │ ├── article_h5 文章(h5)
│ │ │ ├──admire.htm 赞叹模块
│ │ │ ├──ads.htm 广告模块(微信、qq/ 其余浏览器)│ │ │ ├──articleAll.htm 评论模块
│ │ │ ├──comment_like.htm 评论点赞动画
│ │ │ ├──comment_w.htm 评论模块(微信)│ │ │ ├──comment.htm 评论模块 (端内、qq/ 其余浏览器)
│ │ │ ├──content.htm 文章内容(文本、图片、音频、视频、作品、文章)
│ │ │ ├──detail_1.htm 文章详情信息 1(浏览,点赞,评论,分享等)│ │ │ ├──detail.htm 文章详情信息(浏览,点赞,评论,分享等)│ │ │ ├──down.htm 固定下载(微信、qq/ 其余浏览器)│ │ │ ├──like.htm 点赞信息
│ │ │ ├──more_article.htm 举荐视频、举荐文章
│ │ │ ├──music_bg.htm 背景音乐
│ │ │ ├──qrcode.htm 二维码(生成长图性能应用)
│ │ │ ├──red_packet.htm 红包(端内)
│ │ │ ├──share.htm 分享(端内)
│ │ │ ├──user_img.htm 用户头像
│ │ │ ├──user_info.htm 用户信息
│ │ │ ├──verify.htm 手机号验证(微信)│ │ │ └──title.htm 文章题目
│ │ ├── footer
│ │ │ └──footer.htm 端外页脚
│ │ ├── header
│ │ │ └──header.htm 端外头部
│ │ └── theme V 篇模板
│ │ ├──m 挪动端 1.includ 引入须要的模模块(题目等) 2.style 标签中批改款式 3.script 标签中增加 js
│ │ │ ├── default.htm 规范模板 templateCode 值为 theme0
│ │ │ ├── theme1.htm 模板一 theme1 和模板返回的值 templateCode 的值保持一致
│ │ │ ├── ···
│ │ │ └── theme26.htm 模板
│ │ ├──pc pc 端(和挪动统一)│ │ └──style.htm 模板款式 conf 对象
│ ├── user_center
│ │ └──user_center.htm
│ ├── article.html 文章末级页 pc
│ └── article_h5.html 文章末级页 h5
2. 模板、配色
(1)模板(现有 20 种不同的模板类型)
//article_html
<#if (template?? && (template.templateCode!'')=='theme0' )>
<#include "/include/theme/m/default.htm" />
<#elseif (template?? && (template.conf??) && ((template.templateCode!'')!='' ))>
<#include "/include/theme/m/${template.templateCode}.htm" />
<#else>
<#include "/include/theme/m/default.htm" />
</#if>
// 模板文件 theme2.htm
<div class="article_content">
<!-- 背景音乐 -->
<#include "/include/article_h5/music_bg.htm" />
<!-- 文章题目 -->
<#include "/include/article_h5/title.htm" />
<!-- 文章信息 -->
<#include "/include/article_h5/detail.htm" />
<!-- 文章内容 -->
<#include "/include/article_h5/content.htm" />
</div>
配色
conf: {
imgPath: {
pc: '', //PC 端图片资源门路
m: '' // 挪动端图片资源门路
},
backGround: {
top: '', // 内容区距页面顶部的高度 px(头图高度)color: '', // 背景平铺色
repeat: '', // 背景中图平铺
inner: '', // 内容区域背景色,如果色彩有通明成果,请应用 rgba(233, 80, 58, 0.7)色值
},
audio: {
text: '', // 音频播放器文字
border: '', // 音频播放器边框色值
background: '', // 音频播放器背景色
},
fontColor: {
title: '', // 题目
anchor: '', // 作者
time: '', // 工夫
preview: '', // 浏览次数
link: '', // 文章超链接色值
statement: '', // 特地申明色值
colorA: '', // A 对应色值,默认彩色 && 编辑器第 1 色值
colorB: '', // B 对应色值,编辑器第 2 色值
colorC: '', // C 对应色值,编辑器第 3 色值
colorD: '', // D 对应色值,编辑器第 4 色值
colorE: '', // E 对应色值,编辑器第 5 色值
colorF: '', // F 对应色值,编辑器第 6 色值
colorG: '', // G 对应色值,编辑器第 7 色值
}
}
<style>
font[color="#000000"]{color: ${template.conf.fontColor.colorA!'#000000'};
}
font[color="#808080"]{color: ${template.conf.fontColor.colorB!'#808080'};
}
font[color="#ff0000"]{color: ${template.conf.fontColor.colorC!'#ff0000'};
}
font[color="#ff8300"]{color: ${template.conf.fontColor.colorD!'#ff8300'};
}
font[color="#00b937"]{color: ${template.conf.fontColor.colorE!'#00b937'};
}
font[color="#007dff"]{color: ${template.conf.fontColor.colorF!'#007dff'};
}
font[color="#bb69c0"]{color: ${template.conf.fontColor.colorG!'#bb69c0'};
}
.article{
position: relative;
width: 100%;
background: url(${template.conf.imgPath.m!''}contentbg.jpg) repeat center 0 ${template.conf.backGround.color!'#ffffff'};
background-size: 100% auto;
}
.article-bg{
width: 100%;
background: url(${template.conf.imgPath.m!''}themebg.jpg) no-repeat center 0;
background-size: 100% auto;
}
.title_wrap .article_title{color: ${template.conf.fontColor.title!'#222222'};
}
.article .detail_wrap .article_writer{
float: left;
color: ${template.conf.fontColor.anchor!'#222222'};
}
.article .detail_wrap .article_time{
float: left;
color: ${template.conf.fontColor.preview!'#9d9d9d'};
}
.article .detail_wrap .look_num{
float: left;
color: ${template.conf.fontColor.preview!'#9d9d9d'};
}
.article .text{color: ${template.conf.fontColor.colorA!'#222222'};
}
.vp_wrap .audio_box{background: ${template.conf.audio.background!'#f6f6f6'};
color: ${template.conf.audio.text!'#222222'};
border: 1px solid ${template.conf.audio.border!'#ececec'}
}
.vp_wrap .audio_box .audio_name,
.vp_wrap .audio_box .audio_time,
.vp_wrap .audio_box .progress_box .current_time,
.vp_wrap .audio_box .progress_box .duration_time {color: ${template.conf.audio.text!'#000000'};
}
.vp_wrap .audio_box .progress_box .progress .curr_bar{background: ${template.conf.audio.text!'#000000'};
}
.vp_wrap .audio_box .audio_play_btn{background-image: url(${template.conf.imgPath.m}audio_play.gif);
}
.vp_wrap .audio_box .audio_pause_btn {background-image: url(${template.conf.imgPath.m}audio_play.png)
}
.bg_music_btn .bg_music_wrap1,
.bg_music_btn .bg_music_wrap2{/* background-image: url(${template.conf.imgPath.m}bg_music.png); */
background-color: ${template.conf.audio.background!'#f6f6f6'};
}
.bg_music_btn .bg_music_wrap1 .bg_music_icon,
.bg_music_btn .bg_music_wrap2 .bg_music_icon{/* background-color: ${template.conf.audio.text!'#222222'};; */
}
.bg_music_btn .bg_music_wrap1 .bg_music_name{color: ${template.conf.audio.text!'#222222'};;
}
.article .music_box .audio_btn {background-image: url(${template.conf.imgPath.m}audio_icon.png);
}
.article .img_box .media_info{background-color: ${template.conf.audio.background!'#f6f6f6'};
color: ${template.conf.audio.text!'#222222'};;
}
.vp_wrap .hyperlink {background-image: url(${template.conf.imgPath.m}link_icon.png);
color: ${template.conf.fontColor.link!'#5072a1'};
}
.vp_wrap .copyrights{color: ${template.conf.fontColor.statement!'#666666'};
}
/* 长图文 */
.code_wrap{border-top: 1px solid ${template.conf.fontColor.colorA!'#000000'};
}
.code_wrap .code_text{color: ${template.conf.fontColor.colorA!'#000000'};
}
.article_more_btn{background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0,${template.conf.audio.background!'#f6f6f6'} 100%);
color: ${template.conf.audio.text!'#222222'};
}
.article_more_btn .arrow_icon{border-right-color: ${template.conf.audio.text!'#222222'};
border-bottom-color: ${template.conf.audio.text!'#222222'};
}
.vp_wrap .refresh_icon:before{border-color: ${template.conf.audio.text!'#222222'};
border-top-color: transparent;
}
.vp_wrap .refresh_icon:after{border-left-color: ${template.conf.audio.text!'#222222'};
}
.vp_wrap .video_box .transcod_box{background: ${template.conf.audio.background!'#f6f6f6'};
color: ${template.conf.audio.text!'#222222'};
}
</style>
3.js 的援用(端内、微信、qq 或其余浏览器)
<script type="text/javascript"
src="https://mscjs.51vv.com/wx/m/vv-base/js/??base.js,vvlib/pic-cdn-cs.js,source/md5.min.js,source/localstorage-cache.js"></script>
<#if (clientInOrOuter!'')=='inner'>
<script type="text/javascript" src="//mscjs.51vv.com/wx/m/vv-base/js/jsbridge_proxy.js"></script>
<script type="text/javascript" src="//mscjs.51vv.com/v/m/article/dist/js/article.js?v=88"></script>
<#else>
<script type="text/javascript"
src="//mscjs.51vv.com/wx/m/vv-base/js/??utils/backFlow.new.min.js,utils/report.js,source/swiper.5.1.0.min.js?v=2"></script>
<#if (appClient!'')=='weixin'>
<script type="text/javascript"
src="//mscjs.51vv.com/wx/m/vv-base/js/??source/jweixin-1.6.0.js,utils/wx.js"></script>
<script type="text/javascript"
src="//mscjs.51vv.com/v/m/article/dist/js/??share.js,article_wx.js?v=88"></script>
<#else>
<script type="text/javascript"
src="//mscjs.51vv.com/v/m/article/dist/js/article_w.js?v=88"></script>
</#if>
</#if>
4. 参数管制
platfrom:client // 客户端页面(pc、h5) // 曾经废除
from:webview // 预览页面(pc、h5)
editStatus:1 // 编辑状态下的预览(pc)qrcode: 1/2 // 长图文(h5)
haswx: 0/1 // 1 曾经装置微信 0 未装置(h5)
hasqq: 0/1 // 1 曾经装置 QQ 0 未装置(h5)
haswb: 0/1 // 1 曾经装置微博 0 未装置(h5)
vp_ak: 参数加密 // 浏览数量是否显示(只有 vp_ak 存在浏览次数就不显示)iswebchat:1 // 小程序末级页(platfrom:client)h:1 //1 不显示赞叹信息
2. 局部性能
1. 懒加载(图片、评论、点赞、赞叹) – getBoundingClientRect API
。
// 图片 1. 首先给图片一个占位资源 2. 判断图片是否呈现在了以后视口
loadImg.each(function (index, item) {if (-window.innerHeight / 3 < this.getBoundingClientRect().top && this.getBoundingClientRect().top < window.innerHeight * 2) {var imgSrc = format.pictureCsFn($(this).attr('data-img'), 'cw750');
$(this).attr('src', format.waterMarkFn(imgSrc));
$(this).attr('height', 'auto');
$(this).attr('data-isLoaded', 1)
}
});
图片懒加载的三种形式
getBoundingClientRect
2. 返回顶部和评论定位滚动成果
// 评论定位
commentPosFn: function () {loadImage.loadImg = [];
var bh = $(window).scrollTop();
var ch = $('#comment').offset().top;
var topT = 0;
if (parseInt(ch - bh) > window.innerHeight / 2) { // 跳转到评论区
topT = ch;
this.scrollTop = $(window).scrollTop();
if ((ch - bh) > window.innerHeight) {$(window).scrollTop(ch - window.innerHeight);
}
} else { // 返回
topT = this.scrollTop || 0;
if ((topT - ch) < -window.innerHeight) {$(window).scrollTop(topT + window.innerHeight);
}
}
setTimeout(function () {$(window).scrollTo({toT: topT})
}, 5)
},
3.web 端发文章音视频共存
// 编辑页 - 告诉末级页敞开音视频
let iframeList = document.getElementsByTagName('iframe');
for(var i = 0; i<iframeList.length ;i++){iframeList[i].contentWindow.postMessage({
from: 2, //web 端编辑页
playSate: 1, // 播放状态
},'https://music.51vv.com');
}
// 末级页接管到
window.addEventListener('message',function(event){
var data = event.data;
if(data.playSate == 1) closeVoice(2);
});
3. 问题总结
1.forEach 报错(安卓 4.)改用(for 循环或 each)
2.filter 导致低配 ios 滑动时卡顿(作品、音频)
IOS 手机的浏览器对这个属性的渲染非常吃力,进而导致渲染过程的 CPU 占用率过高,最终造成卡顿。
.opus_bg{transform: translate3d(1px,1px,1px); // 解决 ios 滑动进度条卡顿
filter: blur(40px);
}
浏览器层合成与页面渲染优化
3.audio 的属性和办法
(1)ios 微信中 ajax 异步回调中音视频 play() 无奈播放
(2)IOS 不能间接批改 currentTime 值
(3)canplay 安卓反复执行、ios 只执行一次
$('.opus_box').on('click','.opus_cover',function(e){var ele = $(this).parents('.opus_box');
if(!format.onLineFn()||!_this.pauseOpusFn(ele)) return;
var opusAudio = ele.find('.opus_audio');
if(isWeixin&&isIOS){ // 解决 IOS 微信作品不播放 -- 第一次播放,须是一个用户触发(click、touch)的行为
opusAudio[0].play();
opusAudio[0].pause();}
var avid = ele.attr('data-avid');
_this.opusInfoFn(avid,2,function(res){if(ele.find('.opus_audio').attr('src') != res.spaceav.fileURL){var currentTime = opusAudio[0].currentTime;
ele.find('.opus_audio').attr('src', window.base.toUrl(res.spaceav.fileURL));
ele.find('.opus_audio').attr('data-src', window.base.toUrl(res.spaceav.fileURL));
if(isIOS){ //ios 不能间接批改 currentTime
opusAudio.on('canplay',function(){ // 安卓会始终触发该事件
opusAudio[0].currentTime = currentTime;
});
}else{opusAudio[0].currentTime = currentTime;
}
}
_this.opusPlayFn(ele);
}.bind(this),function(res){format.toastFn('原作品已被删除或设为私密')
});
});