metadesktop
v0.1.3
Published
js元桌面 基于vue的框架,实现web桌面系统
Downloads
73
Readme
更新
1. 引入文件 import { metadesktop } from 'metadesktop' 修改为 import { metadesktop } from MetaDesktop'
介绍
metadesktop是一个基于vue3的框架,中文名称云桌面,一个用于在web端实现与window系统类似的桌面管理系统
开始使用
安装
metadesktop框架依赖于vue3构建工具,在使用之前,确保自己的vue版本为3及以上版本
npm install metadesktop
在vue3项目中引入
在vue项目的入口文件main.js中引入两个相关依赖文件,metadesktop.js和metadesktop.css
import { MetaDesktop } from 'metadesktop'
import 'metadesktop/dist/metadesktop.css'
使用 Vue.use 进行安装
createApp(App).use(MetaDesktop).mount('#app')
如果你使用了其他第三方插件,并不会对系统产生影响,可以放心使用,比如下面使用了vuex和vue-router
createApp(App).use(metadesktop).use(store).use(router).mount('#app')
main.js 完整代码:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import { metadesktop } from 'metadesktop'
import 'metadesktop/dist/metadesktop.css'
createApp(App).use(metadesktop).use(store).use(router).mount('#app')
创建桌面
metadesktop内置了一个MetaDesktop组件,他是metadesktop系统的入口组件,我们在App.vue中使用它
<template>
<div id="app">
<MetaDesktop/>
</div>
</template>
我们使用浏览器查看当前项目,会发现桌面上可能什么也没有,这是因为MetaDesktop组件的大小依赖于父元素的大小,我们给 id="app"的div设置css属性,让他铺满整个浏览器窗口
<style lang="less">
#app{
width: 100vw;
height: 100vh;
}
</style>
我们重新打开浏览器,如果看到左下脚的window图标,就证明创建桌面成功了。此时的桌面一片空白,是因为我们还没有加入我们自己的桌面图标,后面会详细介绍。
App.vue 完整代码:
<template>
<div id="app">
<MetaDesktop/>
</div>
</template>
<script>
export default {
}
</script>
<style lang="less">
#app{
width: 100vw;
height: 100vh;
}
</style>
Application应用类、ApplicationManage管理类和 MetaWindow 窗口类
我们先来看一个例子,以此来了解这两个类。 在app.vue组件的生命周期函数 mounted 中加入如下代码。
let appManege = this.$System.getApplicationManage();
appManage.addApplicationWeb({
title:"哔哩哔哩",
icon: "https://www.bilibili.com/favicon.ico?v=1",
href :"https://www.bilibili.com/"
})
如果你是国内的话,你可以看到,我们创建的桌面上出现了哔哩哔哩的图标,点击图标,弹出了一个窗口,内容为哔哩哔哩网站的内容。如果是在国外,你可以随意找一个网站。
上面的代码,通过$System的getApplicationManage函数获取了一个ApplicationManage对象,不难猜出ApplicationManage对象是用来管理应用的。
Application对象是用来生成 MetaWindow 窗口的,所以需要创建一个MetaWindow 窗口之前,就需要创建一个Application对象。Application对象生成窗口需要依赖一个vue的组件,以组件内容生成窗口,而上面可以直接使用网站生成窗口,是因为内部已经默认使用了一个Web组件,通过iframe来加载网页。
Application对象生成窗口会返回一个MetaWindow 对象,通过MetaWindow 对象可以操作生成的MetaWindow窗口,在组件中,可以通过props获取到对应的MetaWindow 对象。
1.ApplicationManage
ApplicationManage里需要关注的方法只有三个:addApplication,addApplicationWeb,remove。 addApplication和addApplicationWeb都是用来创建应用,而remove是用来移除应用,addApplication需要传递一个组件对象,而addApplicationWeb不需要,因为addApplicationWeb是addApplication的一个特例,内部已经使用了Web组件,Web组件是内部的一个用来加载网页组件。
addApplication
// addApplication(Object component,Bool showDesktop)
// component: vue组件
// showDesktop:可选, 应用图标是否显示在桌面上
// return: Application 对象
addApplicationWeb
// addApplicationWeb(Object value,Bool showDesktop)
// value: 传递值对象,title:标题,icon:图标,href:网址
// showDesktop: 应用图标是否显示在桌面上
// return: Application 对象
remove
// remove(Application application)
// application: 需要移除的应用对象
2.Application
Application对象里,需要现在关注的只有一个:open,用来启动一个新窗口,一个应用可以启动多个窗口,不过因为默认只能启动一个窗口,所以现在只能启动一个,想要启动多个,后面会提到,open按需要可以传递一个值对象。 open
// open(Object value)
// value:可选,传递值对象
// return: MetaWindow 对象
3.MetaWindow
MetaWindow 里需要关注的东西有点多,有窗口配置WindowConfig,关闭窗口、隐藏窗口、全屏窗口函数,事件Event。
(1). WindowConfig对象里有很多属性,用来设置窗口,所有属性看下面的表。设置WindowConfig推荐在组件中设置。
export default {
windowConfig:{
windowWidth:"600px",
windowHeight: "90%",
showBottomBar: false,
showTitleBar: false,
isBoxShadow: false,
isOverflow: false,
showAddmin: false,
showDesktop: false,
},
data() {
return {
}
},
mounted(){},
}
属性
| 属性名 | 描述 | 类型| 默认值| |--|--|--|-- | icon | 窗口的图标,是一个资源地址或svg代码 | string | 默认图标 | icon_svg | 是否启用svg图标,如果启用,icon的内容应该是svg代码而非资源地址 |bool|false |showTitleBar |是否显示tar栏|bool|true | title | 窗口名称 |string|null | titleBarBackground | 标题栏背景 |string|null |titleBarFontColor|标题字体颜色|string|null | titleBarFontSize | 标题字体大小,必须带单位 |string|null | titleBarFontWeight | 标题字体粗细 |string|null |titleBarFontFamily |标题字体|string|null | titleBarCancelBackground | 标题栏 关闭窗口按钮 背景色 |string|null | titleBarFullScreenBackground | 标题栏 全屏窗口按钮 背景色 |string|null |titleBarHideBackground|标题栏 隐藏窗口按钮 背景色|string|null | windowTop | 窗口距离桌面顶部位置,必须带单位 |string|null | windowLeft | 窗口距离桌面左边位置,必须带单位 |string|null |windowBottom |窗口距离桌面低部位置,必须带单位 |string|null | windowRight | 窗口距离桌面右边位置,必须带单位 |string|null | windowWidth | 窗口宽度,必须带单位 |string|null |windowHeight | 窗口高度,必须带单位 |string|null | windowMaxWidth | 窗口最大宽度,必须带单位 |string|null | windowMaxHeight | 窗口最大高度,必须带单位 |string|null |windowMinWidth | 窗口最小宽度,必须带单位|string|null | windowMinHeight | 窗口最小高度,必须带单位 |string|null |maxCountWindow|应用最大可打开窗口数量 |number|1 | fullScreen | 窗口是否全屏 |bool|false |isBoxShadow|是否使用用窗口阴影|bool|true |isBoxShadow|是否对超出窗口部分进行裁剪 |bool|true |isReSetSize|是否可以更改窗口大小 |bool|true |isSizeZero|窗口大小可以为0 |bool|false |menu|窗口启动时底部导航栏显示菜单 |array|[] |appMenu|桌面应用图标显示菜单 |array|[] |showAddmin|应用图标是否显示到应用管理界面 |bool|true |showDesktop|应用图标是否显示到桌面 |bool|true |showBottomBar|应用图标是否显示到底部导航栏 |bool|true |isCloseDestroy|是否在应用应窗口全部关闭后销毁图标 |bool|false
(2). 关闭窗口close、隐藏窗口hide、全屏窗口fullScreen
let appManege = this.$System.getApplicationManage();
let app = appManage.addApplicationWeb({
title:"哔哩哔哩",
icon: "https://www.bilibili.com/favicon.ico?v=1",
href :"https://www.bilibili.com/"
})
let metaWindow = app.open();
// 关闭窗口
metaWindow.close();
// 隐藏窗口
metaWindow.hide();
// 显示窗口
metaWindow.hide(false);
// 全屏窗口
metaWindow.fullScreen();
// 取消全屏窗口
metaWindow.fullScreen(false);
上面代码中的例子可以一个一个的试一下,暂时可以以定时器来进行调用。
let appManege = this.$System.getApplicationManage();
let app = appManage.addApplicationWeb({
title:"哔哩哔哩",
icon: "https://www.bilibili.com/favicon.ico?v=1",
href :"https://www.bilibili.com/"
})
let metaWindow = app.open();
// 隔2秒后关闭窗口
setTimeout(()=>{
metaWindow.close();
},2000)
(3.) 事件Event 事件用于对窗口的一些特定的行为进行监听,如关闭窗口close、隐藏窗口hide、全屏窗口fullScreen,监听的是执行动作之前,所以可以利用这对默认行为进行拦截。
let appManege = this.$System.getApplicationManage();
let app = appManage.addApplicationWeb({
title:"哔哩哔哩",
icon: "https://www.bilibili.com/favicon.ico?v=1",
href :"https://www.bilibili.com/"
})
let metaWindow = app.open();
metaWindow.on("onClose",()=>{
console.log("检查到窗口即将关闭");
})
metaWindow.on("onHide",({newV})=>{
if(!newV) console.log("检查到窗口即将隐藏");
else console.log("检查到窗口即将显示");
})
metaWindow.on("onFullScreen",({newV})=>{
if(newV) console.log("检查到窗口即将全屏");
else console.log("检查到窗口即将取消全屏");
})
onClose回调函数不会传递任何值,而onHide和onFullScreen会传递一个值对象,可以根据值对象里的属性newV和oldV,判断隐藏和全屏的状态。
自定义事件 如果需要自定义一个事件,可以用 emit 方法,如果你对vue熟悉,应该对emit 很熟悉。
let appManege = this.$System.getApplicationManage();
let app = appManage.addApplicationWeb({
title:"哔哩哔哩",
icon: "https://www.bilibili.com/favicon.ico?v=1",
href :"https://www.bilibili.com/"
})
let metaWindow = app.open();
// 自定义 onCloseTime 事件,事件名称可以根据自己需要定义
metaWindow.on("onCloseTime",(res)=>{
console.log("关闭时间",res);
})
metaWindow.on("onClose",()=>{
// 触发 onCloseTime 事件,并传递一个值
metaWindow.emit("onCloseTime",new Date().getTime());
})
下面,我们通过一个例子来看看创建窗口的完整流程,以及metaWindow的使用。
首先,创建一个vue组件Test.vue,放到component文件夹下面,内容如下:
<!-- Test.vue -->
<template>
<div class="test">
<button @click="metaWindow.close()">关闭窗口</button>
<button @click="metaWindow.fullScreen(true)">全屏</button>
<button @click="metaWindow.fullScreen(false)">取消全屏</button>
<button @click="metaWindow.hide(false)">隐藏</button>
<button @click="metaWindow.hide(true)">取消隐藏</button>
<button @click="metaWindow.emit('message','傻子')">自定义事件message</button>
</div>
</template>
<script>
export default {
// 在此处配置窗口属性
windowConfig:{
windowWidth : "600px",
windowHeight : "600px",
windowTop : "100px",
windowLeft : "100px",
title:"测试",
icon: require("@/assets/test.png")
},
props:["metaWindow"],// 通过props 获取到 metaWindow对象
mounted() {
this.metaWindow.on("onClose",()=>{
console.log("检查到窗口即将关闭");
})
this.metaWindow.on("onHide",({newV})=>{
if(!newV) console.log("检查到窗口即将隐藏");
else console.log("检查到窗口即将显示");
})
this.metaWindow.on("onFullScreen",({newV})=>{
if(newV) console.log("检查到窗口即将全屏");
else console.log("检查到窗口即将取消全屏");
})
// 自定义事件 message
this.metaWindow.on("message",(msg)=>{
console.log(msg);
})
},
}
</script>
<style>
.test{
width: 100%;
height: 100%;
background: white;
}
</style>
在app.vue中引入Test组件,并且使用Test组件
<template>
<div id="nav">
<MetaDesktop/>
</div>
</template>
<script>
import Test from "@/components/Test.vue"
export default {
data(){
return {}
},
mounted(){
let app = this.$System.getApplicationManage();
app.addApplication(Test);
}
</script>
<style>
body{
position: relative;
width: 100vw;
height: 100vh;
}
#nav{
position: relative;
width: 100vw;
height: 100vh;
}
</style>
然后启动项目,点击桌面上的测试图标,打开一个窗口,内容为 Test.vue 的内容,点击几个按钮,感受一下吧。
子窗口ChildMetaWindow
在浏览器里,很多时候我们页面切换的方式都是通过地址栏,然而,在Metadesktop的系统里,我们可以打开很多个功能不同的应用,它们各自有着不同的页面需要切换,这个时候,一个地址栏就不够用了。 那我们应该如何解决呢? Metadesktop的系统提供了两种方法,子窗口和页面路由,两个可以单独使用也可以混合使用,我们先来看看如何编写子窗口。
首先需要清楚的一点是,子窗口是存在于MetaWindow窗口中,我们先创建一个MetaWindow窗口。
在components文件夹下创建两个文件childWindowHome.vue和selectAddress.vue
在selectAddress.vue写入如下代码:
<template>
<div class="select-address">
<ul>
<li v-for="item in addressList" :key="item" @click="select(item)">{{item}} </li>
</ul>
</div>
</template>
<script>
export default {
childWindowConfig:{
title:"选择地址",
titleBarTitlePosition:"center"
},
inject:["childMetaWindow"],
data() {
return {
addressList:["云南","贵州","广州","上海","重庆"]
}
},
methods: {
select(address){
this.childMetaWindow.value.address = address;
this.childMetaWindow.emit("close");
}
},
}
</script>
<style scoped>
.select-address{
width: 100%;
height: 100%;
background: white;
}
.select-address ul li{
padding: 10px 20px;
transition: 0.25s;
cursor: pointer;
}
.select-address ul li:hover{
background: whitesmoke;
}
</style>
在MetaWindow窗口中,使用了windowConfig来进行设置窗口属性,而在子窗口中,通过childWindowConfig来设置。
在childWindowHome.vue中写入如下代码
.<template>
<div class="child-window-home">
<ul>
<li><h3>下单确认</h3></li>
<li><button @click="toSelectAddress">选择地址</button><p>{{address}}</p> </li>
<li><h5>商品列表</h5></li>
<li><span>草莓</span><span>x1</span></li>
<li><span>苹果</span><span>x1</span></li>
<li><span>梨</span><span>x1</span></li>
</ul>
</div>
</template>
<script>
import selectAddress from "@/components/selectAddress.vue";
export default {
windowConfig:{
windowWidth: "300px",
windowHeight: "500px",
title:"子窗口测试",
icon: "",//写入自己的图片路径
},
data() {
return {
address:""
}
},
inject:["System"],
mounted() {
},
methods: {
toSelectAddress(){
let w = this.System.push(selectAddress,{
address: this.address
}).addEvent("onClose",()=> {
this.address = w.value.address;
})
}
},
}
</script>
<style scoped>
.child-window-home{
width: 100%;
height: 100%;
background: whitesmoke;
}
.child-window-home ul li{
display: flex;
padding: 5px;
}
.child-window-home ul li h3{
text-align: center;
}
.child-window-home ul li span{
width: 50%;
}
.child-window-home ul li button{
margin-right: 80px;
}
.child-window-home ul li >span:last-child{
text-align: right;
}
</style>
写好了这两个文件,然后我们把 childWindowHome.vue 使用桌面图标来启动,这里就不介绍如何使用桌面图标来启动,记不得可以回去看看如何创建桌面图标的教程。
然后我们点击图标,打开 childWindowHome 组件的窗口页面,点击选择地址按钮,弹出了一个子窗口,内容是我们 selectAddress 组件中的内容,点击任意一个地址,就回到了主窗口的位置,我们可以看到,在选择按钮的右边出现了我们刚刚点击的地址,这个例子展示了如何创建子窗口、主窗口如何与子窗口通信以及如何关闭子窗口。
有了上面的例子,对子窗口就有了一定的认识,接下来我们来仔细的认识子窗口。
操作子窗口,并不需要像主窗口一样,需要获取一个管理类,而是在主窗口生成时就会自动创建一个ChildSystem 对象,这个对象通过vue的inject注入功能获取,属性名为System,要和全局的$System区分开。
export default {
inject:["System"],
}
ChildSystem 对象里面有五个方法push,replace,pop,back,remove用来对子窗口进行生成和删除。
应用功能管理类--ApplicationManage
我们一开始的时候已经用过该类,创建桌面图标的时候。现在我们来详细讲解一下该类。 我们知道,通过$System我们可以拿到该类的实例
const appManage = this.$System.getApplicationManage();
我们来看看它具体有哪些方法供我们使用
- add
// add(name,icon,model, component)
// name(必须): 应用名称
// icon(必须): 应用图标
// model(必须): 模式,0-组件模式,1-web模式,2-自定义模式。组件模式可以把传入的组件渲染成窗 口,web模式把网络地址对应页面渲染成窗口,自定义模式根据自己需求进行定制
// component(可选): vue组件
// 返回值: Application对象
import Test from "@/components/Test.vue"
appManage.add('Test',require("@/assets/test.png"),Test);
如果模式为web模式或者自定义模式,请使用返回的Application对象更改。
如果是web模式,调用setValue方法设置地址、图标、标题,这几个属性是MetaWindow窗口的图标、标题,上面设置的是桌面的图标和标题
Application.setValue({
href:'https://git-scm.com/',
icon:'https://git-scm.com/images/[email protected]',
title:'git'
});
如果是自定义模式,调用setAction,指定点击图标的回调函数
Application.setAction(()=>{
// 点击图标需要执行的代码
});
- addComponent
// addComponent(component)
// component(必须): vue组件
// 返回值: Application 对象
import Test from "@/components/Test.vue"
appManage.addComponent(Test);
该方法的默认模式为0。只需要传入一个组件,所有的配置通过组件内部的windowConfg进行配置。
export default{
name:"Test",
windowConfig:{
title: "Test",
icon: require'@/assets/test.png')
}
}
- addWeb
// addWeb(value)
// value(必须): 配置:地址、图标、标题
// 返回值: Application 对象
appManage.addWeb({
href:'https://git-scm.com/',
icon:'https://git-scm.com/images/[email protected]',
title:'git'
});
该方法的默认模式为1 4. addCustom
// addCustom(object value,function action)
// value:一个js的数据对象,用于指定图标和名称
// action:当我们点击桌面图标时触发的函数
// 返回值: Application 对象
appManage.addCustom({
title:"测试",
icon: require("@/assets/01.png") // 图标换成你自己的即可
},function(){
console.log("我被点击了");
});
该方法的默认模式为2。
桌面背景管理类--DesktopBackgroundManage
这个类用于对桌面的背景进行设置,可以设置成纯色背景、渐变背景、图片背景、动态背景(视频背景),四种方式。 下面,我们来一一介绍这四种方式。
- 纯色背景 首先,通过$System拿到DesktopBackgroundManage管理类
const dBManage = this.$System.DesktopBackgroundManage();
然后通过管理类里的方法setColor来设置背景色
// setColor(color)
// color: 颜色值
dBManage.setColor("pink"); // 定义自己的颜色就行
设置完颜色,我们还需要设置背景模式为纯色模式
// setModel(model)
// model: 背景模式,0:纯色模式,1:渐变模式,2:图片模式,3:动态模式
dBManage.setModel(0);
如果需要把颜色重置为默认值,可以使用defaultColor方法
// defaultColor()
dBManage.defaultColor();
- 渐变模式 通过管理类里的方法setRradientColor设置渐变色
// setRradientColor(angle,...color)
// angle: 渐变的角度
// ...color: 渐变的颜色,可以是一个或多个值
dBManage.setRradientColor(45,"rgb(204, 251, 255)","rgb(239, 150, 197)");
然后设置背景模式为渐变模式
// setModel(model)
// model: 背景模式,0:纯色模式,1:渐变模式,2:图片模式,3:动态模式
dBManage.setModel(1);
如果需要单独设置渐变角度,可以使用setRradientAngle方法
// setRradientAngle(angle)
// angle: 渐变的角度
dBManage.setRradientAngle(50);
如果需要把渐变色重置为默认值,可以使用defaultRradientColor方法
// defaultRradientColor()
dBManage.defaultRradientColor();
- 图片背景 需要使用pushImage方法将图片路径加入图片管理数组中
// pushImage(src)
// src: 图片路径
dBManage.pushImage(require'@/assets/bg.jpg'))
加入后把背景模式设置为图片模式
// setModel(model)
// model: 背景模式,0:纯色模式,1:渐变模式,2:图片模式,3:动态模式
dBManage.setModel(2);
因为图片可能有很多张,可以使用setImageIndex方法进行图片切换
// setImageIndex(index)
// index: 图片在数组中的索引
dBManage.setImageIndex(1);
有的时候,需要清空图片数组,可以使用clearImage方法
// clearImage()
dBManage.clearImage()
如果需要把重置图片设置,可以使用defaultImage方法
// defaultImage()
dBManage.defaultImage();
- 动态背景 需要使用pushVideo方法将图片路径加入图片管理数组中
// pushVideo(src)
// src: 视频路径
dBManage.pushVideo(require'@/assets/bg.MP4'))
加入后把背景模式设置为动态模式
// setModel(model)
// model: 背景模式,0:纯色模式,1:渐变模式,2:图片模式,3:动态模式
dBManage.setModel(3);
因为视频可能有很多,可以使用setVideoIndex方法进行图片切换
// setVideoIndex(index)
// index: 视频在数组中的索引
dBManage.setVideoIndex(1);
有的时候,需要清空视频数组,可以使用clearVideo方法
// clearVideo()
dBManage.clearVideo()
如果需要把重置动态设置,可以使用defaultVideo方法
// defaultVideo()
dBManage.defaultVideo();
底部导航栏管理类--BottomBarManage
需要通过$system中的getBottomBarManage方法获取该类。这个类可以更改底部导航栏的背景色、激活图标背景色。
- setBackground
// 修改背景色
// setBackground(color)
// color: 需要设置的颜色
const bottomBarManage = this.$System.getBottomBarManage();
bottomBarManage.setBackground("#fff");
- setIconBackground
// 修改激活图标背景色
// setIconBackground(color)
// color: 需要设置的颜色
const bottomBarManage = this.$System.getBottomBarManage();
bottomBarManage.setIconBackground("#fff");
如果需要对设置进行恢复默认值,可以使用defaultSetting方法
// 恢复默认值
// defaultSetting()
const bottomBarManage = this.$System.getBottomBarManage();
bottomBarManage.defaultSetting();
系统通知管理类--NoticeManage
在MetaDesktop的右下角,有一个留言样式的图标,我们点击它,会弹出一个窗口,而NoticeManage类就是用来操作该窗口。这个类能操作的有三个方法setBackground、add和close。setBackground用来改变窗口的背景色,而add是用来添加一条通知,添加通知需要一个通知组件模板,close用来移除通。通过$System 的getNoticeManage方法获取该管理类
- setBackground
// setBackground(color)
// color: 颜色
const noticeManage= this.$System.getNoticeManage();
noticeManage.setBackground("#00ff00");
- add
// add(value,component)
// value: 需要传递到模板中的值
// component: 组件模板,默认值为内置的一个通知模板,需要传递title和msg
// 返回值:id,通知唯一标识id
const noticeManage= this.$System.getNoticeManage();
noticeManage.add({
title:"重要提醒!",
msg:"数据库v那就是看到女"
});
在模板组件内使用props来获取传递的value值
export default {
props:["value"]
}
- close 添加了通知,close函数把通知从通知列表里移除,close需要传递一个id值,这个id是add的时候返回的。
// close(id)
// id: 通知唯一标识id
const noticeManage= this.$System.getNoticeManage();
let id = noticeManage.add({
title:"重要提醒!",
msg:"数据库v那就是看到女"
});
//隔5s关闭该条通知
setTimeout(()=>{
noticeManage.close(id);
},5000)
在模板组件内部,可以通过props和inject获取id和close函数
export default {
props:["value","id"],
inject:["close"],
}