使用JS+HTML+CSS模拟操作系统

实现效果

模拟操作系统演示

主要功能

  • 桌面右键功能(新建文件夹、更改桌面背景,粘贴)
  • 文件夹右键功能(打开、复制、删除、重命名)
  • 浏览器功能
  • 回收箱功能

实现思路

主要依靠CSS布局以及JS的DOM操作来完成,包括删除、复制DOM节点,控制DOM元素的显示和隐藏等等

代码

代码中用到了一些图片资源,想要复现需要按照路径添加图片资源

项目地址

GitHub地址

emulateOS.html

DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>模拟操作系统title>
head>
<body>
  <div class="container" onmouseup="desktopEve()" ondragover="dragover()" ondrop="drop()">
    
    <div class="icon" draggable="true" style="display: none;">
      <img src="desktop/filefolder.png" onmouseup="fileIconEve()" ondblclick="openFileFolder()" ondragstart="dragStart()">
      <input type="text" value="新建文件夹">
      
      <ul class="fileMenu" style="display: none;">
        <li onclick="openFileFolder()">打开li>
        <li onclick="copyFileFolder()">复制li>
        <li onclick="delFileFolder()">删除li>
        <li onclick="renameFileFolder()">重命名li>
      ul>
    div>
    <div class="container filefolder" style="display: none" onmouseup="filefolderEve()" ondragover="dragover()" ondrop="drop()">
      <img class="close" src="desktop/close.svg" onclick="parentNode.style.display='none'">
      <ul class="fileFolderMenu" style="display: none;">
        <li onclick="newFileFolder()">新建文件夹li>
      ul>
    div>
    
    <div class="icon" draggable="true">
      <img src="desktop/filefolder.png" onmouseup="fileIconEve()" ondblclick="openFileFolder()" ondragstart="dragStart()">
      <input type="text" value="新建文件夹">
      <ul class="fileMenu" style="display: none;">
        <li onclick="openFileFolder()">打开li>
        <li onclick="copyFileFolder()">复制li>
        <li onclick="delFileFolder()">删除li>
        <li onclick="renameFileFolder()">重命名li>
      ul>
    div>
    <div class="container filefolder" style="display: none" onmouseup="filefolderEve()" ondragover="dragover()" ondrop="drop()">
      <img class="close" src="desktop/close.svg" onclick="parentNode.style.display='none'">
      <ul class="fileFolderMenu" style="display: none;">
        <li onclick="newFileFolder()">新建文件夹li>
      ul>
    div>
    
    <div class="icon" draggable="true">
      <img src="desktop/browser.svg" onclick="parentNode.classList.add('active')" ondblclick="getElementById('browser').style.display='block'" ondragstart="dragStart()">
      <input type="text" value="浏览器">
    div>
    <div id="browser" class="filefolder" style="display: none;">
      <input id="urlInput" style="width: 880px; height: 20px;" onkeydown="openBrowser()">
      <button onclick="openBrowser()">前往button>
      <img class="close" src="Desktop/close.svg" onclick="parentNode.style.display='none'">
      <iframe id="iframe">iframe>
    div>
    
    <div class="icon" draggable="true">
      <img src="desktop/trashBin.svg" onclick="parentNode.classList.add('active')" ondblclick="getElementById('trash').style.display='block'" ondragstart="dragStart()">
      <input type="text" value="回收箱">
    div>
    <div id="trash" class="filefolder " style="display: none">
      <img class="close" src="desktop/close.svg" onclick="parentNode.style.display='none'">
    div>
    
    <ul class="desktopMenu" style="display: none;">
      <li onclick="newFileFolder()">新建文件夹li>
      <li onclick="changeBack()">更改桌面背景li>
      <li onclick="pasteFileFolder()">粘贴li>
      <li>排序方式li>
      <li onclick="location.reload()">刷新li>
    ul>
  div>
body>
<script src="./emulateOS.js">script>
<link rel="stylesheet" type="text/css" href="emulateOS.css" />
html>

emulateOS.js

let copyedElem // 复制的对象
let dragged
let ofx
let ofy
let backOrder = 0
let curFileFolder
// 右键菜单事件
document.oncontextmenu = (event) => {
  event.preventDefault()
};
// 桌面点击事件
const desktopEve = (event) => {
  let e = event || window.event
  let fileMenus = document.getElementsByClassName('fileMenu')
  let desktopMenus = document.getElementsByClassName('desktopMenu')
  if (e.button == 0) { // 单击桌面
    for (let i of e.target.children) {
      if (i.classList.contains('icon')) {
        i.classList.remove('active')
      }
    }
    for(let f of fileMenus) {
      f.style.display = 'none'
    }
    desktopMenus[0].style.display = 'none'
  } else if (e.button == 2) { // 右击桌面
    desktopMenus[0].style.display = 'block'
    desktopMenus[0].style.top = e.offsetY + 'px'
    desktopMenus[0].style.left = e.offsetX + 'px'
  }
  e.stopPropagation()
  return false
}
// 文件夹图标点击事件
const fileIconEve = (event) => {
  let e = event || window.event
  if (e.button == 0) {
    e.target.parentNode.classList.add('active')
  } else if (e.button == 2) {
    e.target.parentElement.children[2].style.display = 'block'
    e.target.parentElement.children[2].style.top = e.clientY + 'px'
    e.target.parentElement.children[2].style.left = e.clientX + 'px'
  }
  e.stopPropagation()
  return false
}
// 文件夹点击事件
const filefolderEve = (event) => {
  let e = event || window.event
  if (e.button == 0) {
    for (let i of e.target.children) {
      if (i.classList.contains('icon')) {
        i.classList.remove('active')
      } else if (i.classList.contains('fileFolderMenu')) {
        i.style.display = 'none'
      }
    }
  } else if (e.button == 2) {
    for (let i of e.target.children) {
      if (i.classList.contains('fileFolderMenu')) {
        i.style.display = 'block'
        i.style.top = e.offsetY + 'px'
        i.style.left = e.offsetX + 'px'
      }
    }
  }
  e.stopPropagation()
  return false
}
// 更改桌面背景事件
const changeBack = (event) => {
  let e = event || window.event
  let body = document.getElementsByTagName('body')
  backOrder = (backOrder + 1) % 4
  body[0].style.backgroundImage = `url(desktop/back${backOrder}.jpg)`
  e.stopPropagation()
  return false
}

// 打开网址
const openBrowser = (event) => {
  let e = event || window.event
  let urlInput = document.getElementById('urlInput')
  if (e.keyCode == 13 || e.button == 0) {
    let i = document.getElementById('iframe')
    i.setAttribute('src', urlInput.value)
  }
  e.stopPropagation()
  return false
}
// 拖拽开始事件
const dragStart = (event) => {
  let e = event || window.event
  dragged = e.target.parentElement
  ofx = e.offsetX
  ofy = e.offsetY
  return false
}
// 拖拽过程事件
const dragover = (event) => {
  let e = event || window.event
  e.preventDefault()
  return false
}
// 拖拽结束事件
const drop = (event) => {
  let e = event || window.event
  dragged.style.position = "absolute"
  dragged.style.left = (e.offsetX - ofx) + 'px'
  dragged.style.top = (e.offsetY - ofy) + 'px'
  return false
}
// 打开文件夹事件
const openFileFolder = (event) => {
  let e = event || window.event
  if (e.target.tagName == 'IMG') {
    e.target.parentElement.nextElementSibling.style.display = 'block'
  } else if (e.target.tagName == 'LI') {
    e.target.parentElement.parentElement.nextElementSibling.style.display = 'block'
  }
  e.stopPropagation()
  return false
}
// 复制文件夹
const copyFileFolder = (event) => {
  let e = event || window.event
  copyedElem = e.target.parentElement.parentElement.cloneNode(true)
  e.stopPropagation()
  return false
}
// 删除文件夹
const delFileFolder = (event) => {
  let e = event || window.event
  let trash = document.getElementById("trash")
  trash.appendChild(e.target.parentElement.parentElement)
  e.target.parentElement.remove()
  e.stopPropagation()
  return false
}
// 文件夹重命名
const renameFileFolder = (event) => {
  let e = event || window.event
  e.target.parentElement.parentElement.children[1].focus()
  e.target.parentElement.parentElement.children[1].setSelectionRange(-1,-2,'backward')
  e.target.parentNode.style.display = 'none'
  e.stopPropagation()
  return false
}
// 新建文件夹事件
const newFileFolder = (event) => {
  let e = event || window.event
  let containers = document.getElementsByClassName('container')
  let newItem1 = containers[0].children[0].cloneNode(true)
  let newItem2 = containers[0].children[1].cloneNode(true)
  newItem1.style.display = 'block'
  e.target.parentElement.parentElement.appendChild(newItem1)
  e.target.parentElement.parentElement.appendChild(newItem2)
  e.target.parentElement.style.display = 'none'
  e.stopPropagation()
  return false
}
// 粘贴文件夹
const pasteFileFolder = (event) => {
  let e = event || window.event
  e.target.parentElement.parentElement.appendChild(copyedElem)
  e.stopPropagation()
  return false
}

emulateOS.css

body {
  background-image: url(desktop/back0.jpg);
}
.container {
  position: fixed;
  left: 0;
  top: 0;
  width: 100vw;
  height: 100vh;
}
.icon {
  box-sizing: border-box;
  width: 130px;
  height: 160px;
  margin: 5px;
}
.icon img {
  width: 130px;
  height: 130px;
  border: 3px solid rgba(0, 0, 0, 0);
}
.active img  {
  border: 3px solid white;
  border-radius: 3px;
  background-color: rgba(0, 0, 0, 0.3);
}
.icon input {
  width: 130px;
  text-align: center;
  color: white;
  border: none;
  background-color: rgba(0, 0, 0, 0);
}
.active input  {
  background-color: blue;
}
.filefolder {
  width: 1000px;
  height: 700px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-45%);
  background-color: rgba(255, 255, 255, 0.8);
  z-index: 99;
}
.fileMenu, .desktopMenu, .fileFolderMenu {
  list-style: none;
  width: 200px;
  height: 120px;
  position: absolute;
  background-color: rgba(255, 255, 255, 0.8);
  margin: 0;
  padding: 5px 0;
}
.desktopMenu {
  height: 148px;
}
.fileFolderMenu  {
  height: 30px;
}
li {
  height: 30px;
  line-height: 30px;
  padding: 0 20px;
}
li:hover {
  cursor: pointer;
  background-color: blue;
}
.close{
  width: 30px;
  height: 30px;
  padding: 5px;
  float: right;
}
#iframe {
  width: 1000px;
  height: 650px;
  border: none;
}
#urlInput {
  margin: 8px;
}

你可能感兴趣的:(javascript,html,css)