本文最后更新于 2024-01-21T17:27:22+08:00
之前个人主页右下角的垂云都可以鼠标点击交互的,这次也想要实现这个功能,而且还要更丰富一些,功能包括:点击出现气泡框,鼠标悬停阻止自动消失,随机文字。
气泡框绘制
因为不想直接动源代码,所以这里用的是hexo-fluid的代码注入功能,因此css只能写成行内的style属性,看起来有些丑qwq
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <div id="textbox" style=" width:150px; height:50px; border:2px solid #FF88C2; border-radius: 4px; box-shadow: 2px 2px 2px pink; position:fixed; left:20px; bottom:180px; background-color:white; padding-top: 0.2em; padding-bottom: 0.2em; opacity: 0; z-index: 10; transition:0.5s all ease-in-out; "> <div id="saytext" style=" height:100%; font-size: 0.7em; text-align: center; display: flex; align-items: center; justify-content: center;"><span>你好,我是萍琪派!</span> </div> <div style=" width:0; height:0; border-top:10px solid #FF88C2; border-left:10px dashed transparent; border-right:10px dashed transparent; position:relative; left:60px; bottom:-0.2em;"> </div> </div>
|
简单解释:
- 一个总的气泡盒子,固定在合适的位置,并且加上了一些颜色,设置了文字居中之类的;注意
opacity
属性用来控制是否显示,之所以不用visibility
是因为这样没法通过transition
实现淡入淡出的功能;
- 然后下面绘制一个小小的倒三角;
- 中间的
<div>
用来装文字;
动态交互功能
首先是一些全局变量:
1 2 3 4 5 6 7 8 9 10 11
|
const cvs = document.querySelector("#live2d"); const box = document.querySelector("#textbox"); const text = document.querySelector("#saytext span"); const textbar = document.querySelector("#saytext"); const url = "/blog/js/saying.json"; let articles = null; let timer = null; let hover = false;
|
一些utility function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| function randomChoose(array) { let len = array.length; return array[randomNum(len-1)]; }
function randomNum(minNum,maxNum){ switch(arguments.length){ case 1: return Math.floor(Math.random()*(minNum+1)); break; case 2: return Math.floor(Math.random()*(maxNum-minNum+1)+minNum); break; default: return 0; break; } } function randomBoolean(){ return Math.random()>0.5; }
|
点击出现对话框以及鼠标悬停阻止消失
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function handler_say(event) { clearTimeout(timer); change_content(randomNum(0,1)); box.style.opacity=0.9; timer = setTimeout(()=>{ if(!hover){ box.style.opacity=0; } },2000); } function handler_mouseenter(event){ hover = true; } function handler_mouseleave(event){ hover = false; box.style.opacity=0; }
|
简单解释:
- 第一个函数是click事件的回调函数,和之前垂云那版的实现方式一样,先清除之前未执行的任务,然后改变气泡框文字内容,设置气泡框为可见,最后延迟2000ms之后重新让气泡框不可见;
- 第二个是鼠标悬浮于气泡框时的回调函数,简单设置变量
hover=true
,这样一来之前的延迟任务就不会执行;
- 第三个是鼠标移出气泡框的回调函数,设置
hover=false
,并且让气泡框不可见;
随机生成对话内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function change_content(group) { if(articles==null){return;} while(text.lastElementChild!=null){ text.removeChild(text.lastElementChild); } let anchor = document.createElement("a"); text.textContent = randomChoose(articles[group].text); if(group==0){ let item = randomChoose(articles[group].list); anchor.setAttribute("href",item.link); anchor.style.color = "#FF88C2"; anchor.textContent = item.title; text.appendChild(anchor); } }
|
主要想法是,对话分为有超链接和没有超链接的两组(group
),所有可能的对话内容都储存在saying.json
文件中,然后每次随机从其中某组中选择一句话,构造对应的元素,然后插入相应位置;
读取json文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| function say_init(){ cvs.style.cursor = 'grab'; cvs.addEventListener("click",handler_say); textbar.addEventListener("mouseenter",handler_mouseenter); textbar.addEventListener("mouseleave",handler_mouseleave); var request = new XMLHttpRequest(); request.open("get", url); request.send(null); request.onload = function(){ if(request.status == 200){ articles = JSON.parse(request.responseText); } else{ console.log("error:"+request.status+this.responseText); } } }
|
这是此部分功能的主例程,绑定之前所说的回调函数,以及读取json文件
saying.json
样例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| [ { "text":[ "叮~~ 随机掉落文章推荐:", "想看看这篇文章吗:" ], "list":[ { "title":"示例1", "link":"/blog/示例1" }, { "title":"示例2", "link":"https://xxx.xxx.com" } ] }, { "text":[ "点击我可以给你推荐随机文章哦", "如果喜欢这个站点,欢迎与朋友分享,快乐也会加倍哦", "小技巧:示例3" ] } ]
|
效果图
成功了~ 来看看我们的成果吧: