HTML+CSS+JS实现TodoList应用和动画

目录

 前言

 HTML部分

CSS部分

JS部分


 前言

        界面比较简陋,实现了本地存储,刷新不会损失数据,可以定时提醒,并添加了三个动画。代码还有很多不足之处,应该可以写得更精简的,详情请看代码。

 HTML部分

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="todoList.css" />
    <link rel="stylesheet" href="iconfont.css" />
    <script src="todoList.js" ></script>
  </head>
  <body>
    <div class="all">
        <div class="kkl"></div>
        <div class="add">
          <div class="combine">
            <div class="cephalic">
              <span class="iconfont" id="logo">&#xe604;</span>
              <span class="headline">任务</span>
            </div>
            <div class="task">
               <ul class="todo-list" id="todolist"></ul> 
              <div class="com">
                <div class="store" style="cursor: pointer;">
                  <span>已完成</span><i class="iconfont" id="vue">&#xe602;</i>
                </div>
                <ul class="todo-com"> </ul>
              </div>
             
            </div>
            <div class="join">
                <from class="from">
                    <button class="submit">
                      <span class="iconfont" id="submit_add">&#xeaf3;</span>
                    </button>
                    <div class="from-input">
                      <input placeholder="添加任务" id="content">
                    </div>
                </from>
            </div>
          </div>
        </div>
        
        <div class="warn" id="div">
          <img src="m1.gif" >
        </div>
   
        <div class="contet">
          <div id="rainBox"></div>
        </div>
        <div class="sup" id="sup">
          <div class="hint" id="hint"></div>
          <img src="c1.gif" id="nv">
        </div>
    </div>
  </body>
</html>

CSS部分

* {
  margin: 0px;
  padding: 0px;
  list-style-type: none;
}
html,
body {
  width: 100%;
  height: 100%;
  overflow-x: hidden;
}
body {
  background-image: linear-gradient(90deg, #bedc98, #84e4a6);
}
.all {
  display: flex;
  width: 100%;
  position: relative;
  height: 100%;
}
.add {
  display: table;
  border-radius: 30px;
  background-color: #ffffff;
  width: 520px;
  height: 550px;
  position: relative;
  margin-top: 80px;
  margin-left: auto;
  margin-right: auto;
}
.combine {
  position: relative;
  margin: auto;
  margin-top: 35px;
  width: 400px;
}
.cephalic {
  width: 398px;
  height: 50px;
  display: flex;
  margin-bottom: 30px;
}
#logo {
  margin-top: 2px;
  font-size: 40px;
  color: rgb(142, 135, 135);
  text-align: center;
}
.headline {
  margin-left: 10px;
  margin-top: 5px;
  font-size: 30px;
  font-family: "Times New Roman", Times, serif;
  text-align: center;
  font-weight: 700;
  color: rgb(156, 149, 149);
}
.task {
  height: 350px;
  overflow: auto;
}
.press-sel {
  outline: none;
  position: relative;
  border: none;
  background-color: transparent;
}
.todo-list li {
  text-overflow: ellipsis;
  border-radius: 15px;
  display: flex;
  font-size: 20px;
  color: rgb(255, 255, 255);
  height: 45px;
  margin-bottom: 20px;
  background-color: #84b5a0;
}

.todo-list li {
  margin-left: 18px;
  font-size: 23px;
  text-overflow: ellipsis;
  font-weight: 600;
  color: rgb(255, 255, 255);
}
.todo-com li {
  text-overflow: ellipsis;
  border-radius: 15px;
  display: flex;
  font-size: 20px;
  color: rgb(255, 255, 255);
  height: 45px;
  margin-bottom: 20px;
  background-color: #4a4a4a46;
}
.todo-com li {
  margin-left: 18px;
  font-size: 23px;
  text-overflow: ellipsis;
  font-weight: 600;
  color: rgb(255, 255, 255);
}
.content {
  margin-top: 9px;
  width: 250px;
  margin-left: 10px;
  text-overflow: ellipsis;
  overflow: hidden;
  font-family: Arial, Helvetica, sans-serif;
}
.del {
  color: rgb(255, 255, 255);
  font-size: 23px;
  float: right;
  position: absolute;
  margin-left: 40px;
  font-weight: 700;
  margin-top: 10px;
}

.sel {
  color: rgb(255, 255, 255);
  font-size: 23px;
  margin-left: 10px;
  float: right;
  font-weight: 700;
}
.press-del {
  display: flex;
  position: relative;
  border: none;
  background-color: transparent;
}
.join {
  height: 35px;
  border-radius: 10px;
  margin-top: 8px;
}
.from {
  display: flex;
}
.submit {
  margin-top: 2px;
  border: none;
  background-color: transparent;
}
#submit_add {
  color: #6c6363;
  font-size: 30px;
  margin-left: 10px;
}
.from-input {
  margin: 10px;
}
#content {
  font-size: 18px;
  background-color: transparent;
  border: none;
  outline: none;
  height: 32px;
  width: 300px;
  color: #878484;
  border-bottom: 3px dashed #84b5a0;
}

.task::-webkit-scrollbar {
  /*滚动条整体样式*/
  width: 3px; /*高宽分别对应横竖滚动条的尺寸*/
  height: 1px;
}
.task::-webkit-scrollbar-thumb {
  /*滚动条里面小方块*/
  border-radius: 10px;
  background-color: rgb(228, 228, 228);
}
.task::-webkit-scrollbar-track {
  /*滚动条里面轨道*/
  box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
  background: #ededed;
  border-radius: 10px;
}

input::placeholder {
  color: rgb(223, 223, 223);
  opacity: 1;
}
.store {
  width: 120px;
  color: #4a4a4a46;
  background-color: #66666621;
  font-size: 20px;
  font-weight: 700;
  margin-left: 15px;
  height: 35px;
  border-radius: 15px;
  margin-bottom: 20px;
  display: flex;
}
.store span {
  display: block;
  margin-top: 3px;
  margin-left: 15px;
}

.store i {
  display: block;
  margin-top: 6px;
  margin-left: 10px;
}
.epo {
  margin-top: 10px;
  color: rgb(255, 255, 255);
  font-size: 23px;
  margin-right: 10px;
  font-weight: 700;
}
.timer {
  position: absolute;
  margin-left: 30px;
  margin-top: -35px;
  height: 80px;
  width: 60px;
  z-index: 1;
  display: none;
  border-radius: 30px !important;
}
.timer span {
  width: 60px;
  height: 25px;
  border-radius: 5px;
  background-color: rgb(116, 141, 121);
  font-size: 16px;
  display: block;
  color: #ffffff;
  border: #1b892dfa solid 1px;
}
.timer span:hover {
  background-color: bisque;
}
.warn {
  position: absolute;
}
.warn img {
  width: 260px;
}
.contet {
  position: relative;
}
#rainBox {
  position: fixed;
  top: 0px;
  left: 0;
  width: 100%;
  height: 100%;
  /* 不阻挡其它事件 */
  pointer-events: none;
}
.rain {
  position: absolute;
  width: 1px;
  height: 30px;
  background: linear-gradient(
    rgba(255, 255, 255, 0.6),
    rgba(255, 255, 255, 0.9)
  );
}

.sup {
  position: fixed;
  right: 0px;
  bottom: 10px;
}

#nv {
  width: 240px;
}
.hint {
  display: none;
  overflow: hidden;
  height: 25px;
  background-color: rgba(166, 254, 150, 0.58);
  width: 210px;
  border-radius: 30px;
  margin-left: 25px;
  font-size: 20px;
  font-weight: 600;
  text-align: center;
  color: rgb(228, 121, 67);
}
.content title{
  position: absolute;
        color: #ffffff;
        font-size: 14px;
        padding: 4px;
        background: rgba(40, 40, 40, 0.8);
        border-radius:5px;
        z-index:999;

}

JS部分

        代码比较杂,写得比较繁琐,不过简单易懂,作为新手也是可以看懂的,基本上每个代码都有注释。添加事件使用的是字符串,比较简单,一直拼接字符串,然后使用innerHTML进行渲染。

window.onload = function () {
  let todoList = document.getElementsByClassName("todo-list")[0];
  let newInput = document.querySelector("#content");
  let todoCom = document.getElementsByClassName("todo-com")[0];
  let Hint = document.getElementsByClassName("hint")[0];
  load();
  //存储input里的内容
  newInput.onkeydown = function (event) {
    if (event.keyCode === 13 && newInput.value !== "") {
      var local = getData();
      //存储格式
      local.push({ title: newInput.value, done: false });
      savaDate(local);
      load();
    }
  };

  //读取本地储存
  function getData() {
    var data = localStorage.getItem("todolist");
    if (data !== null) {
      // JSON.parse() 将一个 JSON 字符串转换为 JavaScript 对象
      return JSON.parse(data);
    } else {
      return [];
    }
  }
  //保存本地数据
  function savaDate(data) {
    // JSON.stringify() 将 JavaScript 值转换为 JSON 字符串
    localStorage.setItem("todolist", JSON.stringify(data));
  }
  //渲染加载数据
  function load() {
    //读取本地数据
    var data = getData();
    var str = "";
    var stv = "";
    //遍历数据,拼接字符串
    data.forEach((event, index) => {
      if (event.done === false) {
        str =
          '<li class="record-item"> ' +
          '<button class="press-sel">' +
          '<i class="iconfont sel" id="' +
          index +
          '">&#xe600;</i>' +
          "</button>" +
          '<p class="content" title=' +
          event.title +
          ">" +
          event.title +
          "</p>" +
          '<button class="press-del">' +
          '<i class="iconfont epo" id="' +
          index +
          '" style="cursor: pointer;">&#xe6de;' +
          '<div class="timer" id="' +
          index +
          '"><span class="second"  id="' +
          index +
          '">5s</span><span class="hour"  id="' +
          index +
          '">1h</span><span class="day"  id="' +
          index +
          '">1d</sapn></div></i>' +
          '<i class="iconfont del" id="' +
          index +
          '" style="cursor: pointer;">&#xe869;</i>' +
          "</li>" +
          str;
      } else {
        stv =
          '<li class="record-ite"> ' +
          '<button class="press-sel">' +
          '<i class="iconfont sel" id="' +
          index +
          '">&#xe603;</i>' +
          "</button>" +
          '<p class="content" title=' +
          event.title +
          " ><s>" +
          event.title +
          "</s></p>" +
          '<button class="press-del">' +
          '<i class="iconfont del" id="' +
          index +
          '" style="cursor: pointer;">&#xe869;</i>' +
          "</li>" +
          stv;
      }
    });
    //遍历之前清空ul里的元素内容·
    newInput.value = "";
    //渲染内容到HTML
    todoList.innerHTML = str;
    todoCom.innerHTML = stv;
    //删除的方法
    del();
    //完成的方法
    sel();
    //收拢的方式
    store();
    //完成隐藏
    com();
    console.log(timers);
    //提醒事件
    timers();
    //提醒时间
    second();
    hour();
    day();
    //雨点
    // rain();
    //拖动
    drag();
    sup();
  }
  //删除操作
  function del() {
    var del = document.querySelectorAll(".del");
    // console.log(del);
    if (del !== "") {
      del.forEach((element) => {
        element.onclick = function () {
          //本地读取
          var data = getData();
          //修改数据
          var index = element.getAttribute("id");
          data.splice(index, 1);
          //保存本地
          savaDate(data);
          //渲染
          load();
        };
      });
    }
  }
  //完成
  function sel() {
    var sel = document.querySelectorAll(".sel");
    if (sel !== "") {
      sel.forEach((element) => {
        element.onclick = function () {
          //本地读取
          var data = getData();
          //修改数据
          //获得索引
          var index = element.getAttribute("id");
          // console.log(data[index].done);
          //修改数组
          if (data[index].done === false) {
            //下雨庆祝
            rain();
            data.splice(index, 1, { title: data[index].title, done: true });
          } else {
            data.splice(index, 1, { title: data[index].title, done: false });
          }
          //保存本地
          savaDate(data);

          //渲染
          load();
        };
      });
    }
  }
  //完成收拢
  function store() {
    var store = document.querySelectorAll(".store");
    var vue = document.getElementById("vue");
    store.forEach((element) => {
      element.onclick = function () {
        if (todoCom.style.display == "none") {
          todoCom.style.display = "block";
          vue.innerHTML = "&#xe602;";
        } else {
          todoCom.style.display = "none";
          vue.innerHTML = "&#xe645;";
        }
      };
    });
  }
  //完成隐藏
  function com() {
    let Com = document.querySelectorAll(".com");
    Com.forEach((element) => {
      if (todoCom.innerHTML == "") {
        element.style.display = "none";
      } else {
        element.style.display = "block";
      }
    });
  }
  //提醒事件
  function timers() {
    var epo = document.querySelectorAll(".epo");
    console.log(epo);
    epo.forEach((element) => {
      var isShow = false;
      var time;
      element.onclick = function () {
        clearTimeout(time);
        if (!isShow) {
          isShow = true;
          element.childNodes[1].style.display = "block";
        } else {
          isShow = false;
          element.childNodes[1].style.display = "none";
        }
        //鼠标移入事件
        element.onmouseover = () => {
          clearTimeout(time);
        };
        //鼠标移出事件
        element.onmouseout = () => {
          clearTimeout(time);
          //计时器更改属性
          if (isShow) {
            time = setTimeout(() => {
              element.childNodes[1].style.display = "none";
              isShow = false;
            }, 400);
          }
        };
      };
    });
  }
  //计时5s
  function second() {
    let second1 = document.querySelectorAll(".second");
    // let hint=document.getElementById("hint");
    second1.forEach((element) => {
      element.onclick = function () {
        //本地读取
        var data = getData();
        var index = element.getAttribute("id");
        var time;
        var stv = "";
        console.log(index);
        clearTimeout(time);
        time = setTimeout(function () {
          Hint.style.display = "block";
          stv = data[index].title;
          Hint.innerHTML = stv;
          // alert("任务`"+data[index].title+"`时间到啦");
        }, 5000);
      };
    });
  }
  //计时1小时
  function hour() {
    let hour = document.querySelectorAll(".hour");
    hour.forEach((element) => {
      element.onclick = function () {
        //本地读取
        var data = getData();
        var stv = "";
        var index = element.getAttribute("id");
        var time;
        clearTimeout(time);
        time = setTimeout(function () {
          // alert("任务`"+data[index].title+"`时间到啦")
          Hint.style.display = "block";
          stv = data[index].title;
          Hint.innerHTML = stv;
        }, 60 * 1000 * 60);
      };
    });
  }
  //计时一天
  function day() {
    let day = document.querySelectorAll(".day");
    day.forEach((element) => {
      element.onclick = function () {
        //本地读取
        var data = getData();
        var index = element.getAttribute("id");
        var time;
        var stv = "";
        // console.log(index)
        clearTimeout(time);
        time = setTimeout(function () {
          Hint.style.display = "block";
          stv = data[index].title;
          Hint.innerHTML = stv;
        }, 1000 * 60 * 60 * 24);
      };
    });
  }
  //下雨事件
  function rain() {
    const box = document.getElementById("rainBox");
    var time;
    //每隔一段时间添加雨点
    time = setInterval(() => {
      // clearInterval(timer)
      let boxHeight = box.clientHeight;
      let boxWidth = box.clientWidth;
      const rain = document.createElement("div");
      rain.classList.add("rain");
      rain.style.top = 0;
      //随机刷新雨点位置
      rain.style.left = Math.random() * boxWidth + "px";
      //随机雨点透明度
      rain.style.opacity = Math.random();
      box.appendChild(rain);
      //每隔一段时间雨点下落
      let race = 1;
      const timer = setInterval(() => {
        if (parseInt(rain.style.top) > boxHeight) {
          clearInterval(timer);
          box.removeChild(rain);
        }
        race++;
        rain.style.top = parseInt(rain.style.top) + race + "px";
      }, 1);
    }, 1);
    setInterval(() => {
      clearTimeout(time);
    }, 10000);
  }
  //小猫
  function drag() {
    var isShow = false;
    let div = document.getElementById("div");
    let body;
    setInterval(() => {
      // 获取整个网页的宽度
      body = document.body.scrollWidth;
      //   console.log(body)
      div.onclick = function () {
        if (body === 1490) {
          if (!isShow) {
            isShow = true;
          } else {
            isShow = false;
          }
          if (isShow) {
            // onmousemove鼠标指针移到指定的对象时发生
            document.onmousemove = function (e) {
              let event = e || window.event;
              //解决兼容问题,获得鼠标位置
              div.style.left = event.clientX - div.clientWidth / 2 + "px";
            };
          } else {
            document.onmousemove = function (e) {
              let event = e || window.event;
              //解决兼容问题,获得鼠标位置
              div.style.left = div.style.left;
            };
          }
        }
      };
    }, 100);
  }
  //超人
  function sup() {
    var isShow = false;
    let sup = document.getElementById("sup");
    var num = 0;
    sup.onclick = function () {
      //隐藏提醒框
      Hint.style.display = "none";
      let speed = 15;
      if (!isShow) {
        isShow = true;
      } else {
        isShow = false;
      }
      if (isShow) {
        timer = setInterval(() => {
          num += speed;
          //   获取整个网页的高度
          let body = document.body.scrollHeight;
          sup.style.bottom = num + "px";
          if (num >= body) {
            num = -250;
          }
        }, 100);
      } else {
        //结束计时
        clearInterval(timer);
        num = num;
      }
    };
  }
};

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宝子向前冲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值