当前位置:   article > 正文

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

css todolist

目录

 前言

 HTML部分

CSS部分

JS部分


 前言

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

 HTML部分

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  7. <title>Document</title>
  8. <link rel="stylesheet" href="todoList.css" />
  9. <link rel="stylesheet" href="iconfont.css" />
  10. <script src="todoList.js" ></script>
  11. </head>
  12. <body>
  13. <div class="all">
  14. <div class="kkl"></div>
  15. <div class="add">
  16. <div class="combine">
  17. <div class="cephalic">
  18. <span class="iconfont" id="logo">&#xe604;</span>
  19. <span class="headline">任务</span>
  20. </div>
  21. <div class="task">
  22. <ul class="todo-list" id="todolist"></ul>
  23. <div class="com">
  24. <div class="store" style="cursor: pointer;">
  25. <span>已完成</span><i class="iconfont" id="vue">&#xe602;</i>
  26. </div>
  27. <ul class="todo-com"> </ul>
  28. </div>
  29. </div>
  30. <div class="join">
  31. <from class="from">
  32. <button class="submit">
  33. <span class="iconfont" id="submit_add">&#xeaf3;</span>
  34. </button>
  35. <div class="from-input">
  36. <input placeholder="添加任务" id="content">
  37. </div>
  38. </from>
  39. </div>
  40. </div>
  41. </div>
  42. <div class="warn" id="div">
  43. <img src="m1.gif" >
  44. </div>
  45. <div class="contet">
  46. <div id="rainBox"></div>
  47. </div>
  48. <div class="sup" id="sup">
  49. <div class="hint" id="hint"></div>
  50. <img src="c1.gif" id="nv">
  51. </div>
  52. </div>
  53. </body>
  54. </html>

CSS部分

  1. * {
  2. margin: 0px;
  3. padding: 0px;
  4. list-style-type: none;
  5. }
  6. html,
  7. body {
  8. width: 100%;
  9. height: 100%;
  10. overflow-x: hidden;
  11. }
  12. body {
  13. background-image: linear-gradient(90deg, #bedc98, #84e4a6);
  14. }
  15. .all {
  16. display: flex;
  17. width: 100%;
  18. position: relative;
  19. height: 100%;
  20. }
  21. .add {
  22. display: table;
  23. border-radius: 30px;
  24. background-color: #ffffff;
  25. width: 520px;
  26. height: 550px;
  27. position: relative;
  28. margin-top: 80px;
  29. margin-left: auto;
  30. margin-right: auto;
  31. }
  32. .combine {
  33. position: relative;
  34. margin: auto;
  35. margin-top: 35px;
  36. width: 400px;
  37. }
  38. .cephalic {
  39. width: 398px;
  40. height: 50px;
  41. display: flex;
  42. margin-bottom: 30px;
  43. }
  44. #logo {
  45. margin-top: 2px;
  46. font-size: 40px;
  47. color: rgb(142, 135, 135);
  48. text-align: center;
  49. }
  50. .headline {
  51. margin-left: 10px;
  52. margin-top: 5px;
  53. font-size: 30px;
  54. font-family: "Times New Roman", Times, serif;
  55. text-align: center;
  56. font-weight: 700;
  57. color: rgb(156, 149, 149);
  58. }
  59. .task {
  60. height: 350px;
  61. overflow: auto;
  62. }
  63. .press-sel {
  64. outline: none;
  65. position: relative;
  66. border: none;
  67. background-color: transparent;
  68. }
  69. .todo-list li {
  70. text-overflow: ellipsis;
  71. border-radius: 15px;
  72. display: flex;
  73. font-size: 20px;
  74. color: rgb(255, 255, 255);
  75. height: 45px;
  76. margin-bottom: 20px;
  77. background-color: #84b5a0;
  78. }
  79. .todo-list li {
  80. margin-left: 18px;
  81. font-size: 23px;
  82. text-overflow: ellipsis;
  83. font-weight: 600;
  84. color: rgb(255, 255, 255);
  85. }
  86. .todo-com li {
  87. text-overflow: ellipsis;
  88. border-radius: 15px;
  89. display: flex;
  90. font-size: 20px;
  91. color: rgb(255, 255, 255);
  92. height: 45px;
  93. margin-bottom: 20px;
  94. background-color: #4a4a4a46;
  95. }
  96. .todo-com li {
  97. margin-left: 18px;
  98. font-size: 23px;
  99. text-overflow: ellipsis;
  100. font-weight: 600;
  101. color: rgb(255, 255, 255);
  102. }
  103. .content {
  104. margin-top: 9px;
  105. width: 250px;
  106. margin-left: 10px;
  107. text-overflow: ellipsis;
  108. overflow: hidden;
  109. font-family: Arial, Helvetica, sans-serif;
  110. }
  111. .del {
  112. color: rgb(255, 255, 255);
  113. font-size: 23px;
  114. float: right;
  115. position: absolute;
  116. margin-left: 40px;
  117. font-weight: 700;
  118. margin-top: 10px;
  119. }
  120. .sel {
  121. color: rgb(255, 255, 255);
  122. font-size: 23px;
  123. margin-left: 10px;
  124. float: right;
  125. font-weight: 700;
  126. }
  127. .press-del {
  128. display: flex;
  129. position: relative;
  130. border: none;
  131. background-color: transparent;
  132. }
  133. .join {
  134. height: 35px;
  135. border-radius: 10px;
  136. margin-top: 8px;
  137. }
  138. .from {
  139. display: flex;
  140. }
  141. .submit {
  142. margin-top: 2px;
  143. border: none;
  144. background-color: transparent;
  145. }
  146. #submit_add {
  147. color: #6c6363;
  148. font-size: 30px;
  149. margin-left: 10px;
  150. }
  151. .from-input {
  152. margin: 10px;
  153. }
  154. #content {
  155. font-size: 18px;
  156. background-color: transparent;
  157. border: none;
  158. outline: none;
  159. height: 32px;
  160. width: 300px;
  161. color: #878484;
  162. border-bottom: 3px dashed #84b5a0;
  163. }
  164. .task::-webkit-scrollbar {
  165. /*滚动条整体样式*/
  166. width: 3px; /*高宽分别对应横竖滚动条的尺寸*/
  167. height: 1px;
  168. }
  169. .task::-webkit-scrollbar-thumb {
  170. /*滚动条里面小方块*/
  171. border-radius: 10px;
  172. background-color: rgb(228, 228, 228);
  173. }
  174. .task::-webkit-scrollbar-track {
  175. /*滚动条里面轨道*/
  176. box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
  177. background: #ededed;
  178. border-radius: 10px;
  179. }
  180. input::placeholder {
  181. color: rgb(223, 223, 223);
  182. opacity: 1;
  183. }
  184. .store {
  185. width: 120px;
  186. color: #4a4a4a46;
  187. background-color: #66666621;
  188. font-size: 20px;
  189. font-weight: 700;
  190. margin-left: 15px;
  191. height: 35px;
  192. border-radius: 15px;
  193. margin-bottom: 20px;
  194. display: flex;
  195. }
  196. .store span {
  197. display: block;
  198. margin-top: 3px;
  199. margin-left: 15px;
  200. }
  201. .store i {
  202. display: block;
  203. margin-top: 6px;
  204. margin-left: 10px;
  205. }
  206. .epo {
  207. margin-top: 10px;
  208. color: rgb(255, 255, 255);
  209. font-size: 23px;
  210. margin-right: 10px;
  211. font-weight: 700;
  212. }
  213. .timer {
  214. position: absolute;
  215. margin-left: 30px;
  216. margin-top: -35px;
  217. height: 80px;
  218. width: 60px;
  219. z-index: 1;
  220. display: none;
  221. border-radius: 30px !important;
  222. }
  223. .timer span {
  224. width: 60px;
  225. height: 25px;
  226. border-radius: 5px;
  227. background-color: rgb(116, 141, 121);
  228. font-size: 16px;
  229. display: block;
  230. color: #ffffff;
  231. border: #1b892dfa solid 1px;
  232. }
  233. .timer span:hover {
  234. background-color: bisque;
  235. }
  236. .warn {
  237. position: absolute;
  238. }
  239. .warn img {
  240. width: 260px;
  241. }
  242. .contet {
  243. position: relative;
  244. }
  245. #rainBox {
  246. position: fixed;
  247. top: 0px;
  248. left: 0;
  249. width: 100%;
  250. height: 100%;
  251. /* 不阻挡其它事件 */
  252. pointer-events: none;
  253. }
  254. .rain {
  255. position: absolute;
  256. width: 1px;
  257. height: 30px;
  258. background: linear-gradient(
  259. rgba(255, 255, 255, 0.6),
  260. rgba(255, 255, 255, 0.9)
  261. );
  262. }
  263. .sup {
  264. position: fixed;
  265. right: 0px;
  266. bottom: 10px;
  267. }
  268. #nv {
  269. width: 240px;
  270. }
  271. .hint {
  272. display: none;
  273. overflow: hidden;
  274. height: 25px;
  275. background-color: rgba(166, 254, 150, 0.58);
  276. width: 210px;
  277. border-radius: 30px;
  278. margin-left: 25px;
  279. font-size: 20px;
  280. font-weight: 600;
  281. text-align: center;
  282. color: rgb(228, 121, 67);
  283. }
  284. .content title{
  285. position: absolute;
  286. color: #ffffff;
  287. font-size: 14px;
  288. padding: 4px;
  289. background: rgba(40, 40, 40, 0.8);
  290. border-radius:5px;
  291. z-index:999;
  292. }

JS部分

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

  1. window.onload = function () {
  2. let todoList = document.getElementsByClassName("todo-list")[0];
  3. let newInput = document.querySelector("#content");
  4. let todoCom = document.getElementsByClassName("todo-com")[0];
  5. let Hint = document.getElementsByClassName("hint")[0];
  6. load();
  7. //存储input里的内容
  8. newInput.onkeydown = function (event) {
  9. if (event.keyCode === 13 && newInput.value !== "") {
  10. var local = getData();
  11. //存储格式
  12. local.push({ title: newInput.value, done: false });
  13. savaDate(local);
  14. load();
  15. }
  16. };
  17. //读取本地储存
  18. function getData() {
  19. var data = localStorage.getItem("todolist");
  20. if (data !== null) {
  21. // JSON.parse() 将一个 JSON 字符串转换为 JavaScript 对象
  22. return JSON.parse(data);
  23. } else {
  24. return [];
  25. }
  26. }
  27. //保存本地数据
  28. function savaDate(data) {
  29. // JSON.stringify() 将 JavaScript 值转换为 JSON 字符串
  30. localStorage.setItem("todolist", JSON.stringify(data));
  31. }
  32. //渲染加载数据
  33. function load() {
  34. //读取本地数据
  35. var data = getData();
  36. var str = "";
  37. var stv = "";
  38. //遍历数据,拼接字符串
  39. data.forEach((event, index) => {
  40. if (event.done === false) {
  41. str =
  42. '<li class="record-item"> ' +
  43. '<button class="press-sel">' +
  44. '<i class="iconfont sel" id="' +
  45. index +
  46. '">&#xe600;</i>' +
  47. "</button>" +
  48. '<p class="content" title=' +
  49. event.title +
  50. ">" +
  51. event.title +
  52. "</p>" +
  53. '<button class="press-del">' +
  54. '<i class="iconfont epo" id="' +
  55. index +
  56. '" style="cursor: pointer;">&#xe6de;' +
  57. '<div class="timer" id="' +
  58. index +
  59. '"><span class="second" id="' +
  60. index +
  61. '">5s</span><span class="hour" id="' +
  62. index +
  63. '">1h</span><span class="day" id="' +
  64. index +
  65. '">1d</sapn></div></i>' +
  66. '<i class="iconfont del" id="' +
  67. index +
  68. '" style="cursor: pointer;">&#xe869;</i>' +
  69. "</li>" +
  70. str;
  71. } else {
  72. stv =
  73. '<li class="record-ite"> ' +
  74. '<button class="press-sel">' +
  75. '<i class="iconfont sel" id="' +
  76. index +
  77. '">&#xe603;</i>' +
  78. "</button>" +
  79. '<p class="content" title=' +
  80. event.title +
  81. " ><s>" +
  82. event.title +
  83. "</s></p>" +
  84. '<button class="press-del">' +
  85. '<i class="iconfont del" id="' +
  86. index +
  87. '" style="cursor: pointer;">&#xe869;</i>' +
  88. "</li>" +
  89. stv;
  90. }
  91. });
  92. //遍历之前清空ul里的元素内容·
  93. newInput.value = "";
  94. //渲染内容到HTML
  95. todoList.innerHTML = str;
  96. todoCom.innerHTML = stv;
  97. //删除的方法
  98. del();
  99. //完成的方法
  100. sel();
  101. //收拢的方式
  102. store();
  103. //完成隐藏
  104. com();
  105. console.log(timers);
  106. //提醒事件
  107. timers();
  108. //提醒时间
  109. second();
  110. hour();
  111. day();
  112. //雨点
  113. // rain();
  114. //拖动
  115. drag();
  116. sup();
  117. }
  118. //删除操作
  119. function del() {
  120. var del = document.querySelectorAll(".del");
  121. // console.log(del);
  122. if (del !== "") {
  123. del.forEach((element) => {
  124. element.onclick = function () {
  125. //本地读取
  126. var data = getData();
  127. //修改数据
  128. var index = element.getAttribute("id");
  129. data.splice(index, 1);
  130. //保存本地
  131. savaDate(data);
  132. //渲染
  133. load();
  134. };
  135. });
  136. }
  137. }
  138. //完成
  139. function sel() {
  140. var sel = document.querySelectorAll(".sel");
  141. if (sel !== "") {
  142. sel.forEach((element) => {
  143. element.onclick = function () {
  144. //本地读取
  145. var data = getData();
  146. //修改数据
  147. //获得索引
  148. var index = element.getAttribute("id");
  149. // console.log(data[index].done);
  150. //修改数组
  151. if (data[index].done === false) {
  152. //下雨庆祝
  153. rain();
  154. data.splice(index, 1, { title: data[index].title, done: true });
  155. } else {
  156. data.splice(index, 1, { title: data[index].title, done: false });
  157. }
  158. //保存本地
  159. savaDate(data);
  160. //渲染
  161. load();
  162. };
  163. });
  164. }
  165. }
  166. //完成收拢
  167. function store() {
  168. var store = document.querySelectorAll(".store");
  169. var vue = document.getElementById("vue");
  170. store.forEach((element) => {
  171. element.onclick = function () {
  172. if (todoCom.style.display == "none") {
  173. todoCom.style.display = "block";
  174. vue.innerHTML = "&#xe602;";
  175. } else {
  176. todoCom.style.display = "none";
  177. vue.innerHTML = "&#xe645;";
  178. }
  179. };
  180. });
  181. }
  182. //完成隐藏
  183. function com() {
  184. let Com = document.querySelectorAll(".com");
  185. Com.forEach((element) => {
  186. if (todoCom.innerHTML == "") {
  187. element.style.display = "none";
  188. } else {
  189. element.style.display = "block";
  190. }
  191. });
  192. }
  193. //提醒事件
  194. function timers() {
  195. var epo = document.querySelectorAll(".epo");
  196. console.log(epo);
  197. epo.forEach((element) => {
  198. var isShow = false;
  199. var time;
  200. element.onclick = function () {
  201. clearTimeout(time);
  202. if (!isShow) {
  203. isShow = true;
  204. element.childNodes[1].style.display = "block";
  205. } else {
  206. isShow = false;
  207. element.childNodes[1].style.display = "none";
  208. }
  209. //鼠标移入事件
  210. element.onmouseover = () => {
  211. clearTimeout(time);
  212. };
  213. //鼠标移出事件
  214. element.onmouseout = () => {
  215. clearTimeout(time);
  216. //计时器更改属性
  217. if (isShow) {
  218. time = setTimeout(() => {
  219. element.childNodes[1].style.display = "none";
  220. isShow = false;
  221. }, 400);
  222. }
  223. };
  224. };
  225. });
  226. }
  227. //计时5s
  228. function second() {
  229. let second1 = document.querySelectorAll(".second");
  230. // let hint=document.getElementById("hint");
  231. second1.forEach((element) => {
  232. element.onclick = function () {
  233. //本地读取
  234. var data = getData();
  235. var index = element.getAttribute("id");
  236. var time;
  237. var stv = "";
  238. console.log(index);
  239. clearTimeout(time);
  240. time = setTimeout(function () {
  241. Hint.style.display = "block";
  242. stv = data[index].title;
  243. Hint.innerHTML = stv;
  244. // alert("任务`"+data[index].title+"`时间到啦");
  245. }, 5000);
  246. };
  247. });
  248. }
  249. //计时1小时
  250. function hour() {
  251. let hour = document.querySelectorAll(".hour");
  252. hour.forEach((element) => {
  253. element.onclick = function () {
  254. //本地读取
  255. var data = getData();
  256. var stv = "";
  257. var index = element.getAttribute("id");
  258. var time;
  259. clearTimeout(time);
  260. time = setTimeout(function () {
  261. // alert("任务`"+data[index].title+"`时间到啦")
  262. Hint.style.display = "block";
  263. stv = data[index].title;
  264. Hint.innerHTML = stv;
  265. }, 60 * 1000 * 60);
  266. };
  267. });
  268. }
  269. //计时一天
  270. function day() {
  271. let day = document.querySelectorAll(".day");
  272. day.forEach((element) => {
  273. element.onclick = function () {
  274. //本地读取
  275. var data = getData();
  276. var index = element.getAttribute("id");
  277. var time;
  278. var stv = "";
  279. // console.log(index)
  280. clearTimeout(time);
  281. time = setTimeout(function () {
  282. Hint.style.display = "block";
  283. stv = data[index].title;
  284. Hint.innerHTML = stv;
  285. }, 1000 * 60 * 60 * 24);
  286. };
  287. });
  288. }
  289. //下雨事件
  290. function rain() {
  291. const box = document.getElementById("rainBox");
  292. var time;
  293. //每隔一段时间添加雨点
  294. time = setInterval(() => {
  295. // clearInterval(timer)
  296. let boxHeight = box.clientHeight;
  297. let boxWidth = box.clientWidth;
  298. const rain = document.createElement("div");
  299. rain.classList.add("rain");
  300. rain.style.top = 0;
  301. //随机刷新雨点位置
  302. rain.style.left = Math.random() * boxWidth + "px";
  303. //随机雨点透明度
  304. rain.style.opacity = Math.random();
  305. box.appendChild(rain);
  306. //每隔一段时间雨点下落
  307. let race = 1;
  308. const timer = setInterval(() => {
  309. if (parseInt(rain.style.top) > boxHeight) {
  310. clearInterval(timer);
  311. box.removeChild(rain);
  312. }
  313. race++;
  314. rain.style.top = parseInt(rain.style.top) + race + "px";
  315. }, 1);
  316. }, 1);
  317. setInterval(() => {
  318. clearTimeout(time);
  319. }, 10000);
  320. }
  321. //小猫
  322. function drag() {
  323. var isShow = false;
  324. let div = document.getElementById("div");
  325. let body;
  326. setInterval(() => {
  327. // 获取整个网页的宽度
  328. body = document.body.scrollWidth;
  329. // console.log(body)
  330. div.onclick = function () {
  331. if (body === 1490) {
  332. if (!isShow) {
  333. isShow = true;
  334. } else {
  335. isShow = false;
  336. }
  337. if (isShow) {
  338. // onmousemove鼠标指针移到指定的对象时发生
  339. document.onmousemove = function (e) {
  340. let event = e || window.event;
  341. //解决兼容问题,获得鼠标位置
  342. div.style.left = event.clientX - div.clientWidth / 2 + "px";
  343. };
  344. } else {
  345. document.onmousemove = function (e) {
  346. let event = e || window.event;
  347. //解决兼容问题,获得鼠标位置
  348. div.style.left = div.style.left;
  349. };
  350. }
  351. }
  352. };
  353. }, 100);
  354. }
  355. //超人
  356. function sup() {
  357. var isShow = false;
  358. let sup = document.getElementById("sup");
  359. var num = 0;
  360. sup.onclick = function () {
  361. //隐藏提醒框
  362. Hint.style.display = "none";
  363. let speed = 15;
  364. if (!isShow) {
  365. isShow = true;
  366. } else {
  367. isShow = false;
  368. }
  369. if (isShow) {
  370. timer = setInterval(() => {
  371. num += speed;
  372. // 获取整个网页的高度
  373. let body = document.body.scrollHeight;
  374. sup.style.bottom = num + "px";
  375. if (num >= body) {
  376. num = -250;
  377. }
  378. }, 100);
  379. } else {
  380. //结束计时
  381. clearInterval(timer);
  382. num = num;
  383. }
  384. };
  385. }
  386. };

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/640807
推荐阅读
相关标签
  

闽ICP备14008679号