动手写一个微信聊天页,有文字,有语音,有图片
2018-12-23 本文已影响10人
菜菜___
今天给大家分享用网页实现移动端微信聊天记录的功能,效果图如下:
页面布局中,聊天框使用flex布局,聊天气泡通过伪元素实现(前面文章有记录如何实现一个微信聊天气泡框)
语音播放时写的一个css动画,通过改变播放icon的背景图位置使icon变换:
icon背景图:
voice_icon.png
.container .item .voice.play{
-webkit-animation: voiceplay 1s infinite step-start;
-moz-animation: voiceplay 1s infinite step-start;
-o-animation: voiceplay 1s infinite step-start;
animation: voiceplay 1s infinite step-start;
}
@-webkit-keyframes voiceplay {
30% {
background-position: 0px center;
}
31% {
background-position: -.36rem center;
}
61% {
background-position: -.36rem center;
}
61.5% {
background-position: -.72rem center;
}
100% {
background-position: -.72rem center;
}
}
点击语音框时,我们需要判断当前语音是播放还是暂停状态,如果是播放状态,那么暂停当前的语音,如果是暂停状态,那么先关掉其他正在播放的语音,再播放当前这条语音,并加上动画,代码如下:
//播放列表
var audiolist={};
$(".container").on('click','.item .chat-content p .voice,.item .chat-content p .voice+a',function(){
var audio = $(this).children("audio")[0] || $(this).siblings("span").children("audio")[0];
var no = audio.getAttribute("no");
if(audio !== null){
if(audio.paused){
pauseOther();
audio.play();
$(this).addClass("play");
$(this).siblings(".voice").addClass("play");
audiolist[no]=audio;
}else{
$(this).removeClass("play");
$(this).siblings(".voice").removeClass("play");
audio.pause();
delete audiolist[no];
}
}
})
/*播放结束停止动画*/
function playOver(event){
var no =$(event.target).attr("no");
delete audiolist[no];
$(event.target).parent(".voice").removeClass("play");
}
/*关闭其他的语音*/
function pauseOther(){
for (var i in audiolist){
audiolist[i].pause();
$(audiolist[i]).parent().removeClass("play");
}
}
点击图片时,将图片放大,代码如下:
$(".container").on('click','.item .chat-content p.img-msg img',function(){
var screenWidth = $(window).width();
$("#showImg").attr("src",$(this).attr("src"));
$("<img/>").attr("src", $(this).attr("src")).load(function() {
realWidth = this.width;
realHeight = this.height;
//如果真实的宽度大于浏览器的宽度就按照100%显示
if(realWidth>=screenWidth){
$("#showImg").css("width","100%").css("height","auto");
}
else{//如果小于浏览器的宽度按照原尺寸显示
$("#showImg").css("width",realWidth+'px').css("height",realHeight+'px');
}
});
$('.win').fadeIn("3000");
})
$("#showImg").click(function(){
$('.win').fadeOut("3000",function(){
$(this).attr("src","");
});
});
完整代码:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">
<title>仿微信聊天界面</title>
<link rel="stylesheet" href="css/chat_record.css" />
<script>
(function (doc, win) {
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function () {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
if(clientWidth>=640){
docEl.style.fontSize = '85px';
}else{
docEl.style.fontSize = 100 * (clientWidth / 750) + 'px';
}
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);
</script>
</head>
<body>
<div class="container">
<div class="content" id="contentList">
<div class="item flex left">
<div class="header-img">
<img src="http://gbres.dfcfw.com/Files/picture/20180123/size500/8500AF041D0CBA36227FB1FFCD9E1B05.gif">
</div>
<div class="chat-content">
<p>明天就是周末,晚上去吃火锅吧</p>
</div>
</div>
<div class="item flex right">
<div class="header-img">
<img src="http://wx3.sinaimg.cn/large/00610vQGly1fkwwq76bkaj30dw0dwq51.jpg">
</div>
<div class="chat-content">
<p>可是我今晚要加班啊,下周再去吃吧,海底捞或者小龙坎,听说美国政府正式"关门" ,特朗普想给民主党下马威,因美国国会和白宫围绕特朗普边境墙计划的拨款问题未达成一致,美国政府于当地时间22日凌晨00:01分(北京时间22日13:00)正式部分关门,CNBC22日对此进行了报道</p>
</div>
</div>
<div class="item flex right">
<div class="header-img">
<img src="http://wx3.sinaimg.cn/large/00610vQGly1fkwwq76bkaj30dw0dwq51.jpg">
</div>
<div class="chat-content">
<p>
<span class="voice">
<audio preload="auto" no="1" src="//www.baidu.com/15328008019580.mp3" onended="playOver(event)"></audio>
</span>
<a style="width: 1.64rem;">23''</a>
</p>
</div>
</div>
<div class="item flex left">
<div class="header-img">
<img src="http://gbres.dfcfw.com/Files/picture/20180123/size500/8500AF041D0CBA36227FB1FFCD9E1B05.gif">
</div>
<div class="chat-content">
<p>
<span class="voice">
<audio preload="auto" no="2" src="//www.baidu.com/15328008019580.mp3" onended="playOver(event)"></audio>
</span>
<a style="width: 3.4rem;">56''</a>
</p>
</div>
</div>
<div class="item flex left">
<div class="header-img">
<img src="http://gbres.dfcfw.com/Files/picture/20180123/size500/8500AF041D0CBA36227FB1FFCD9E1B05.gif">
</div>
<div class="chat-content">
<p class="img-msg">
<img src="http://wx3.sinaimg.cn/large/006VtoKely1fwijwbe9d7j30dw0dw40r.jpg">
</p>
</div>
</div>
<div class="item flex right">
<div class="header-img">
<img src="http://wx3.sinaimg.cn/large/00610vQGly1fkwwq76bkaj30dw0dwq51.jpg">
</div>
<div class="chat-content">
<p>好啊,那我们就一起</p>
</div>
</div>
<div class="item flex right">
<div class="header-img">
<img src="http://wx3.sinaimg.cn/large/00610vQGly1fkwwq76bkaj30dw0dwq51.jpg">
</div>
<div class="chat-content">
<p>叫上兔八哥</p>
</div>
</div>
<div class="item flex left">
<div class="header-img">
<img src="http://gbres.dfcfw.com/Files/picture/20180123/size500/8500AF041D0CBA36227FB1FFCD9E1B05.gif">
</div>
<div class="chat-content">
<p>嗯嗯好哒</p>
</div>
</div>
</div>
</div>
<!--展示图片看大图-->
<div class="win">
<div class="mask-layer"></div>
<div class="win-panel">
<div class="win-content">
<img id="showImg" src="">
</div>
</div>
</div>
<script type="text/javascript" src="//code.jquery.com/jquery-1.8.2.min.js"></script>
<script>
//播放列表
var audiolist={};
$(function(){
$(".container").on('click','.item .chat-content p .voice,.item .chat-content p .voice+a',function(){
var audio = $(this).children("audio")[0] || $(this).siblings("span").children("audio")[0];
var no = audio.getAttribute("no");
if(audio !== null){
if(audio.paused){
pauseOther();
audio.play();
$(this).addClass("play");
$(this).siblings(".voice").addClass("play");
audiolist[no]=audio;
}else{
$(this).removeClass("play");
$(this).siblings(".voice").removeClass("play");
audio.pause();
delete audiolist[no];
}
}
})
$(".container").on('click','.item .chat-content p.img-msg img',function(){
var screenWidth = $(window).width();
$("#showImg").attr("src",$(this).attr("src"));
$("<img/>").attr("src", $(this).attr("src")).load(function() {
realWidth = this.width;
realHeight = this.height;
//如果真实的宽度大于浏览器的宽度就按照100%显示
if(realWidth>=screenWidth){
$("#showImg").css("width","100%").css("height","auto");
}
else{//如果小于浏览器的宽度按照原尺寸显示
$("#showImg").css("width",realWidth+'px').css("height",realHeight+'px');
}
});
$('.win').fadeIn("3000");
})
$("#showImg").click(function(){
$('.win').fadeOut("3000",function(){
$(this).attr("src","");
});
});
})
/*播放结束停止动画*/
function playOver(event){
var no =$(event.target).attr("no");
delete audiolist[no];
$(event.target).parent(".voice").removeClass("play");
}
/*关闭其他的语音*/
function pauseOther(){
for (var i in audiolist){
audiolist[i].pause();
$(audiolist[i]).parent().removeClass("play");
}
}
</script>
</body>
</html>
css代码:
* {
padding: 0;
margin: 0;
box-sizing: border-box;
-webkit-box-sizing: border-box;
}
body{
max-width: 540px;
}
a,a:focus{
-webkit-tap-highlight-color:transparent
}
.flex{
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
.container{
height: 100%;
padding: .3rem .2rem;
overflow-y:scroll;
background-color: #ebebeb;
}
.container .content .item{
margin-bottom: .3rem;
}
.container .item .header-img{
width: .8rem;
height: .8rem;
-ms-flex-negative: 0;
flex-shrink: 0;
-webkit-box-flex: 0;
-ms-flex-positive: 0;
flex-grow: 0;
border-radius: 5px;
overflow: hidden;
background: transparent;
}
.container .item .header-img img{
display: block;
width: 100%;
}
.container .left.item .chat-content{
margin-left: .25rem;
}
.container .right.item .chat-content{
margin-right: .25rem;
}
.container .left.item .chat-content p{
margin-right: 1.05rem;
background: #fff;
}
.container .right.item .chat-content p{
margin-left: 1.1rem;
background: #9EEA6A;
}
.container .item .chat-content p{
position: relative;
padding: .18rem;
border:solid 1px #D4D4D4;
border-radius: 4px;
font-size: .3rem;
word-wrap: break-word;
word-break: break-all;
}
.container .item .chat-content p:before,.container .item .chat-content p:after{
content: "";
display: block;
position: absolute;
width:0;
height: 0;
top: .22rem;
border-top: .12rem solid transparent;
border-bottom: .12rem solid transparent;
}
.container .left.item .chat-content p:before{
border-right: .18rem solid #D4D4D4;
left: -.18rem;
}
.container .left.item .chat-content p:after{
border-right: .18rem solid #fff;
left: -.16rem;
}
.container .right.item .chat-content p:before{
border-left: .18rem solid #9EEA6A;
right: -.18rem;
}
.container .right.item .chat-content p:after{
border-left: .18rem solid #9EEA6A;
right: -.16rem;
}
.container .right.item{
flex-direction: row-reverse;
}
.container .item p span,.container .item p a{
display:inline-block;
vertical-align: middle;
cursor: pointer;
text-align:right;
font-size:.34rem;
color:#7b7a7a;
}
.container .item p.img-msg{
max-width: 40%;
}
.container .right.item p.img-msg{
margin-left: 60%;
}
.container .item p.img-msg img{
display: block;
width: 100%;
}
.container .item .voice{
width: .36rem;
height: .4rem;
display: inline-block;
background-repeat: no-repeat;
background-image: url(../image/voice_icon.png);
background-size: 1.08rem .4rem;
background-position: -.72rem center;
}
.container .right.item .voice{
transform:rotate(180deg);
}
.container .item .voice.play{
-webkit-animation: voiceplay 1s infinite step-start;
-moz-animation: voiceplay 1s infinite step-start;
-o-animation: voiceplay 1s infinite step-start;
animation: voiceplay 1s infinite step-start;
}
@-webkit-keyframes voiceplay {
30% {
background-position: 0px center;
}
31% {
background-position: -.36rem center;
}
61% {
background-position: -.36rem center;
}
61.5% {
background-position: -.72rem center;
}
100% {
background-position: -.72rem center;
}
}
/*弹出层*/
.win {
display: none;
}
.mask-layer {
position: fixed;
width: 100%;
height: 100%;
opacity: 1;
filter: alpha(opacity=100);
background-color: black;
z-index: 9999;
top: 0;
left: 0;
}
.win-panel{
position: fixed;
z-index: 10000;
top:50%;
left:50%;
overflow: hidden;
width: 100%;
transform:translate(-50%,-50%);
transform-origin:50% 50%;
text-align: center;
background-color: #000;
}
.win-panel .win-content img{
background-color: #fff;
}
原文作者技术博客:https://www.jianshu.com/u/ac4daaeecdfe
95后前端妹子一枚,爱阅读,爱交友,将工作中遇到的问题记录在这里,希望给每一个看到的你能带来一点帮助。
欢迎留言交流。