概述
Svelte-Webchat 一款仿製微信網頁版類Mac介面聊天專案。使用最新技術棧svelte3.x+svelteKit+sass+mescroll+svelte-layer
等技術開發構建。別緻的dock可拖拽/左右滾動選單。
功能特效
✅經典Dock可滾動選單模式
✅流暢的操作體驗
✅可收縮/展開側邊
✅可全屏/恢復視窗、退出彈窗提示
✅豐富的視覺效果,自定義桌面虛化主題
✅自定義視覺化彈窗+滾動條,支援各種自定義定製開發。
技術棧
- 編輯器:Vscode
- 框架技術:Svelte^3.46.5+SvelteKit
- 狀態管理:svelte/store
- 下拉重新整理:mescroll.js
- 滾動條元件:svelte-scrollbar
- 對話方塊元件:svelte-layer
- sass預處理:sass^1.50.1+svelte-preprocess
svelte-webchat 還內建了朋友圈模組。
專案結構
非常清晰的分層目錄結構。
svelte自定義元件(彈窗+滾動條)
專案中無處不在的彈窗及滾動條功能,均是基於svelte.js自定義元件實現功能。
- svelte-layer 一款基於svelte3開發的網頁對話方塊元件
https://segmentfault.com/a/1190000041721778 - svelte-scrollbar 一款基於svelte.js虛擬美化滾動條元件
https://segmentfault.com/a/1190000041814107
由於之前有過相關分享文章,這裡就不詳細的介紹了。
svelte公共佈局模板
svelteKit提供了__layout.svelte
佈局模板及__error.svelte
錯誤處理頁面。
如上圖:整體佈局分為左側+右側內容區+底部dock選單。
<div class="sv__container flexbox flex-alignc flex-justifyc" style="--themeSkin: {$skin}">
<div class="sv__wrapper" class:maximize={$isWinMaximize}>
{#if $userinfo}
<div class="sv__board flexbox flex-col">
<!-- <div class="sv__topbar">頂部模組</div> -->
<div class="sv__mainwrap flex1 flexbox">
<!-- <div class="sv__sidebar">側邊欄</div> -->
<Middle />
<div class="sv__mainbx flex1 flexbox flex-col">
<Winbar />
<slot />
</div>
</div>
<Dock />
</div>
{:else}
<div class="sv__board flexbox flex-col">
<div class="sv__mainwrap flex1 flexbox">
<slot />
</div>
</div>
{/if}
</div>
</div>
<script context="module">
export function load({ error, status }) {
return {
props: { error, status }
}
}
</script>
<script>
import { goto } from '$app/navigation'
export let status
export let error
function goBack() {
// history.go(-1)
goto('/')
}
</script>
<svelte:head>
<title>{status} Error!</title>
</svelte:head>
<div class="sv__scrollview flex1">
<div class="sv__page-error flexbox flex-col flex-alignc flex-justifyc">
<div class="sv__page-error-img">
<img src="404.png" alt="" />
</div>
<div class="sv__page-error-content">
<div class="c-red fs-18">┗| {status} |┛ Page Error~~</div>
<div class="c-999 mt-10">{error.message}</div>
<div class="sv__btn sv__btn-default" style="color:#40b3ff;height:32px;width:120px;" on:click={goBack}><i class="iconfont icon-arrL"></i> 返回首頁</div>
</div>
</div>
</div>
svelte實現聊天
聊天編輯框支援多行文字、游標處插入內容,貼上截圖傳送圖片+拖拽傳送圖片。
編輯框監聽paste事件
editorEl.addEventListener('paste', function(e) {
e.preventDefault()
let cbd = e.clipboardData
let ua = window.navigator.userAgent
if(!(e.clipboardData && e.clipboardData.items)) return
if(cbd.items && cbd.items.length === 2 && cbd.items[0].kind === "string" && cbd.items[1].kind === "file" &&
cbd.types && cbd.types.length === 2 && cbd.types[0] === "text/plain" && cbd.types[1] === "Files" &&
ua.match(/Macintosh/i) && Number(ua.match(/Chrome\/(\d{2})/i)[1]) < 49){
return;
}
for(var i = 0; i < cbd.items.length; i++) {
var item = cbd.items[i]
// console.log(item)
// console.log(item.kind)
if(item.kind == 'file') {
var blob = item.getAsFile()
if(blob.size === 0) return
// 讀取圖片記錄
var reader = new FileReader()
reader.readAsDataURL(blob)
reader.onload = function() {
var imgpath = this.result
// 返回圖片給父元件
dispatch('paste', imgpath)
}
}
}
})
svelte拖拽上傳
/**
* svelte拖拽上傳圖片
* author:andy Q:282310962
*/
function handleDragEnter(e) {
e.stopPropagation()
e.preventDefault()
}
function handleDragOver(e) {
e.stopPropagation()
e.preventDefault()
}
function handleDrop(e) {
e.stopPropagation()
e.preventDefault()
handleFileList(e.dataTransfer)
}
// 拖拽檔案列表
function handleFileList(filelist) {
let files = filelist.files
if(files.length >= 2) {
svLayer.message({content: '暫時支援拖拽一張圖片', icon: 'error', time: 0, xclose: true, shade: true})
return false
}
for(let i = 0; i < files.length; i++) {
if(files[i].type != '') {
handleFileAdd(files[i])
}else {
svLayer.message({content: '目前不支援資料夾拖拽功能', icon: 'error', time: 0, xclose: true, shade: true})
}
}
}
function handleFileAdd(file) {
let len = msgList.length
// 訊息佇列
let msgArr = {
id: `msg_${++len}`,
msgtype: 5,
isme: true,
avatar: '/uimg/img-avatar08.jpg',
author: 'Hison',
msg: '',
imgsrc: '',
videosrc: ''
}
if(file.type.indexOf('image') == -1) {
svLayer.message({content: '目前不支援非圖片拖拽功能', icon: 'error', time: 0, xclose: true, shade: true})
}else {
let reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = async function() {
let img = this.result
msgArr.imgsrc = img
msgList = msgList.concat(msgArr)
await tick()
scrollBottom()
}
}
}
OK,基於svelte.js開發仿微信web版聊天例項就分享到這裡。
最後附上兩個最新例項專案
https://segmentfault.com/a/1190000041357547
https://segmentfault.com/a/1190000040015181