打造web版epub阅读器(书架设计)

写在前面的话

实现本阅读器需要进行以下几个步骤:

  1. 设计书架。(可添加图书,删除图书等)
  2. 打开并阅读epub图书。(可做高亮、笔记、书签,可显示目录并通过目录跳转)

本篇文章先实现第一项,设计书架,epub的阅读部分将在稍后文章中进行描述。
作者在实现时采用了vue + vue-loader来进行编码,直接使用js实现时原理都是一样的。

先附上效果图:

实现书架主要有以下几点:

  1. 图书的显示
  2. 图书的上传。
  3. 图书的存储。
  4. 图书的管理。

显示图书

设计对象 files 存储所有图书信息

<div v-for="file in files" class="booklocal">
    <div class="readtime">
        {{file.readtimedis}}
    </div>
    <el-card :body-style="{ padding: '0px' }">
        ![](file.thumbnail)
    </el-card>
    <div class="filename">
        <span>{{file.name}}</span>
    </div>
</div>

上传图书

因为在很多时候,我们要通过其他方式来触发文件选择框,所以在此将默认的文件选择器设置为不可见的,然后在其他(图片按钮)地方点击事件中触发文件选择框。

//添加file input并将其设置为不可见
<input type="file" multiple="multiple" class="fileInput" @change="selectedFiles" 
 ref="inputer" />
.fileInput {
    display: none;
}
//设置自定义按钮并在其点击事件中触发文件选择器。
<div class="book-add" v-on:click="addbook">+</div>
.book-add {
    width: 60px;
    height: 60px;
    border-radius: 30px;
    background-color: #FB771E;
    box-shadow: 5px 5px 10px #272727;
    text-align: center;
    line-height: 60px;
    font-size: 40px;
    //设置文字不能选中
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    cursor: pointer;
}
addbook: function(event) {
    $('.fileInput').click();
},
//用户选择文件后的触发事件,
selectedFiles: function(event) {
    var self = this;
    //获取文件
    var files = this.$refs.inputer.files;
    $.each(files, function(index, file) {//可在此处理上传的文件。
    }
}

存储图书

HTML5提供了对象存储技术,可以再IndexedDB数据库中保存Bolb对象,而文件正是一种特殊的Blob对象。
在进行对象存储时,其存储形式为Key---Object(文件),需要对每个文件进行区分,也就是说每个文件需要唯一的Key,在此我们使用MD5来对文件进行区分。

1. 提取文件MD5码

我们使用github上的开源库spark-md5来实现MD5码的提取。代码如下:

selectedFiles: function(event) {
    var self = this;
    //获取文件
    var files = this.$refs.inputer.files;
    $.each(files, function(index, file) {
        var fileName = file.name;
        if (fileName.substr(fileName.indexOf(".")) == '.epub') {
            if (file.size / 1024 / 1024 > 200) {
                //如果大于20M
                self.$notify({
                    title: '失败',
                    message: fileName + '大于200M,目前只支持小于200M文件',
                    type: 'error'
                });
            } else {
                var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice,
                    chunkSize = 2097152, // Read in chunks of 2MB
                    chunks = Math.ceil(file.size / chunkSize),
                    currentChunk = 0,
                    spark = new SparkMD5.ArrayBuffer(),
                    fileReader = new FileReader();
                var md5;
                fileReader.onload = function(e) {
                    spark.append(e.target.result); // Append array buffer
                    currentChunk++;
                    if (currentChunk < chunks) {
                        loadNext();
                    } else {
                        md5 = spark.end();//在此处获取MD5码。
                    }
                };
                fileReader.onerror = function() {
                    console.warn('oops, something went wrong.');
                };
                function loadNext() {
                    var start = currentChunk * chunkSize,
                        end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
                    fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
                }
                loadNext();
            }
        } else {
            self.$notify({
                title: '失败',
                message: fileName + '为非epub文件!',
                type: 'error'
            });
        }
    });
},
2. 存储图书

使用github上的开源库localForage来对文件进行存储。localForage将对IndexedDB数据库的操作进行了封装,代码如下:

//在vue中引入localForage
import localForage from "localforage";
//初始化localForage
this.store = localForage.createInstance({
    name: this.dbName
});
//使用开源库对文件进行存储。(MD5为以上代码获取的MD5值,file为循环中的file)
self.store.setItem(md5, file, function(err) {
});
3. 管理图书

我们先讨论管理图书都需要什么操作,使用什么方式的操作更容易让用户接受,然后再讨论每种操作的实现方式。

  1. 管理图书所需操作。
  • 添加图书
  • 导出图书
  • 删除图书
  • 重命名图书
  1. 操作方式
    使用右键来对其进行操作。如图:

右键菜单使用context.js来实现,具体使用方式请参考使用指南或如下代码:

addRightClick: function() {
        var self = this;
        context.init({
            preventDoubleContext: false
        });
        context.attach('.booklocal', [{
            text: '打开',
            action: function(e, selector) {
              //添加打开操作
            }
        }, {
            text: '导出',
            action: function(e, selector) {
              //添加导出操作
            }
        }, {
            text: '重命名',
            action: function(e, selector) {
              //添加重命名操作
            }
        }, {
            text: '删除',
            action: function(e, selector) {
              //添加删除操作
            }
        }]);
    },
  1. 操作的实现方式。
    设计文件管理是包含如下属性:
    var fileInfo=new Object();
    fileInfo.name = file.name; //文件显示的名字
    fileInfo.dname = md5; //文件的MD5值
    fileInfo.addtime = Date.parse(new Date()); //文件添加日期(如有需要可以添加)
    fileInfo.readtime = null; //文件上次阅读时间
    fileInfo.readtimedis = "未读过"; //显示给用户的文件上次阅读时间
    fileInfo.lastreadurl = null; //文件上次关闭时后的阅读位置,方便下次阅读直接跳转
    fileInfo.thumbnail = ""; //文件缩略图
    fileInfo.tags=[]; //阅读图书时所添加的标签
    fileInfo.notes=[]; //阅读图书时的笔记
    导出
    //导出
    export: function() {
    var self = this;
    //this.editFile为当前正在操作的文件,可在用户点击右键时获取
    this.store.getItem(this.editFile.dname, function(err, file) {
    if (file) {
    var fileName = self.editFile.name;
    if (fileName.substr(fileName.indexOf(".")) == '.epub') {
    self.downFile(file, self.editFile.name);
    } else {
    self.downFile(file, self.editFile.name + ".epub");
    }
    } else {
    }
    });
    },
    //下载
    downFile: function(blob, fileName) {
    if (window.navigator.msSaveOrOpenBlob) {
    navigator.msSaveBlob(blob, fileName);
    } else {
    var link = document.createElement('a');
    link.href = window.URL.createObjectURL(blob);
    link.download = fileName;
    link.click();
    window.URL.revokeObjectURL(link.href);
    }
    },
    删除
    删除就是把图书信息中的本图书删掉即可。
    vue的数据绑定机制,会自动删除相应图书。
    重命名
    重命名跟删除机制一样,只需要修改图书信息中的name即可。

总结:

书架的设计,主要包括图书的显示,图书的上传,图书的存储和图书的管理。

  • 使用VUE可以很方便的使界面显示和数据进行同步。
  • 图书上传时使用MD5来标记图书,可以方便索引图书。
  • 使用localForage可以很方便的对图书进行存储。
  • 使用context.js来实现右键菜单,对图书进行管理。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • iOS开发系列--网络开发 概览 大部分应用程序都或多或少会牵扯到网络开发,例如说新浪微博、微信等,这些应用本身可...
    lichengjin阅读 3,637评论 2 7
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,852评论 6 13
  • 今天的主题,运动。 2016年最有成就感的事,是自己开始形成运动的习惯。 最直接的表现是,某次去上海,住在酒店就开...
    石艳华阅读 149评论 1 1
  • 我喜欢仰望没有一丝云彩的蓝天,清澈澄明,有让我浮躁的心平静下来的魔力。
    333455adff2d阅读 187评论 0 0