今晚又是在单位值班,最近看小说在印象笔记记了几百条零散的笔记,在印象笔记app上看要一条一条点开,今天把笔记导出来尝试着用js解析它,把一条条笔记转化为一张张小卡片,像刷抖音那样滑动着看,于是就用js写了一个demo,写完继续发个博客总结一下,作为专业的业余编程爱好者,不是以研究技术为主,博主一直是以做东西为导向,所以这篇文章也不例外,不是单一的一项技术,而是一个完整的demo,一会儿下面上代码,先看下手机端效果,大体如下:
这次这些代码全都是在手机上写的,前些日子在App Store发现的“koder”这个app,可以在手机上写代码,还自带个服务器和浏览器可以预览,还支持ssh,ftp等,在ios上算是功能比较强大了。
如图,koder就长这样,应急用一下还是可以的。
说一下印象笔记的导出文件enex,其实就是个xml文档,如下图
这就好办了,js解析xml很容易的,读取xml文件直接转化为json树形结构,我们只要找到需要的node节点把数据抠出来就ok了,下面还是上代码,注释比较详细了,由于是手机端,所以也得写一个类监听手指滑动事件。
<html>
<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, maximum-scale=1.0, user-scalable=no" />
<title>印象笔记卡片</title>
<style>
body{
overflow:hidden;
font-size: 24px;
}
#main{
position: relitave;
left: 10px;
top:10px;
right: 10px;
bottom: 10px;
}
.card{
position:relative;
left: 0px;
right: 0px;
top:0px;
margin:20px;
box-shadow:10px 10px 10px #000;
animation:cardMove 1s;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
}
.cardTitle{
position:relative;
left: 0px;
top:0px;
right: 0px;
height: 40px;
background: #00b548;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
padding: 10px;
overflow: hidden; text-overflow:ellipsis; white-space: nowrap;
}
.cardContent{
position:relative;
left: 0px;
top:0px;
right: 0px;
max-height:500px;
min-height:500px;
background: #ccc;
padding: 10px;
}
.hd{
display:none;
}
@keyframes cardMove
{
from {transform:rotate(-7deg);}
to {transform:rotate(0deg);}
}
.tm{
position: absolute;
bottom:10px;
right:10px;
}
.set{
position: fixed;
top:100px;
right: -400px;
bottom: 100px;
width:80%;
border-radius:10px;
background:#fff;
animation:setMove2 1s;
}
.set1{
position: fixed;
top:100px;
right: -400px;
bottom: 100px;
width:80%;
border-radius:10px;
background:#fff;
}
#set div{
padding:10px;
}
#set input{
font-size:24px;
color:#00b548;
width:100px;
margin:10px;
}
#set button{
font-size:26px;
background:#00b548;
border-radius:10px;
color:#fff;
}
@keyframes setMove1
{
from {right:-400px}
to {right:40px}
}
@keyframes setMove2
{
from {right:40px}
to {right:-400px}
}
.setMove{
position: fixed;
top:100px;
right: 40px;
bottom: 100px;
width:80%;
border-radius:10px;
background:#fff;
animation:setMove1 1s;
}
</style>
</head>
<body>
<div id="main">
</div>
<div id="set" class="set1">
<div class="cardTitle">
跳转
</div>
<div id="setS">q</div>
<input type="text">
<button>确定</button>
</div>
</body>
<script>
/*卡片*/
class Card{
fileName="印象笔记导出文件/对白.enex";
cardNum=0;//生成的卡片数量
haveMove=0;//动画移动量
//读取xml文件(需要在服务器环境下或者浏览器允许跨域,没兼容IE等)
loadXML(xmlFile){
var xmlDoc;
var xmlhttp = new window.XMLHttpRequest();
xmlhttp.open("GET",xmlFile,false);
xmlhttp.send(null);
xmlDoc = xmlhttp.responseXML.documentElement;
return xmlDoc;
}
//下一页
next(){
let screenHeight=document.body.scrollHeight;
let cardHeight=Math.floor(screenHeight/this.cardNum);
let This=this;
//翻页动画的实现
if(document.body.scrollTop<screenHeight){
if(this.haveMove<cardHeight){
document.body.scrollTop+=40;
this.haveMove+=40;
setTimeout(function(){
This.next();
},20);
}else{
console.log(this.haveMove);
document.body.scrollTop+=(cardHeight-this.haveMove);//处理位移偏差
this.haveMove=0;
}
}
}
//上一页
last(){
let screenHeight=document.body.scrollHeight;
let cardHeight=Math.floor(screenHeight/this.cardNum);
let This=this;
//翻页动画的实现
if(document.body.scrollTop>0){
if(this.haveMove<cardHeight){
document.body.scrollTop-=40;
this.haveMove+=40;
setTimeout(function(){
This.last();
},20);
}else{
document.body.scrollTop-=(cardHeight-this.haveMove);//处理位移偏差
this.haveMove=0;
}
}
}
//跳转
goTo(){
let screenHeight=document.body.scrollHeight;
let cardHeight=Math.floor(screenHeight/this.cardNum);
let page=document.querySelector("input").value;
page=parseInt(page)-1;
document.body.scrollTop=page*cardHeight;
document.querySelector("#set").className="set";
}
//主方法,读取enex文件生成卡片
main(){
let xml=this.loadXML(this.fileName).childNodes;
let html="";
let title="";
let content="";
for(var i=1;i<xml.length;i++){
try{
title=xml[i].childNodes[0].innerHTML;
content=xml[i].childNodes[1].childNodes[0].data;
this.cardNum+=1;
var tm=xml[i].childNodes[2].innerHTML;
var tmS="";//读取笔记创建时间
tmS+=tm.substr(0,4)+"/"+tm.substr(4,2)+"/"+tm.substr(6,2);
}catch(e){
console.log(e);
title="error";
content="";
var tmS="";
}
html+=`<div class="card"><div class="cardTitle">【${i}】${title}</div><div class="cardContent">${content}<div class="tm">${tmS}</div></div></div>`;
}
document.querySelector("#main").innerHTML=html;
//监听手指触摸
let This=this;
Touch.listener(function(){
//手指向下滑动
This.next();
},
function(){
//手指向上滑动
This.last();
},
function(){
//手指向左滑动
document.querySelector("#setS").innerHTML="输入要跳转的页码,共"+This.cardNum+"页,向右滑动关闭跳转功能。";
document.querySelector("#set").className="setMove";
},
function(){
//手指向右滑动
document.querySelector("#set").className="set";
},
);
//跳转按钮添加点击事件
document.querySelector("button").addEventListener("click",function(e){
This.goTo();
},false);
}
}
/*触摸事件*/
class Touch{
startx=0;
starty=0;
//取得角度
static getAngle(angx, angy) {
return Math.atan2(angy, angx) * 180 / Math.PI;
}
//根据起点终点返回方向 1向上 2向下 3向左 4向右 0未滑动
static getDirection(startx, starty, endx, endy){
var angx = endx - startx;
var angy = endy - starty;
var result = 0;
//如果滑动距离太短
if (Math.abs(angx) < 2 && Math.abs(angy) < 2) {
return result;
}
var angle = Touch.getAngle(angx, angy);
if (angle >= -135 && angle <= -45) {
result = 1;
} else if (angle > 45 && angle < 135) {
result = 2;
} else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) {
result = 3;
} else if (angle >= -45 && angle <= 45) {
result = 4;
}
return result;
}
//监听,参数为下上左右四个回调方法
static listener(downFun,upFun,leftFun,rightFun){
//手指接触屏幕
document.addEventListener("touchstart", function(e) {
this.startx = e.touches[0].pageX;
this.starty = e.touches[0].pageY;
}, false);
//手指离开屏幕
document.addEventListener("touchend", function(e) {
var endx, endy;
endx = e.changedTouches[0].pageX;
endy = e.changedTouches[0].pageY;
var direction = Touch.getDirection(this.startx, this.starty, endx, endy);
switch (direction) {
case 0:
break;
case 1:
downFun();
break;
case 2:
upFun();
break;
case 3:
leftFun();
break;
case 4:
rightFun();
break;
default:
}
}, false);
}
}
let card=new Card();
card.main();
</script>
</html>
需要注意的是,浏览器要是读取本地xml文件是需要跨域的,浏览器默认不让跨域就会报错,两种方法,一种把文件在服务器环境下运行,一种就是强制浏览器支持跨域,只需要在chrome或者edge浏览器快捷方式后面加个空格,然后接上一句话--args --disable-web-security --user-data-dir=D:\HaoroomsChromeUserData,如下图,然后浏览器就可以跨域请求了。