先上效果图: 用户登录以后,就可以像服务端发送文字,或者图片;输入文字的时候,点击发送就可以了,如果发送图片,点击发送图片,选择图片后,会自动发送图片到服务器端;
用户名:
密 码:
发送文字:
发送图片:
var Im_Name=document.getElementById("Im_Name");
var Im_PassWord=document.getElementById("Im_PassWord");
var textField=document.getElementById("textField");
var send = document.getElementById("send");
var login = document.getElementById("login");
var result=document.getElementById("result");
var result1 = document.getElementById("result1");
var socketStatus = false;
var globalBufferIndex='';
var websocket = null, tick_heartpac;
var timerID = '';
var globaldataindex = '';
var globalBuffer = '';
var globalBuffer_REVICE = '';
var Message_data = "";
var segment = 50 * 1024;
function F_Open_dialog() {
document.getElementById("Imagg_File").click();
}
function print(text) {
result1.innerHTML = (new Date).getTime() + ": " + text + result1.innerHTML+"
";;
}
function initSocket(option) {
//服务器地址
layer.msg("建立连接中...");
var locate = window.location;
var url = option.url ? option.url : "ws://" + locate.hostname + ":" + locate.port + _get_basepath() + "/websocket";
//回调函数
var callback = option.callback;
if (typeof callback !== "function") {
layer.msg('callback 必须为函数');
return false;
}
//一些对浏览器的兼容已经在插件里面完成
websocket = null;
websocket = new ReconnectingWebSocket(url);
//连接发生错误的回调方法
websocket.onerror = function () {
socketStatus = false;
layer.msg("websocket.error");
};
//连接成功建立的回调方法
websocket.onopen = function (event) {
Heart(!0);
//websocket.send("User_Name|zhang")
socketStatus = true;
//t1 = setInterval(tanchuang, 3000);
}
//接收到消息的回调方法
websocket.onmessage = function (event) {
if (event.data != "@heart")
callback(event.data);
}
//连接关闭的回调方法
websocket.onclose = function () {
Heart(!1);
socketStatus = false;
layer.msg("websocket Server error");
websocket.close();
//if (websocket.readyState == 3) websocket.close();
//setInterval(initSocket(option), 3000);
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
socketStatus = false;
websocket.close();
}
websocket.onerror = function (evnt) {
socketStatus = false;
websocket.close();
};
return websocket;
}
$(function () {
var option = {
url: $("#socketAddress").val(),
callback: function (msg) {
console.log(msg);
//处理业务逻辑
var msg_data = eval("(" + msg + ")");//转换为json对象
//$.each(msg_data, function (index, item) {
// $("#info").append(
// "
// "
//});
//layer.msg("数据接收成功" + msg_data.Message);
if (msg_data.Message_Type == "0") {
print("[onmessage] '" + msg_data.Message + "'\n");
}
else if (msg_data.Message_Type == "999") {
layer.msg("登录成功\n");
localStorage.setItem("Im_Id", msg_data.Im_PassWord);
}
else if (msg_data.Message_Type == "-1") {
layer.msg("登录失败\n");
}
else if (msg_data.Message_Type == "1") {
unpackagedata(msg_data.Message);
}
}
};
initSocket(option);
send.onclick = function () {
if (localStorage.getItem("Im_Id") == "") {
layer.msg("您还没有登录!")
return;
}
alert(localStorage.getItem("Im_Id"));
var Message = textField.value;
Message_data = "{ 'Send_Id': '" + localStorage.getItem("Im_Id") + "', 'To_Id': '10067', 'Message_Type': '0', 'Message': '" + Message + "' }";
"" != Message && (websocket && 1 == websocket.readyState ? (Heart(!0), websocket.send(Message_data), print("[send] '" + Message + "'\n"), $("#textField").val(""), Heart(!0)) : layer.msg("连接已经断开!"))
};
login.onclick = function () {
var Im_Name1 = Im_Name.value;
var Im_PassWord1 = Im_PassWord.value;
Message_data = "{ 'Im_Name': '" + Im_Name1 + "', 'Im_PassWord': '" + Im_PassWord1 + "', 'Message_Type': '-1'}";
"" != Im_Name1 && (websocket && 1 == websocket.readyState ? (Heart(!0), websocket.send(Message_data), Heart(!0)) : layer.msg("连接已经断开!"))
};
})
function Heart(a) {
a ? tick_heartpac = setInterval(function () {
websocket.send("@heart")
},
3e4) : (clearInterval(tick_heartpac), tick_heartpac = null)
}
// 用于压缩图片的canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext('2d');
// 瓦片canvas
var tCanvas = document.createElement("canvas");
var tctx = tCanvas.getContext("2d");
var maxsize = 100 * 1024;
var result = document.getElementById("result");
var input = document.getElementById("Imagg_File");
if (typeof FileReader === 'undefined') {
result.innerHTML = "抱歉,你的浏览器不支持 FileReader";
input.setAttribute('disabled', 'disabled');
} else {
input.addEventListener('change', readFile, false);
}
function readFile() {
var file = this.files[0];
// if (!/image\/\w+/.test(file.type)) {
// alert("请确保文件为图像类型");
// return false;
// }
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function() {
var result = this.result;
var img = new Image();
img.src = result;
//如果图片大小小于100kb,则直接上传
if (result.length <= maxsize) {
img = null;
sendpicdata(this.result);
return;
}
//图片加载完毕之后进行压缩,然后上传
if (img.complete) {
callback();
} else {
img.onload = callback;
}
function callback() {
var data = compress(img);
sendpicdata(data);
img = null;
}
};
}
function sendpicdata(txt) {
if (timerID == '') {
globaldataindex='';
globalBuffer='';
globalBuffer = packagedata(txt);
Message_data ="{ 'Send_Id': '" + localStorage.getItem("Im_Id") + "', 'To_Id': '10067', 'Message_Type': '1', 'Message': '" + globalBuffer[0] + "' }";
websocket.send(Message_data);
//layer.msg(globalBuffer[0]);
globalBufferIndex = 1;
timerID = setInterval(sendBufferInterval, 1000);
}
}
function sendBufferInterval() {
if (globalBufferIndex < (globalBuffer.length)) {
Message_data = "{ 'Send_Id': '" + localStorage.getItem("Im_Id") + "', 'To_Id': '10067', 'Message_Type': '1', 'Message': '" + globalBuffer[globalBufferIndex] + "'}";
websocket.send(Message_data);
//layer.msg(globalBuffer[globalBufferIndex]);
globalBufferIndex += 1;
}
else {
clearInterval(timerID);
timerID = '';
}
}
function hexToString(num) {
var val = "";
var str = num.toString(16);
if (str.length < 4) {
for (var i = 0; i < (4 - str.length) ; i++) {
val += '0';
}
}
val += str;
return val;
}
function packagedata(data) {
var buffer = new Array();
var length = data.length;
alert(length);
if (length > segment) {
var packagecount = 0;
var packagefloor = 0;
packagecount = Math.ceil(length / (segment));
packagefloor = Math.floor(length / (segment));
for (var i = 0; i < packagefloor; i++) {
buffer[i] = '0001';
buffer[i] += '0000';
buffer[i] += hexToString(packagecount);
buffer[i] += hexToString(i + 1);
buffer[i] += data.substr(segment * i, segment);
}
if (packagecount > packagefloor) {
buffer[packagecount - 1] = '0001';
buffer[packagecount - 1] += '0000';
buffer[packagecount - 1] += hexToString(packagecount);
buffer[packagecount - 1] += hexToString(packagecount);
buffer[packagecount - 1] += data.substr(segment * (packagecount - 1), length % (segment));
}
}
else {
buffer[0] = '0001';
buffer[0] += '0000';
buffer[0] += '0001';
buffer[0] += '0001';
buffer[0] += data;
}
return buffer;
}
function unpackagedata(buffer) {
var data = new Array();
data[0] = buffer.substr(0, 4);//0001
data[1] = buffer.substr(4, 4);//0000
data[2] = buffer.substr(8, 4);//0001
data[3] = buffer.substr(12, 4);//0001
data[4] = buffer.substr(16);
//layer.msg(buffer);
view(data);
}
function view(data) {
debugger;
if (data[2] == data[3]) {
if (globaldataindex > data[3]) {
globaldataindex = '';
}
else {
globaldataindex = data[3];
globalBuffer_REVICE += data[4];
//layer.msg(globalBuffer_REVICE);
//alert(globalBuffer_REVICE);
result1.innerHTML +='';
globalBuffer_REVICE = '';
globaldataindex = 'ffffffff';
}
}
else {
if (globaldataindex == data[3]) {
}
else {
alert(globalBuffer_REVICE);
globaldataindex = data[3];
globalBuffer_REVICE += data[4];
}
}
}
// 使用canvas对大图片进行压缩
function compress(img) {
var initSize = img.src.length;
var width = img.width;
var height = img.height;
//如果图片大于四百万像素,计算压缩比并将大小压至400万以下
var ratio;
if ((ratio = width * height / 4000000) > 1) {
ratio = Math.sqrt(ratio);
width /= ratio;
height /= ratio;
} else {
ratio = 1;
}
canvas.width = width;
canvas.height = height;
// 铺底色
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, canvas.width, canvas.height);
//如果图片像素大于100万则使用瓦片绘制
var count;
if ((count = width * height / 1000000) > 1) {
count = ~~(Math.sqrt(count) + 1); //计算要分成多少块瓦片
// 计算每块瓦片的宽和高
var nw = ~~(width / count);
var nh = ~~(height / count);
tCanvas.width = nw;
tCanvas.height = nh;
for (var i = 0; i < count; i++) {
for (var j = 0; j < count; j++) {
tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
}
}
} else {
ctx.drawImage(img, 0, 0, width, height);
}
//进行最小压缩
var ndata = canvas.toDataURL('image/jpeg', 0.6);
console.log('压缩前:' + initSize);
console.log('压缩后:' + ndata.length);
console.log('压缩率:' + ~~(100 * (initSize - ndata.length) / initSize) + "%");
tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
return ndata;
}
图片过分的大的时候需要分段发送;也可以进行图片压缩;图片的分段和压缩借鉴了网上一些js代码,谢谢各位的无偿奉献;
服务端使用mina开发的;两个客户端通过服务端转发就可以聊天了。
如果大家有好的web端设计或者想法,可以联系。