html5移动端webscoket实现在线聊天

向右看齐 2021-11-26 14:06 830阅读 0赞

页面效果图

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xpdWp1Y2Fp_size_16_color_FFFFFF_t_70

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width,height=device-height">
  7. <meta name="apple-mobile-web-app-capable" content="yes">
  8. <meta name="apple-mobile-web-app-status-bar-style" content="black">
  9. <meta name="format-detection" content="telephone=no">
  10. <!--解决点击页面文本框导致页面放大-->
  11. <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
  12. <link rel="stylesheet" type="text/css" href="../font_Icon/iconfont.css">
  13. <link rel="stylesheet" type="text/css" href="../font_Icon/iconfont2.css">
  14. <link rel="stylesheet" type="text/css" href="../css/chat.css">
  15. <script src="../js/HZRecorder.js"></script>
  16. <script src="../js/common_audio.js"></script>
  17. <link rel="stylesheet" href="../css/common_audio.css">
  18. <script src="../js/mui.min.js"></script>
  19. <!--标准mui.css-->
  20. <link rel="stylesheet" href="../css/mui.css">
  21. <link rel="stylesheet" href="../css/mui.min.css">
  22. <!--App自定义的css-->
  23. <style type="text/css">
  24. .mui-preview-image.mui-fullscreen {
  25. position: fixed;
  26. z-index: 20;
  27. background-color: #000;
  28. }
  29. .mui-preview-header,
  30. .mui-preview-footer {
  31. position: absolute;
  32. width: 100%;
  33. left: 0;
  34. z-index: 10;
  35. }
  36. .mui-preview-header {
  37. height: 44px;
  38. top: 0;
  39. }
  40. .mui-preview-footer {
  41. height: 50px;
  42. bottom: 0px;
  43. }
  44. .mui-preview-header .mui-preview-indicator {
  45. display: block;
  46. line-height: 25px;
  47. color: #fff;
  48. text-align: center;
  49. margin: 15px auto 4;
  50. width: 70px;
  51. background-color: rgba(0, 0, 0, 0.4);
  52. border-radius: 12px;
  53. font-size: 16px;
  54. }
  55. .mui-preview-image {
  56. display: none;
  57. -webkit-animation-duration: 0.5s;
  58. animation-duration: 0.5s;
  59. -webkit-animation-fill-mode: both;
  60. animation-fill-mode: both;
  61. }
  62. .mui-preview-image.mui-preview-in {
  63. -webkit-animation-name: fadeIn;
  64. animation-name: fadeIn;
  65. }
  66. .mui-preview-image.mui-preview-out {
  67. background: none;
  68. -webkit-animation-name: fadeOut;
  69. animation-name: fadeOut;
  70. }
  71. .mui-preview-image.mui-preview-out .mui-preview-header,
  72. .mui-preview-image.mui-preview-out .mui-preview-footer {
  73. display: none;
  74. }
  75. .mui-zoom-scroller {
  76. position: absolute;
  77. display: -webkit-box;
  78. display: -webkit-flex;
  79. display: flex;
  80. -webkit-box-align: center;
  81. -webkit-align-items: center;
  82. align-items: center;
  83. -webkit-box-pack: center;
  84. -webkit-justify-content: center;
  85. justify-content: center;
  86. left: 0;
  87. right: 0;
  88. bottom: 0;
  89. top: 0;
  90. width: 100%;
  91. height: 100%;
  92. margin: 0;
  93. -webkit-backface-visibility: hidden;
  94. }
  95. .mui-zoom {
  96. -webkit-transform-style: preserve-3d;
  97. transform-style: preserve-3d;
  98. }
  99. .mui-slider .mui-slider-group .mui-slider-item img {
  100. width: auto;
  101. height: auto;
  102. max-width: 100%;
  103. max-height: 100%;
  104. }
  105. .mui-android-4-1 .mui-slider .mui-slider-group .mui-slider-item img {
  106. width: 100%;
  107. }
  108. .mui-android-4-1 .mui-slider.mui-preview-image .mui-slider-group .mui-slider-item {
  109. display: inline-table;
  110. }
  111. .mui-android-4-1 .mui-slider.mui-preview-image .mui-zoom-scroller img {
  112. display: table-cell;
  113. vertical-align: middle;
  114. }
  115. .mui-preview-loading {
  116. position: absolute;
  117. width: 100%;
  118. height: 100%;
  119. top: 0;
  120. left: 0;
  121. display: none;
  122. }
  123. .mui-preview-loading.mui-active {
  124. display: block;
  125. }
  126. .mui-preview-loading .mui-spinner-white {
  127. position: absolute;
  128. top: 50%;
  129. left: 50%;
  130. margin-left: -25px;
  131. margin-top: -25px;
  132. height: 50px;
  133. width: 50px;
  134. }
  135. .mui-preview-image img.mui-transitioning {
  136. -webkit-transition: -webkit-transform 0.5s ease, opacity 0.5s ease;
  137. transition: transform 0.5s ease, opacity 0.5s ease;
  138. }
  139. @-webkit-keyframes fadeIn {
  140. 0% {
  141. opacity: 0;
  142. }
  143. 100% {
  144. opacity: 1;
  145. }
  146. }
  147. @keyframes fadeIn {
  148. 0% {
  149. opacity: 0;
  150. }
  151. 100% {
  152. opacity: 1;
  153. }
  154. }
  155. @-webkit-keyframes fadeOut {
  156. 0% {
  157. opacity: 1;
  158. }
  159. 100% {
  160. opacity: 0;
  161. }
  162. }
  163. @keyframes fadeOut {
  164. 0% {
  165. opacity: 1;
  166. }
  167. 100% {
  168. opacity: 0;
  169. }
  170. }
  171. p img {
  172. max-width: 100%;
  173. height: auto;
  174. }
  175. </style>
  176. <style type="text/css">
  177. * {
  178. margin: 0;
  179. padding: 0;
  180. }
  181. html, body {
  182. background: #fff;
  183. }
  184. .btn {
  185. position: fixed;
  186. bottom: 0;
  187. width: 100%;
  188. height: 60px;
  189. background: #eee;
  190. }
  191. .btn input {
  192. width: 100%;
  193. height: 100%;
  194. font: 20px/60px 'microsoft yahei';
  195. }
  196. .blackBoxSpeak {
  197. width: 176px;
  198. height: 176px;
  199. position: absolute;
  200. left: 0;
  201. right: 0;
  202. top: 0;
  203. bottom: 0;
  204. margin: auto;
  205. background: url("../img/ic_record@2x.png") no-repeat 28px 16px/65px 104px,
  206. url("../img/ic_record_ripple@2x-9.png") no-repeat 111.2px 32px/28.8px 88px;
  207. background: rgba(0, 0, 0, .7);
  208. display: none;
  209. border-radius: 12px;
  210. }
  211. .blackBoxSpeakConent {
  212. font: 14.4px '微软雅黑 Light';
  213. position: absolute;
  214. left: 0;
  215. right: 0;
  216. bottom: 12px;
  217. display: block;
  218. text-align: center;
  219. width: 90%;
  220. padding: 8px 0;
  221. margin: auto;
  222. color: #ffffff;
  223. font-weight: 200;
  224. border-radius: 4px;
  225. }
  226. .blackBoxPause {
  227. width: 176px;
  228. height: 176px;
  229. position: absolute;
  230. left: 0;
  231. right: 0;
  232. top: 0;
  233. bottom: 0;
  234. margin: auto;
  235. background: url("../img/ic_record@2x.png") no-repeat 28px 16px/65px 104px,
  236. url("../img/ic_record_ripple@2x-9.png") no-repeat 111.2px 32px/28.8px 88px;
  237. background: rgba(0, 0, 0, .7);
  238. display: none;
  239. border-radius: 12px;
  240. }
  241. .blackBoxPauseContent {
  242. font: 14.4px '微软雅黑 Light';
  243. position: absolute;
  244. left: 0;
  245. right: 0;
  246. bottom: 12px;
  247. display: block;
  248. text-align: center;
  249. width: 90%;
  250. padding: 8px 0;
  251. margin: auto;
  252. color: #ffffff;
  253. font-weight: 200;
  254. border-radius: 4px;
  255. }
  256. </style>
  257. <script type="text/javascript" src="../js/jquery.min.js"></script>
  258. <script type="text/javascript">
  259. mui.init();
  260. window.addEventListener('refresh', function(e){//执行刷新
  261. if(e.detail.id==1){
  262. location.reload();
  263. }
  264. });
  265. //聊天记录
  266. var chatRecord;
  267. //好友手机号
  268. var ToUserId ;
  269. //名称
  270. var toName;
  271. //本人手机号
  272. var UserId;
  273. //本人名字
  274. var name ;
  275. var msg_type;
  276. var websocket = null;
  277. mui.plusReady(function () {
  278. name =plus.storage.getItem("name");
  279. plus.nativeUI.closeWaiting();
  280. mui.currentWebview.show();
  281. var self = plus.webview.currentWebview();
  282. ToUserId = ""+self.ToUserId;//获得参数
  283. toName = self.Name;
  284. console.log(toName);
  285. $(".ChatInfoName").html("<font color=\"#000000\">"+toName+"</font>");
  286. if(plus.storage.getItem("chatback")!=null){
  287. var img=plus.storage.getItem("chatback");
  288. $(".chatBox-info").css("background-image","url("+img+")");
  289. }
  290. console.log("ToUserId----"+ToUserId);
  291. plus.storage.setItem("chating",ToUserId);
  292. UserId=plus.storage.getItem("username");
  293. console.log("UserId----"+UserId);
  294. if(plus.storage.getItem(ToUserId)==null){
  295. plus.storage.setItem(ToUserId,"");
  296. //alert('创建成功');
  297. }else{
  298. //alert('已经创建成功');
  299. chatRecord=plus.storage.getItem(ToUserId);
  300. //alert(chatRecord);
  301. $(".chatBox-content-demo").append(chatRecord);
  302. $(document).ready(function () {
  303. $("#chatBox-content-demo").scrollTop($("#chatBox-content-demo")[0].scrollHeight);
  304. });
  305. }
  306. //判断当前浏览器是否支持WebSocket
  307. if ('WebSocket' in window) {
  308. websocket = new WebSocket("ws://192.168.1.18:8080/xgh_logistics/websocket/"+UserId);
  309. /* websocket = new WebSocket("ws://61.163.34.143:8090/zzdy_oa/websocket");*/
  310. }
  311. else {
  312. alert('当前浏览器 Not support websocket')
  313. }
  314. //连接发生错误的回调方法
  315. websocket.onerror = function () {
  316. console.log("通信连接发生错误");
  317. // setMessageInnerHTML("WebSocket连接发生错误",msg_type);
  318. };
  319. //连接成功建立的回调方法
  320. websocket.onopen = function () {
  321. //setMessageInnerHTML("WebSocket连接成功",msg_type);
  322. console.log("WebSocket连接成功-------");
  323. /* var Content='{"UserId":"'+UserId+'","ToUserId":"'+ToUserId+'","Content":"WebSocket连接成功","time":"'+time+'"}';//字符串中的属性要严格的加上引号
  324. websocket.send(Content);*/
  325. }
  326. //接收到消息的回调方法
  327. websocket.onmessage = function (event) {
  328. var str=event.data;
  329. var obj = JSON.parse(str);;
  330. console.log("发送方--"+obj.UserId);
  331. console.log("接收方---"+obj.ToUserId);
  332. console.log("消息内容"+obj.Content);
  333. console.log("消息类型"+obj.type);
  334. console.log("消息类型"+obj.time);
  335. msg_type=obj.type;
  336. var audio_Time="test";
  337. if(msg_type=="audio"){
  338. audio_Time=obj.audio_time;
  339. }
  340. if(ToUserId==obj.UserId){
  341. setMessageInnerHTML(obj.Content,obj.time,msg_type,audio_Time);
  342. }
  343. }
  344. //连接关闭的回调方法
  345. websocket.onclose = function () {
  346. console.log("WebSocket连接关闭");
  347. //setMessageInnerHTML("WebSocket连接关闭");
  348. }
  349. //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
  350. window.onbeforeunload = function () {
  351. closeWebSocket();
  352. }
  353. //将消息显示在网页上
  354. function setMessageInnerHTML(innerHTML,msg_Time,msg_type,audio_Time) {
  355. var content=null;
  356. if(msg_type=="image"){
  357. content= "<div class='clearfloat'><div class='author-name'><small class='chat-date'>"+msg_Time+"</small></div><div class='left'><div class='chat-avatars' style='font-size: 75%;text-align:center;line-height:0.7rem;background-color: #007AFF;width:0.7rem;height: 0.7rem;border-radius: 100%;color: #FFFFFF;margin-top: -5px;'>"+toName+"</div><div class='chat-message'><img src='"+innerHTML+"' data-preview-src='' data-preview-group='1' alt=''/></div></div></div>"
  358. // document.getElementById('message').innerHTML += innerHTML + '<br/>';
  359. }if(msg_type=="txt"||msg_type==null){
  360. content= "<div class='clearfloat'><div class='author-name'><small class='chat-date'>"+msg_Time+"</small></div><div class='left'> <div class='chat-avatars' style='font-size: 75%;text-align:center;line-height:0.7rem;background-color: #007AFF;width:0.7rem;height: 0.7rem;border-radius: 100%;color: #FFFFFF;margin-top: -5px;'>"+toName+"</div><div class='chat-message'>"+innerHTML+"</div></div></div>";
  361. console.log("----"+content);
  362. }if(msg_type=="audio"){
  363. var msg="<div class='add_yuyin'><div class='r_yuyin' onclick='playaudio(this)' style='width:60px' data-time='44'>"+audio_Time+"\" <input style='display:none' value='"+innerHTML+"'/><s></s></div></div>";
  364. content="<div class='clearfloat'><div class='author-name'><small class='chat-date'>"+msg_Time+"</small></div><div class='left'> <div class='chat-avatars' style='font-size: 75%;text-align:center;line-height:0.7rem;background-color: #007AFF;width:0.7rem;height: 0.7rem;border-radius: 100%;color: #FFFFFF;margin-top: -5px;'>"+toName+"</div><div class='chat-message'>"+msg+"</div></div></div>" ;
  365. console.log("http---"+content);
  366. }
  367. addChatRecord(content);
  368. //新消息提示
  369. startPlay();
  370. $(".chatBox-content-demo").append(content);
  371. $(document).ready(function () {
  372. $("#chatBox-content-demo").scrollTop($("#chatBox-content-demo")[0].scrollHeight);
  373. });
  374. }
  375. //关闭WebSocket连接
  376. function closeWebSocket() {
  377. websocket.close();
  378. }
  379. })
  380. /* if(window.plus){
  381. // 在这里调用5+ API
  382. }else{// 兼容老版本的plusready事件
  383. document.addEventListener('plusready',function () {
  384. }
  385. },false);
  386. }*/
  387. /**
  388. * @param {Object} chat_record 聊天文本
  389. */
  390. function addChatRecord(chat_record){
  391. //console.log(chat_record);
  392. chatRecord=plus.storage.getItem(ToUserId);
  393. console.log("-++++-------"+ToUserId);
  394. chatRecord+=chat_record;
  395. console.log("-------"+chatRecord);
  396. plus.storage.setItem(ToUserId,chatRecord);
  397. }
  398. /**
  399. * 播放音频
  400. * @param {Object} path
  401. */
  402. var player;
  403. function playAudio (id,path) {
  404. if(player!=null) //如果存在
  405. {
  406. player.stop(); //停止正在播放的音频,
  407. $(".r_yuyin").find("s").removeClass("bofang");
  408. player=null;
  409. } else{
  410. $(id).find("s").addClass("bofang");
  411. player = plus.audio.createPlayer(path);
  412. player.play(function(){
  413. $(id).find("s").removeClass("bofang");
  414. // mui.toast("播放完成");
  415. }, function(e) {
  416. // mui.toast("播放失败");
  417. });
  418. }
  419. }
  420. var dshiqi = null;
  421. var audiotime;
  422. var audioStatus;
  423. function playaudio(id) {
  424. var url = $(id).find("input").val();
  425. audioStatus = plus.audio.createPlayer(url);
  426. // var len= audioStatus.getBuffered();
  427. //$(id).find("s").removeClass("bofang");
  428. playAudio(id,url);
  429. }
  430. /**
  431. * base64字符串转成语音文件(参考http://ask.dcloud.net.cn/question/16935)
  432. * @param {Object} base64Str
  433. * @param {Object} callback
  434. */
  435. function dataURL2Audio (base64Str, callback) {
  436. var base64Str = base64Str.replace('data:audio/amr;base64,','');
  437. var audioName = (new Date()).valueOf() + '.amr';
  438. plus.io.requestFileSystem(plus.io.PRIVATE_DOC,function(fs){
  439. fs.root.getFile(audioName,{create:true},function(entry){
  440. // 获得平台绝对路径
  441. var fullPath = entry.fullPath;
  442. if(mui.os.android){
  443. // 读取音频
  444. var Base64 = plus.android.importClass("android.util.Base64");
  445. var FileOutputStream = plus.android.importClass("java.io.FileOutputStream");
  446. try{
  447. var out = new FileOutputStream(fullPath);
  448. var bytes = Base64.decode(base64Str, Base64.DEFAULT);
  449. out.write(bytes);
  450. out.close();
  451. // 回调
  452. callback && callback(entry);
  453. }catch(e){
  454. console.log(e.message);
  455. }
  456. }else if(mui.os.ios){
  457. var NSData = plus.ios.importClass('NSData');
  458. var nsData = new NSData();
  459. nsData = nsData.initWithBase64EncodedStringoptions(base64Str,0);
  460. if (nsData) {
  461. nsData.plusCallMethod({writeToFile: fullPath,atomically:true});
  462. plus.ios.deleteObject(nsData);
  463. }
  464. // 回调
  465. callback && callback(entry);
  466. }
  467. })
  468. })
  469. }
  470. //发送消息
  471. /* function send() {
  472. var message = document.getElementById('text').value;
  473. websocket.send(message);
  474. }*/
  475. </script>
  476. </head>
  477. <body>
  478. <div id="content" class="content">
  479. <div class="chatContainer">
  480. <div class="chatBtn">
  481. <i class="iconfont icon-xiaoxi1"></i>
  482. </div>
  483. <div class="chatBox" ref="chatBox">
  484. <div class="chatBox-head">
  485. <div class="chatBox-head-two">
  486. <div class="chat-return" style="color: #000000;"><div class="mui-icon mui-icon-back"></div></div>
  487. <div class="chat-people">
  488. <div class="ChatInfoName" style="width: 100%;font;position: absolute;left: 39%;"></div>
  489. </div>
  490. <div class="ChatIcon">
  491. <div onclick="chatChoose()" class="mui-icon mui-icon-phone" style="color: #000000;"></div>
  492. <div onclick="claer_chat()" class="mui-icon mui-icon-bars" style="color: #000000;"></div>
  493. </div>
  494. <!-- <div class="chat-close">关闭</div>-->
  495. </div>
  496. </div>
  497. <div class="chatBox-info">
  498. <!-- <audio controls autoplay src="http://sc1.111ttt.cn:8282/2018/1/03m/13/396131232171.m4a?tflag=1546606800&pin=97bb2268ae26c20fe093fd5b0f04be80#.mp3"></audio>-->
  499. <div class="chatBox-kuang" ref="chatBoxkuang">
  500. <div class="chatBox-content">
  501. <div style="display: none;"><audio controls autoplay></audio> </div>
  502. <div class="chatBox-content-demo" id="chatBox-content-demo">
  503. </div>
  504. </div>
  505. <div class="chatBox-send">
  506. <div class="div-textarea" contenteditable="true"></div>
  507. <div>
  508. <button id="bt_recoding" class="btn-default-styles">
  509. <i class="mui-icon mui-icon-mic"></i>
  510. </button>
  511. <label id="chat-tuxiang" title="发送图片" for="inputImage" class="btn-default-styles">
  512. <input type="file" onchange="selectImg(this)" accept="image/*" name="file" id="inputImage" class="hidden" capture="camera">
  513. <i class="mui-icon mui-icon-image"></i>
  514. </label>
  515. <button id="chat-fasong" class="btn-default-styles"><i class="fasong">发送</i><!--<i class="iconfont icon-fasong" style="width: px;"></i>-->
  516. </button>
  517. </div>
  518. </div>
  519. </div>
  520. </div>
  521. </div>
  522. </div>
  523. </div>
  524. <!-- 中间黑框 录音状态 -->
  525. <div class="blackBoxSpeak">
  526. <p class="blackBoxSpeakConent">手指上划,取消发送</p>
  527. </div>
  528. <!-- 中间黑框 暂停状态 -->
  529. <div class="blackBoxPause">
  530. <p class="blackBoxPauseContent" style="background: red">松开手指, 取消发送</p>
  531. </div>
  532. <script>
  533. function Time(){
  534. var date=new Date();
  535. var year=date.getFullYear();//当前年份
  536. var month=date.getMonth();//当前月份
  537. var data=date.getDate();//天
  538. var hours=date.getHours();//小时
  539. var minute=date.getMinutes();//分
  540. var second=date.getSeconds();//秒
  541. var time=year+"-"+fnW((month+1))+"-"+fnW(data)+" "+fnW(hours)+":"+fnW(minute)+":"+fnW(second);
  542. console.log("time---"+time);
  543. return time;
  544. }
  545. //补位 当某个字段不是两位数时补0
  546. function fnW(str){
  547. var num;
  548. str>9?num=str:num="0"+str;
  549. return num;
  550. }
  551. screenFuc();
  552. function screenFuc() {
  553. var topHeight = $(".chatBox-head").innerHeight();//聊天头部高度
  554. //屏幕小于768px时候,布局change
  555. var winWidth = $(window).innerWidth();
  556. if (winWidth <= 768) {
  557. var totalHeight = $(window).height(); //页面整体高度
  558. $(".chatBox-info").css("height", totalHeight - topHeight);
  559. var infoHeight = $(".chatBox-info").innerHeight();//聊天头部以下高度
  560. //中间内容高度
  561. $(".chatBox-content").css("height", infoHeight - 46);
  562. $(".chatBox-content-demo").css("height", infoHeight - 66);
  563. $(".chatBox-list").css("height", totalHeight - topHeight);
  564. $(".chatBox-kuang").css("height", totalHeight - topHeight);
  565. $(".div-textarea").css("width", winWidth - 150);
  566. } else {
  567. $(".chatBox-info").css("height", 495);
  568. $(".chatBox-content").css("height", 448);
  569. $(".chatBox-content-demo").css("height", 448);
  570. $(".chatBox-list").css("height", 495);
  571. $(".chatBox-kuang").css("height", 495);
  572. $(".div-textarea").css("width", 260);
  573. }
  574. }
  575. (window.onresize = function () {
  576. screenFuc();
  577. })();
  578. //返回列表
  579. $(".chat-return").click(function () {
  580. plus.storage.removeItem("chating");
  581. mui.back();
  582. /* window.history.back();*/
  583. });
  584. //点击选择照片自动触发input图片上传
  585. $("#chat-tuxiang").click(function () {
  586. //$("#inputImage").click();
  587. document.getElementById("inputImage").click();
  588. });
  589. // 发送信息
  590. $("#chat-fasong").click(function () {
  591. var textContent = $(".div-textarea").html()/* resplace(/[\n\r]/g, '<br>') */;
  592. if (textContent != "") {
  593. var chatdiv="<div class=\"clearfloat\">" +
  594. "<div class=\"author-name\"><small class=\"chat-date\">"+Time()+"</small> </div> " +
  595. "<div class=\"right\"> <div class=\"chat-message\"> " + textContent + " </div> " +
  596. "<div class=\"chat-avatars\" style=\"font-size: 75%;text-align:center;line-height:0.7rem;background-color: #007AFF;width:0.7rem;height: 0.7rem;border-radius: 75%;color: #FFFFFF;margin-top:-5px\">"+name+"</div> </div> </div>";
  597. console.log("============="+chatdiv);
  598. $(".chatBox-content-demo").append(chatdiv);
  599. //发送后清空输入框
  600. $(".div-textarea").html("");
  601. //聊天框默认最底部
  602. $(document).ready(function () {
  603. $("#chatBox-content-demo").scrollTop($("#chatBox-content-demo")[0].scrollHeight);
  604. });
  605. // out.println(textContent);
  606. addChatRecord(chatdiv);
  607. var Content='{"UserId":"'+UserId+'","FromUserName":"'+name+'","ToUserId":"'+ToUserId+'","Content":"'+textContent+'","type":"txt","time":"'+Time()+'"}';//字符串中的属性要严格的加上引号
  608. websocket.send(Content);
  609. }
  610. });
  611. //通过画布降低上传图片像素
  612. var canvas = document.createElement("canvas");
  613. var ctx = canvas.getContext('2d');
  614. // 发送图片
  615. function selectImg(pic) {
  616. if (!pic.files || !pic.files[0]) {
  617. return;
  618. }
  619. var reader = new FileReader();
  620. var images=new Image();
  621. reader.onload = function () {
  622. var url = reader.result;//读取到的文件内容.这个属性只在读取操作完成之后才有效,并且数据的格式取决于读取操作是由哪个方法发起的.所以必须使用reader.onload,
  623. images.src=url;//reader读取的文件内容是base64,利用这个url就能实现上传前预览图片
  624. var chatImg="<div class=\"clearfloat\">" +
  625. "<div class=\"author-name\"><small class=\"chat-date\">"+Time()+"</small> </div> " +
  626. "<div class=\"right\"> <div class=\"chat-message\"><img src=" + images.src + " data-preview-src='' data-preview-group='1'></div> " +
  627. "<div class=\"chat-avatars\" style=\"font-size: 75%;text-align:center;line-height:0.7rem;background-color: #007AFF;width:0.7rem;height: 0.7rem;border-radius: 100%;color: #FFFFFF;margin-top: -5px;\">"+name+"</div> </div> </div>";
  628. addChatRecord(chatImg);
  629. $(".chatBox-content-demo").append(chatImg);
  630. //聊天框默认最底部
  631. $(document).ready(function () {
  632. $("#chatBox-content-demo").scrollTop($("#chatBox-content-demo")[0].scrollHeight);
  633. });
  634. };
  635. images.onload=function(){
  636. var w = images.naturalWidth,
  637. h = images.naturalHeight;
  638. canvas.width = w;
  639. canvas.height = h;
  640. ctx.drawImage(images, 0, 0, w, h, 0, 0, w, h);
  641. fileUpload();
  642. };
  643. reader.readAsDataURL(pic.files[0]);
  644. }
  645. function fileUpload() {
  646. var data = canvas.toDataURL("image/jpeg",0.3);
  647. console.log("img------"+data);
  648. var Content='{"UserId":"'+UserId+'","FromUserName":"'+name+'","ToUserId":"'+ToUserId+'","Content":"'+data+'","type":"image","time":"'+Time()+'"}';//字符串中的属性要严格的加上引号
  649. websocket.send(Content);
  650. }
  651. </script>
  652. </body>
  653. <script src="../js/mui.zoom.js"></script>
  654. <script src="../js/mui.previewimage.js"></script>
  655. <script>
  656. mui.previewImage();
  657. </script>
  658. </html>
  659. <script type="text/javascript">
  660. var MIN_SOUND_TIME = 800;
  661. var startTimestamp = null;
  662. var stopTimestamp = null;
  663. // 开始录音
  664. var r;
  665. //语音path
  666. var amr;
  667. //判断是否发送语音
  668. var IsSendAudio=true;
  669. function startRecord(){
  670. // alert("开始录音");
  671. startTimestamp = (new Date()).getTime();
  672. r = plus.audio.getRecorder();
  673. r.record( {filename:"_doc/audio/"}, function (p) {
  674. //alert("录音成功");
  675. amr=p;
  676. stopTimestamp = (new Date()).getTime();
  677. if(IsSendAudio==true){
  678. if (stopTimestamp - startTimestamp < MIN_SOUND_TIME) {
  679. mui.toast("按键时间太短");
  680. }else{
  681. Audio2dataURL(amr);
  682. }
  683. }
  684. }, function ( e ) {
  685. alert( "Audio record failed: " + e.message );
  686. } );
  687. }
  688. // 停止录音
  689. function stopRecord(){
  690. r.stop();
  691. }
  692. function startPlay(){
  693. var p= plus.audio.createPlayer("../music/tips.mp3");
  694. //alert("p"+p);
  695. p.play(function(){
  696. //alert("播放完毕");
  697. })
  698. }
  699. /**
  700. * 录音语音文件转base64字符串
  701. * @param {Object} path
  702. */
  703. function Audio2dataURL (path) {
  704. plus.io.resolveLocalFileSystemURL(path, function(entry){
  705. entry.file(function(file){
  706. var reader = new plus.io.FileReader();
  707. reader.onloadend = function (e) {
  708. var data=e.target.result;
  709. stopTimestamp = (new Date()).getTime();
  710. var times=((stopTimestamp-startTimestamp)/1000).toFixed(1);
  711. console.log("------"+e.target.result);
  712. var chataudio="<div class=\"clearfloat\">" +
  713. "<div class=\"author-name\"><small class=\"chat-date\">"+Time()+"</small> </div> " +
  714. "<div class=\"right\"> <div class=\"chat-message\"> <div class=\"add_yuyin\"><div class=\"r_yuyin\" onclick=\"playaudio(this)\" style=\"width:60px;color:white\" >"+times+"\"<input style=\"display:none\" value='"+amr+"'/><s></s></div></div></div>" +
  715. "<div class=\"chat-avatars\" style=\"font-size: 75%;text-align:center;line-height:0.7rem;background-color: #007AFF;width:0.7rem;height: 0.7rem;border-radius: 100%;color: #FFFFFF;margin-top:-5px\">"+name+"</div> </div> </div>";
  716. addChatRecord(chataudio);
  717. $(".chatBox-content-demo").append(chataudio);
  718. //聊天框默认最底部
  719. $(document).ready(function () {
  720. $("#chatBox-content-demo").scrollTop($("#chatBox-content-demo")[0].scrollHeight);
  721. });
  722. var Content='{"UserId":"'+UserId+'","FromUserName":"'+name+'","ToUserId":"'+ToUserId+'","Content":"'+data+'","type":"audio","time":"'+Time()+'","audio_time":"'+times+'"}';//字符串中的属性要严格的加上引号
  723. websocket.send(Content);
  724. };
  725. reader.readAsDataURL(file);
  726. },function(e){
  727. mui.toast("读写出现异常: " + e.message );
  728. })
  729. })
  730. }
  731. //录音按钮
  732. var bt_recoding = document.getElementById("bt_recoding");
  733. //中间黑色边框和里面的内容(录音状态)
  734. var blackBoxSpeak = document.querySelector(".blackBoxSpeak");
  735. blackBoxSpeak.style.background = "url('../img/ic_record@2x.png')no-repeat 28 16px/65px 104px, url('../img/ic_record_ripple@2x-9.png')no-repeat 111.2px 32px/28.8px 88px";
  736. blackBoxSpeak.style.backgroundColor = "rgba(0,0,0,.7)";
  737. //中间黑色边框和里面的内容(暂停状态)
  738. var blackBoxPause = document.querySelector(".blackBoxPause");
  739. blackBoxPause.style.background = "rgba(0,0,0,.7) url('../img/ic_release_to_cancel@2x.png')no-repeat center 8px/67.2px 104px";
  740. blackBoxPause.style.backgroundColor = "rgba(0,0,0,.7)";
  741. //手指移动相关
  742. var posStart = 0;//初始化起点坐标
  743. var posEnd = 0;//初始化终点坐标
  744. var posMove = 0;//初始化滑动坐标
  745. //轮播相关
  746. var index = [9, 8, 7, 6, 5, 4, 3, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9];
  747. var num = index.length;
  748. var timer = null; //用于清除计时器
  749. //直接开启轮播模式
  750. setTimer();
  751. function initEvent() {
  752. bt_recoding.addEventListener("touchstart", function (event) {
  753. event.preventDefault();//阻止浏览器默认行为
  754. posStart = 0;
  755. posStart = event.touches[0].pageY;//获取起点坐标
  756. //开始录音
  757. startRecord();
  758. //显示录音 隐藏暂停
  759. showBlackBoxSpeak();
  760. });
  761. bt_recoding.addEventListener("touchmove", function (event) {
  762. event.preventDefault();//阻止浏览器默认行为
  763. posMove = event.targetTouches[0].pageY;//获取滑动实时坐标
  764. if (posStart - posMove < 200) {
  765. //隐藏录音 显示暂停
  766. // alert('aaa');
  767. showBlackBoxSpeak();
  768. } else {
  769. //停止录音
  770. stopRecord();
  771. //显示录音 隐藏暂停
  772. showBlackBoxPause();
  773. IsSendAudio=false;
  774. // alert('停止录音取消发送');
  775. }
  776. });
  777. bt_recoding.addEventListener("touchend", function (event) {
  778. event.preventDefault(); //阻止浏览器默认行为
  779. posEnd = 0;
  780. posEnd = event.changedTouches[0].pageY;//获取终点坐标
  781. //初始化状态
  782. initStatus();
  783. if (posStart - posEnd < 200) {
  784. stopRecord();
  785. showBlackBoxNone();
  786. IsSendAudio=true;
  787. } else {
  788. showBlackBoxNone();
  789. IsSendAudio=false;
  790. }
  791. });
  792. }
  793. initEvent();
  794. //轮播
  795. function setTimer() {
  796. timer = setInterval(function () {
  797. setTimeout(function () {
  798. num++;
  799. blackBoxSpeak.style.background = "url('../img/ic_record@2x.png')no-repeat 28px 16px/64px 104px, url('../img/ic_record_ripple@2x-" + index[num] + ".png')no-repeat 111.2px 32px/28.8px 88px";
  800. blackBoxSpeak.style.backgroundColor = " rgba(0,0,0,.7)";
  801. }, 70);
  802. if (num >= index.length - 1) {
  803. num = 0;
  804. }
  805. }, 70);
  806. }
  807. //初始化状态
  808. var initStatus = function () {
  809. bt_recoding.value = '按住 说话';
  810. //全部隐藏
  811. showBlackBoxNone();
  812. }
  813. //显示录音 隐藏暂停
  814. var showBlackBoxSpeak = function () {
  815. bt_recoding.value = '松开 结束';
  816. blackBoxSpeak.style.display = "block";
  817. blackBoxPause.style.display = "none";
  818. }
  819. //隐藏录音 显示暂停
  820. var showBlackBoxPause = function () {
  821. bt_recoding.value = '松开手指,取消发送';
  822. blackBoxSpeak.style.display = "none";
  823. blackBoxPause.style.display = "block";
  824. }
  825. //隐藏录音
  826. var showBlackBoxNone = function () {
  827. blackBoxSpeak.style.display = "none";
  828. blackBoxPause.style.display = "none";
  829. }
  830. //拨打电话
  831. function chatChoose(){
  832. var btnArray = [{
  833. title: "手机电话"
  834. }/*, {
  835. title: "语音通话"
  836. },{
  837. title: "视频通话"
  838. }*/];
  839. plus.nativeUI.actionSheet({
  840. title: "你可以选择以下通话操作",
  841. cancel: "取消",
  842. buttons: btnArray
  843. }, function(e) {
  844. var index = e.index;
  845. switch (index) {
  846. case 0:
  847. break;
  848. case 1:
  849. //手机电话
  850. plus.device.dial(ToUserId, false);
  851. //mui.toast("手机电话开发中..");
  852. break;
  853. case 2:
  854. //语音通话
  855. mui.toast("语音通话开发中..");
  856. break;
  857. case 3:
  858. //视频通话
  859. mui.toast("视频通话开发中..");
  860. break;
  861. }
  862. });
  863. }
  864. //拨打电话
  865. function claer_chat(){
  866. var btnArray = [{
  867. title: "清空本地聊天记录"
  868. }, {
  869. title: "修改聊天背景"
  870. }/*,{
  871. title: "访问服务端聊天记录"
  872. }*/
  873. ];
  874. plus.nativeUI.actionSheet({
  875. title: "聊天设置",
  876. cancel: "取消",
  877. buttons: btnArray
  878. }, function(e) {
  879. var index = e.index;
  880. switch (index) {
  881. case 0:
  882. break;
  883. case 1:
  884. //清空本地聊天记录
  885. plus.storage.removeItem(ToUserId);
  886. location.reload();
  887. mui.toast("清空成功");
  888. break;
  889. case 2:
  890. var webview = mui.openWindow({
  891. url: 'chatBackground.html',
  892. extras: {
  893. toUserId: ToUserId, //扩展参数
  894. Name: name
  895. }
  896. });
  897. // mui.open("chatBackground.html");
  898. break;
  899. /*case 3:
  900. //访问服务端聊天记录
  901. mui.toast("访问服务端聊天记录..");
  902. break;*/
  903. }
  904. });
  905. }
  906. </script>

发表评论

表情:
评论列表 (有 1 条评论,830人围观)
蒲公英云5D8521
蒲公英云5D8521V铁粉 2022-10-10 03:09
楼主,方便分享下代码?学习下

相关阅读

    相关 WebSocket实现在线聊天

    这一篇文章前面部分我们会先介绍WebSocket协议的基本知识,在最后我们会用Spring Boot来集成WebSocket实现一个简单的在线聊天功能,单纯想看实现部分的话可以