资源无需等待,交易就趁现在,全面资源整合网络大咖云集,让你轻松玩转互联网!
您需要 登录 才可以下载或查看,没有账号?立即注册
×
引用一个JS文件来实现任意页面弹窗公告,弹窗公告代码JS文件本地化可放心使用。
效果展示
公告能够在不同设备自适应显示 实现方法1.在网站目录创建文件 itjs.js ,并且粘贴以下代码到你刚刚创建的这个JS文件里面。
- // 公告弹窗
- (function () {
- function showAnnounce() {
- const lastClose = localStorage.getItem('announceLastClose');
- if (!lastClose) return true;
- const oneDayAgo = Date.now() - (24 * 60 * 60 * 1000);
- return new Date(lastClose).getTime() < oneDayAgo;
- }<p></p>
- <p style="line-height: 30px; text-indent: 2em;"> if (!showAnnounce()) return;</p>
- <p style="line-height: 30px; text-indent: 2em;"> const cfg = window.announceConfig || {
- title: "公告通知",
- items: [
- {
- icon: "news",
- title: "最新公告",
- content: "本平台新增多项安全验证功能,建议您及时完善个人信息。"
- },
- {
- icon: "update",
- title: "功能更新",
- content: "新版移动端已上线,支持离线模式和数据同步功能。"
- }
- ],
- noShowText: "一天内不再显示",
- laterText: "稍后提醒",
- okText: "我知道了",
- mainColor: "#3b82f6",
- maxW: "500px",
- z: 9999
- };</p>
- <p style="line-height: 30px; text-indent: 2em;"> function addStyles() {
- const style = document.createElement('style');
- style.textContent = `
- .announce-mask {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: rgba(0,0,0,0.5);
- z-index: ${cfg.z - 1};
- opacity: 0;
- visibility: hidden;
- transition: opacity 0.3s;
- backdrop-filter: blur(4px);
- }
-
- .announce-mask.show {
- opacity: 1;
- visibility: visible;
- }
-
- .announce-box {
- position: fixed;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%) scale(0.95);
- background: white;
- border-radius: 10px;
- max-width: ${cfg.maxW};
- width: calc(100% - 30px);
- box-shadow: 0 5px 20px rgba(0,0,0,0.1);
- z-index: ${cfg.z};
- overflow: hidden;
- opacity: 0;
- visibility: hidden;
- transition: all 0.3s;
- }
-
- .announce-box.show {
- opacity: 1;
- visibility: visible;
- transform: translate(-50%, -50%) scale(1);
- }
-
- .announce-head {
- background: ${cfg.mainColor};
- color: white;
- padding: 15px 20px;
- display: flex;
- align-items: center;
- justify-content: space-between;
- }
-
- .announce-title {
- margin: 0;
- font-size: 1.2rem;
- display: flex;
- align-items: center;
- gap: 10px;
- }
-
- .announce-close {
- background: none;
- border: none;
- color: white;
- font-size: 1.5rem;
- cursor: pointer;
- width: 30px;
- height: 30px;
- display: flex;
- align-items: center;
- justify-content: center;
- border-radius: 50%;
- }
-
- .announce-close:hover {
- background: rgba(255,255,255,0.2);
- }
-
- .announce-body {
- padding: 20px;
- }
-
- .announce-list {
- margin: 0;
- padding: 0;
- list-style: none;
- }
-
- .announce-item {
- display: flex;
- gap: 12px;
- padding: 15px 0;
- border-bottom: 1px solid #f1f5f9;
- }
-
- .announce-item:last-child {
- border-bottom: none;
- padding-bottom: 0;
- }
-
- .announce-icon {
- width: 40px;
- height: 40px;
- border-radius: 8px;
- display: flex;
- align-items: center;
- justify-content: center;
- flex-shrink: 0;
- }
-
- .announce-icon.news {
- background: #e0f2fe;
- }
-
- .announce-icon.update {
- background: #e6f7ee;
- }
-
- .announce-icon svg {
- width: 20px;
- height: 20px;
- }
-
- .announce-icon.news svg {
- fill: #0284c7;
- }
-
- .announce-icon.update svg {
- fill: #059669;
- }
-
- .announce-text {
- flex: 1;
- }
-
- .announce-item-title {
- margin: 0 0 5px 0;
- font-size: 1rem;
- font-weight: 600;
- color: #1e293b;
- }
-
- .announce-item-desc {
- margin: 0;
- font-size: 0.9rem;
- color: #64748b;
- line-height: 1.5;
- }
-
- .announce-option {
- padding: 0 20px 15px;
- }
-
- .announce-check {
- display: flex;
- align-items: center;
- gap: 8px;
- cursor: pointer;
- }
-
- .announce-checkbox {
- width: 18px;
- height: 18px;
- accent-color: ${cfg.mainColor};
- }
-
- .announce-check-label {
- font-size: 0.9rem;
- color: #64748b;
- }
-
- .announce-foot {
- padding: 15px 20px;
- border-top: 1px solid #f1f5f9;
- display: flex;
- gap: 10px;
- }
-
- .announce-btn {
- padding: 9px 15px;
- border: none;
- border-radius: 6px;
- font-size: 0.9rem;
- cursor: pointer;
- flex: 1;
- transition: all 0.2s;
- }
-
- .announce-btn.later {
- background: #f1f5f9;
- color: #475569;
- }
-
- .announce-btn.later:hover {
- background: #e2e8f0;
- }
-
- .announce-btn.ok {
- background: ${cfg.mainColor};
- color: white;
- }
-
- .announce-btn.ok:hover {
- background: ${shadeColor(cfg.mainColor, -15)};
- }
-
- @media (max-width: 480px) {
- .announce-foot {
- flex-direction: column;
- }
- }
- `;
- document.head.appendChild(style);
- }</p>
- <p style="line-height: 30px; text-indent: 2em;"> function shadeColor(color, percent) {
- let R = parseInt(color.substring(1, 3), 16);
- let G = parseInt(color.substring(3, 5), 16);
- let B = parseInt(color.substring(5, 7), 16);</p>
- <p style="line-height: 30px; text-indent: 2em;"> R = parseInt(R * (100 + percent) / 100);
- G = parseInt(G * (100 + percent) / 100);
- B = parseInt(B * (100 + percent) / 100);</p>
- <p style="line-height: 30px; text-indent: 2em;"> R = R < 255 ? R : 255;
- G = G < 255 ? G : 255;
- B = B < 255 ? B : 255;</p>
- <p style="line-height: 30px; text-indent: 2em;"> R = Math.round(R);
- G = Math.round(G);
- B = Math.round(B);</p>
- <p style="line-height: 30px; text-indent: 2em;"> const RR = (R.toString(16).length === 1) ? "0" + R.toString(16) : R.toString(16);
- const GG = (G.toString(16).length === 1) ? "0" + G.toString(16) : G.toString(16);
- const BB = (B.toString(16).length === 1) ? "0" + B.toString(16) : B.toString(16);</p>
- <p style="line-height: 30px; text-indent: 2em;"> return "#" + RR + GG + BB;
- }</p>
- <p style="line-height: 30px; text-indent: 2em;"> function closeAnnounce(mask, box, noShow) {
- mask.classList.remove('show');
- box.classList.remove('show');</p>
- <p style="line-height: 30px; text-indent: 2em;"> if (noShow) {
- localStorage.setItem('announceLastClose', new Date().toISOString());
- }</p>
- <p style="line-height: 30px; text-indent: 2em;"> setTimeout(() => {
- mask.remove();
- box.remove();
- }, 300);
- }</p>
- <p style="line-height: 30px; text-indent: 2em;"> function createItems(container) {
- const list = document.createElement('ul');
- list.className = 'announce-list';</p>
- <p style="line-height: 30px; text-indent: 2em;"> cfg.items.forEach(item => {
- const li = document.createElement('li');
- li.className = 'announce-item';</p>
- <p style="line-height: 30px; text-indent: 2em;"> const icon = document.createElement('div');
- icon.className = `announce-icon ${item.icon}`;</p>
- <p style="line-height: 30px; text-indent: 2em;"> let svg = '';
- if (item.icon === 'news') {
- svg = `
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
- <path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14zM7 7h5v5H7zm5 7H7v2h5zm2-4h2v2h-2zm0 4h2v2h-2z"/>
- </svg>
- `;
- } else if (item.icon === 'update') {
- svg = `
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
- <path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8zm-2 8v3l4-4-4-4v3H6v2h4z"/>
- </svg>
- `;
- }</p>
- <p style="line-height: 30px; text-indent: 2em;"> icon.innerHTML = svg;</p>
- <p style="line-height: 30px; text-indent: 2em;"> const text = document.createElement('div');
- text.className = 'announce-text';</p>
- <p style="line-height: 30px; text-indent: 2em;"> const title = document.createElement('h4');
- title.className = 'announce-item-title';
- title.textContent = item.title;</p>
- <p style="line-height: 30px; text-indent: 2em;"> const desc = document.createElement('p');
- desc.className = 'announce-item-desc';
- desc.textContent = item.content;</p>
- <p style="line-height: 30px; text-indent: 2em;"> text.appendChild(title);
- text.appendChild(desc);</p>
- <p style="line-height: 30px; text-indent: 2em;"> li.appendChild(icon);
- li.appendChild(text);
- list.appendChild(li);
- });</p>
- <p style="line-height: 30px; text-indent: 2em;"> container.appendChild(list);
- }</p>
- <p style="line-height: 30px; text-indent: 2em;"> function createAnnounce() {
- const mask = document.createElement('div');
- mask.className = 'announce-mask';</p>
- <p style="line-height: 30px; text-indent: 2em;"> const box = document.createElement('div');
- box.className = 'announce-box';</p>
- <p style="line-height: 30px; text-indent: 2em;"> const head = document.createElement('div');
- head.className = 'announce-head';</p>
- <p style="line-height: 30px; text-indent: 2em;"> const title = document.createElement('h3');
- title.className = 'announce-title';
- title.innerHTML = `
- <svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor">
- <path d="M12 2c5.51 0 10 4.49 10 10s-4.49 10-10 10S2 17.51 2 12 6.49 2 12 2zm0 2c-4.41 0-8 3.59-8 8s3.59 8 8 8 8-3.59 8-8-3.59-8-8-8zm-1 3h2v6h-2zm0 8h2v2h-2z"/>
- </svg>
- ${cfg.title}
- `;</p>
- <p style="line-height: 30px; text-indent: 2em;"> const closeBtn = document.createElement('button');
- closeBtn.className = 'announce-close';
- closeBtn.textContent = '×';
- closeBtn.addEventListener('click', () => {
- closeAnnounce(mask, box, false);
- });</p>
- <p style="line-height: 30px; text-indent: 2em;"> head.appendChild(title);
- head.appendChild(closeBtn);</p>
- <p style="line-height: 30px; text-indent: 2em;"> const body = document.createElement('div');
- body.className = 'announce-body';
- createItems(body);</p>
- <p style="line-height: 30px; text-indent: 2em;"> const option = document.createElement('div');
- option.className = 'announce-option';</p>
- <p style="line-height: 30px; text-indent: 2em;"> const check = document.createElement('label');
- check.className = 'announce-check';</p>
- <p style="line-height: 30px; text-indent: 2em;"> const checkbox = document.createElement('input');
- checkbox.type = 'checkbox';
- checkbox.className = 'announce-checkbox';
- checkbox.id = 'noShow';</p>
- <p style="line-height: 30px; text-indent: 2em;"> const label = document.createElement('span');
- label.className = 'announce-check-label';
- label.textContent = cfg.noShowText;</p>
- <p style="line-height: 30px; text-indent: 2em;"> check.appendChild(checkbox);
- check.appendChild(label);
- option.appendChild(check);</p>
- <p style="line-height: 30px; text-indent: 2em;"> const foot = document.createElement('div');
- foot.className = 'announce-foot';</p>
- <p style="line-height: 30px; text-indent: 2em;"> const laterBtn = document.createElement('button');
- laterBtn.className = 'announce-btn later';
- laterBtn.textContent = cfg.laterText;
- laterBtn.addEventListener('click', () => {
- closeAnnounce(mask, box, false);
- });</p>
- <p style="line-height: 30px; text-indent: 2em;"> const okBtn = document.createElement('button');
- okBtn.className = 'announce-btn ok';
- okBtn.textContent = cfg.okText;
- okBtn.addEventListener('click', () => {
- closeAnnounce(mask, box, checkbox.checked);
- });</p>
- <p style="line-height: 30px; text-indent: 2em;"> foot.appendChild(laterBtn);
- foot.appendChild(okBtn);</p>
- <p style="line-height: 30px; text-indent: 2em;"> box.appendChild(head);
- box.appendChild(body);
- box.appendChild(option);
- box.appendChild(foot);</p>
- <p style="line-height: 30px; text-indent: 2em;"> document.body.appendChild(mask);
- document.body.appendChild(box);</p>
- <p style="line-height: 30px; text-indent: 2em;"> setTimeout(() => {
- mask.classList.add('show');
- box.classList.add('show');
- }, 100);</p>
- <p style="line-height: 30px; text-indent: 2em;"> mask.addEventListener('click', (e) => {
- if (e.target === mask) {
- closeAnnounce(mask, box, false);
- }
- });</p>
- <p style="line-height: 30px; text-indent: 2em;"> document.addEventListener('keydown', (e) => {
- if (e.key === 'Escape') {
- closeAnnounce(mask, box, false);
- }
- });
- }</p>
- <p style="line-height: 30px; text-indent: 2em;"> if (document.readyState === 'loading') {
- document.addEventListener('DOMContentLoaded', () => {
- addStyles();
- createAnnounce();
- });
- } else {
- addStyles();
- createAnnounce();
- }
- })();</p>
复制代码
这里的文本按照你的需求进行更改,其中 icon 为图标名称,小白切勿随意修改,否则图标将无法正常显示。
2.在需要弹窗公告的页面加上以下代码即可实现弹窗公告功能。[size=1.2em]一般加在主页,也可以加在全局文件实现全部页面弹出公告,具体根据你的实际需求。 - <script src="itjs.js"></script>
复制代码 小白请注意:src后的路径根据实际情况调整!
关于这段代码放在页面哪里比较好: 1.body标签的末尾(推荐) [size=1.2em]注意:不是body标签后面!在body标签里面,放在</body>标签前。
优点:此时页面 DOM 加载完成后再执行公告脚本,避免因 DOM 未就绪导致的问题,同时不阻塞页面渲染
缺点:公告弹窗会比放在head中稍晚出现
2.head标签内,配合defer属性
- <script src="itjs.js" defer></script>
复制代码优点:提前加载脚本,但会等待 DOM 就绪后再执行,不阻塞页面渲染
缺点:需要浏览器支持defer属性(现代浏览器都支持)
3.head标签内,不使用任何属性(不推荐)
缺点:会阻塞页面渲染,直到脚本加载并执行完成,影响页面加载速度
[size=1.2em]综合考虑,推荐放在body标签末尾,这种方式既能保证脚本正常运行,又不会影响页面的加载性能,公告弹窗会在页面内容渲染完成后适时出现,给用户更好的体验。
如果希望公告尽可能早地出现,但又不影响页面加载,可以选择第二种方式(head中加defer)
代码说明模块化设计:采用立即执行函数表达式 (IIFE) 封装,避免全局变量污染,内部功能划分清晰(样式添加、元素创建、事件处理等) 响应式设计:在移动设备上自动调整布局,支持点击遮罩层、关闭按钮、ESC 键等多种关闭方式。 样式隔离:公告代码通过独特的类名前缀(announce-)避免样式冲突。 有任何问题可在评论区说明,博主随时在线,若你实在不会操作可以联系博主为你操作(有偿)。
|