商业级web阅读器项目(上)

1.技术难点分析

  • 阅读器开发:
  • 分页算法、全文搜索算法、引入web字体、主题设计
  • 离线存储机制设计:LocalStorage+IndexDB
  • 实现各种复杂手势+交互动画,如何兼容手势+鼠标操作
  • 利用vuex+mixin实现组件解耦+复用 科大讯飞web在线语音合成API开发

2.项目准备

  • 字体图标
  • 项目依赖包+项目配置
  • 准备web字体
  • viewport配置
  • rem设置+自适应布局实现思路
  • global.scss和reset.scss
  • 搭建静态资源服务器Nginx

2.1.字体图标准备

在main.js中引入

$ import "./assets/styles/icon.css"

2.2.安装epubjs依赖包

$ npm install --save epubjs

2.3.准备web字体

![在这里插入图片描述](https://img-blog.csdnimg.cn/20190922195133297.png
然后再在index.html中引入即可,

<link rel="stylesheet" href="<%= BASE_URL %>fonts/daysOne.css">

**在这里需要注意的是,有两种方法引入文本字体,一种是上述所示的方法,另一种是把fonts放到assets中,这时,就不能在index.html中引入,而应该在main 中以import的形式引入
**

2.4.viewport配置

在index.html中

<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no">

2.5.rem配置

在App.vue中编写script代码

<script>
  export default {
      name:"App"
  }
  document.addEventListener('DOMContentLoaded', () => {
      const html = document.querySelector('html')
      let fontSize = window.innerWidth / 10
      fontSize = fontSize > 50 ? 50 : fontSize
      html.style.fontSize = fontSize + 'px'
  })
</script>

2.6. global.scss和reset.scss设置

在这里插入图片描述
在main中引入
import “./assets/styles/global.scss”

2.7.搭建nginx静态资源服务器

下载方法,及使用方法可参考 博客一文
,主要的命令 就是结束 nginx -s stop;接下来,在D盘的根目录下创建资源文件夹 resource
,然后修改 nginx.conf文件
添加这段代码,自起一个服务端口

server {
		listen 8081;
		server_name resource;
		root D:/resource;
		autoindex on;
		location / {
		  add_header Access-Control-Allow-Origin *;
		}
		add_header Cache-Control "no-cache,must-revalidate";
	}

在这里插入图片描述

当出现这个,说明成功了
在这里插入图片描述

3.阅读器–标题菜单、字号字体及主题设置功能开发

3.1.需求分析图

看看需求分析图
在这里插入图片描述

主要技术难点

  • epubjs
  • vuex+mixin
  • vue-i18n
  • 动态切换主题+书签手势操作

3.2.阅读器解析和渲染

把epub文件夹(放有所有epub电子书的文件夹)放到resource当中

由于访问资源每一本书的url是 http://localhost:8080/#/ebook/education/202yalishanda
这种方式,可见要用动态路由的方式来访问资源
什么是动态路由?听我说来
在这里插入图片描述
这种就是动态路由
,然后我们在浏览器上输入
http://localhost:8080/#/ebook/asasd
在EBook Reader中

<template>
    <div class="ebook-reader">
        {
  {$route.params.fileName}}
    </div>
</template>

接收到了参数
在这里插入图片描述
这就是动态路由

到了这这里想要获取nginx上的电子书时出现了跨域问题,暂时解决不了,先用 本地资源

3.3.翻页功能的实现

当屏幕向左划时,向上翻页,反之翻下一页。

//监听滑动翻页事件
                this.rendition.on("touchstart",event=>{
   
                    this.touchStartX = event.changedTouches[0].clientX;
                    this.touchStartTime = event.timeStamp;
                });
                this.rendition.on("touchend",event=>{
   
                    const offsetX = event.changedTouches[0].clientX-this.touchStartX;
                    const time = event.timeStamp - this.touchStartTime;
                    if(time<500 && offsetX>40){
   
                        this.prevPage();
                    }else if (time<500 && offsetX<-40) {
   
                        this.nextPage();
                    }else{
   
                        this.toggleTitleAndMenu()
                    }
                })
            prevPage(){
   
                if (this.rendition){
   
                   this.rendition.prev();
                   // this.$store.dispatch("setMenuVisible",false)
                    this.setMenuVisible(false);
               }
            },
            nextPage(){
   
              if (this.rendition){
   
                  this.rendition.next();
                  // this.$store.dispatch("setMenuVisible",false)
                  this.setMenuVisible(false);
              }
            },

在这里,值得注意的一点,需要修改epubjs的版本,修改为 “epubjs”: “0.3.71”,因为0.38以上的都不支持滑动

3.4.标题栏和菜单栏实现

先创建标题栏和菜单栏组件

//EbookTitle
<template>
    <transition name="slide-down">
        <div class="title-wrapper" v-show="menuVisible">
            <div class="left">
                <span class="icon-back"></span>
            </div>
            <div class="right">
                <div class="icon-wrapper">
                    <span class="icon-book"></span>
                </div>
                <div class="icon-wrapper">
                    <span class="icon-cart"></span>
                </div>
                <div class="icon-wrapper">
                    <span class="icon-more"></span>
                </div>
            </div>
        </div>
    </transition>
</template>

<script>
    // import {mapGetters} from "vuex"
    import {
     ebookMixin } from "./../../utils/mixin"
    export default {
    
        name: "EbookTitle",
        mixins:[ebookMixin],
        // computed:{
    
        //     ...mapGetters(["menuVisible"])
        // }
    }
</script>


<style lang='scss' scoped>
    @import './../../assets/styles/global';
    .title-wrapper {
    
        position: absolute;
        top: 0;
        left: 0;
        z-index: 101;
        display: flex;
        width: 100%;
        height: px2rem(48);
        background: white;
        box-shadow: 0 px2rem(8) px2rem(8) rgba(0, 0, 0, .15);
        font-size: px2rem(20);
        .left {
    
            flex: 0 0 px2rem(60);
            @include center;
        }
        .right {
    
            flex: 1;
            display: flex;
            justify-content: flex-end;
            .icon-wrapper {
    
                flex: 0 0 px2rem(40);
                @include center;
                .icon-cart {
    
                    font-size: px2rem(22);
                }
            }
        }
    }
</style>
//EbookMenu
<template>
    <div>
        <transition name="slide-up">
            <div class="menu-wrapper" :class="{
    'hide-box-shadow':!menuVisible}" v-show="menuVisible">
                <div class="icon-wrapper">
                    <span class="icon-menu icon" @click="showSetting(3)"></span>
                </div>
                <div class="icon-wrapper">
                    <span class="icon-progress icon" @click="showSetting(2)"></span>
                </div>
                <div class="icon-wrapper">
                    <span class="icon-bright icon" @click="showSetting(1)"></span>
                </div>
                <div class="icon-wrapper">
                    <span class="icon-a icon" @click="showSetting(0)">A</span>
                </div>
            </div>
        </transition>
    </div>
</template>

<script>
    // import {mapGetters} from "vuex";
    import {
     ebookMixin } from "../../utils/mixin.js"
    export default {
    
        name: "EbookMenu",
        mixins:[ebookMixin],
        // computed:{
    
        //     ...mapGetters(["menuVisible"])
        // },
        methods:{
    
            showSetting(){
    

            }
        }

    }
</script>


<style lang='scss' scoped>
    @import './../../assets/styles/global';
    .menu-wrapper {
    
            position: absolute;
            bottom: 0;
            left: 0;
            z-index: 102;
            display: flex;
            width: 100%;
            height: px2rem(48);
            background: white;
            box-shadow: 0 px2rem(-8) px2rem(8) rgba(0, 0, 0, .15);
            font-size: px2rem(20);
            &.hide-box-shadow {
    
        
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值