资讯专栏INFORMATION COLUMN

turnjs fabricjs canvas 翻书

mylxsw / 1632人阅读

摘要:最近做了一个翻书效果的项目来总结一下实现过程和遇到的一些问题供自己以后快速解决问题希望也能帮到同样遇到此类问题的同学如果有更好的方法希望你能分享给我地址插件问题都是些自己觉的比较难解决的比较片面如有其他疑问可以留言交流或者当你从官网下载

最近做了一个翻书效果的项目, 来总结一下实现过程和遇到的一些问题, 供自己以后快速解决问题, 希望也能帮到同样遇到此类问题的同学, 如果有更好的方法,希望你能分享给我
git地址

插件:

Turn.js, Fabric.js, Touch.js, jQuery.js, jQuery-ui.js, ES6-Promise

问题都是些自己觉的比较难解决的, 比较片面, 如有其他疑问可以留言交流或者Bing

Turn.js

当你从Turn官网下载下来文件后它里面会提供5种事例代码, 根据需求我用的是docs, 先看一段简单的事例代码:

HTML

JS

$("#flipbook").turn({
  width: width,
  height: height,
  pages: length,
  autoCenter: true,
  when: { // 处理事件
    missing: function(e, pages) { // e:(event), pages:(type:arr,需要添加的页数)
      var book = $(this)
      pages.forEach(function(item, i) {
        addPage(item, i, data)
      })
    }
  }
})

把你的内容放在flipbook下面, 然后通过turn(object)来初始化你的数据, 当然你也可以使用DOM添加数据, 然后再初始化数据.区别可能是通过missing事件监听可以及时知道数据变化, 而通过DOM则不能(只是猜想没有验证).

Fabric.js

这里每一页内容都是由图片, 文字, 线段组成的, 所以用了canvas.

第一个问题是背景平铺问题, 因为在Fabric文档中好像不支持背景平铺, 也可能是我没有找到, 所以就用了这种方式, 直接给画布加背景:

$("#canvas").css({
  "background-image":"url(" + url + ")",
  "background-size": "size"
})

第二个问题是绘制贝塞尔曲线问题, 在绘制贝塞尔曲线用的是Path方法, 先看段代码:

var path = new fabric.Path("C43,128,28,143,17,153C14,156,12,158,12,158z", {
  opacity: .5, // 线条透明度
  stroke: "#e4393c", // 颜色
  strokeLineCap: "round", // 线头样式
  strokeWidth: 3, // 线宽
  fill: false, // 填充透明
  strokeLineJoin: "round" // 交点样式
})
canvas.add(path) // 添加到canvas上

你可以通过这种方式来加曲线, 其实完整写法是
new Path("M0,0L100,100C50,50,60,60,70,70z", {})
其中字母也可以小写, 逗号可以用空格代替或者短横线, 应该也支持其他的(我没试过)M代表将点移动那里然后L画出一条线, C代表开始画贝塞尔曲线, 是三次贝赛尔曲线(还有二次的,不知道Bing下), 三次贝塞尔曲线需要4个点来控制, 第一个点就是代码里面的(100,100), 紧接着是第一个控制点(50,50), 第二个控制点(60,60), 最后一个点(70,70)结束点z封闭一下. 你想在C后面加8个数? 别试了, 我试过没用. 在绘制过程中你会发现绘制出来的曲线总是首尾相连,如果不合需求你在绘制的最后就不能加z, 同时把fill设置为false.

第三个问题是层级问题, 你想文字在图片上面, 你想小的logo在最顶部但是往往绘制出来并不是你想要的效果, 这是因为图片和logo大部分都是图片, 请求是异步的, 你把异步拿来的图片画上去设置zindex并不能达到预期的效果, 先看代码:

var stepCounter = {}, layerArr = [], promiseArr = []

function adjustment(canvas, img, index) {
  var obj = new Object()
  obj.canvas = canvas
  obj.img = img
  obj.index = index
  return obj
}

function draw() {
    var promise = new Promise(function(res, rej) {
      var img = new Image()
      stepCounter[num] += 1
      img.src = url
      img.onload = function() {
        res(img)
      }
    })
    
    promise.then(function(img) {
      Img = new fabric.Image(img, {
        ... // 设置一些属性
      })
      canvas.add(Img)
      obj = adjustment(canvas, Img, -50)
      layerArr.push(obj)
      promiseArr.push(promise)
    })
}

setTimeout(function() {
  if (stepCounter[i] == promiseArr.length) {
    Promise.all(promiseArr).then(function() {
      layerArr.sort(function(a, b) {
        return a.index - b.index
      })
      layerArr.forEach(function(item, i) {
        var c = item.canvas
        c.moveTo(item.img, i)
        c.renderAll()
      })
    })
    return
  }
  setTimeout(arguments.callee, 50)
}, 50)

整体思路是这样的:

Promise加载图片, 同时将promisepush到数组promiseArr中, 可以用来判断图片是否都下载完和做对比判断.

假设第一页有20个图片, 每创建一个Promise就在stepCounter中对应的属性记录一下, 对比判断.

把图片的zIndex和一些必要信息放在一个数组中(layerArr), 图片下载完调整zIndex.

最后setTimeout检测当页绘制的图片与promise.length是否相同, 相同就证明所有图片都在加载中, 再用Promise.all()确定图片加载完成后就可以调整图片的zIndex了, 我参考了stackoverflow0, stackoverflow1, 考虑到Promise的兼容性, 需要引入ES6-Promise

翻书区域
用了Touchjs模拟, 就不多说了, 很简单.
分享

原来用的是jiathis分享, https后不能用了, 可能是不支持.

var qzone = "http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url={url}&title={title}&pics={pic}&summary={content}";
var sina = "http://service.weibo.com/share/share.php?url={url}&title={title}&pic={pic}&searchPic=false";
var weixin = "http://qr.liantu.com/api.php?text={url}";

所以直接调接口自己写了个

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/81262.html

相关文章

  • fabricjs上手指南

    摘要:可以对每一个对象使用动画,克隆,修改属性,事件监听,碰撞检测等。修改属性需及时渲染才能展示出效果。每次更改了对象的位置,大小时比如,,若要感知该对象的具体位置用于对象间碰撞边缘检测,或事件响应,需要使用方法重设对象的四个角坐标。 fabricjs是一个canvas的库,原本canvas的操作主要基于上下文,需要使用者自己从0开始去实现一些基本功能。而canvas库文件封装好了许多便利的...

    张迁 评论0 收藏0
  • FabricJS 前端绘图库使用总结(一)

    摘要:使用一段时间了,总得来说,是一款非常强大的矢量图工具,官方文档也算丰富,但文档组织形式不太好,而且少部分设计不太一致,还是需要整理一下。是最基础的对象,针对标签做的封装,可以管理内部绘制的所有对象。 使用一段时间了,总得来说,是一款非常强大的矢量图工具,官方文档也算丰富,但文档组织形式不太好,而且少部分api设计不太一致,还是需要整理一下。 Canvas canvas是最基础的对象,针...

    paney129 评论0 收藏0
  • 用typescript写静态页面

    摘要:在中调用库以调用一个库为例识别库需要一个接口文件,的接口文件已经做好了,只需在终端众即可安装其余步骤与以往写时一样,在中引入,在中引入编译后的文件以上就是在静态页面中的应用。 typescript有许多的优点,对于已经上手angular开发的朋友想必都会很熟悉。那么,如果想在其其他非angular框架环境下使用typescript需要哪些步骤呢? 以下内容,我们将以一个静态页面为例,简...

    canger 评论0 收藏0

发表评论

0条评论

mylxsw

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<