最近作了一個翻書效果的項目, 來總結一下實現過程和遇到的一些問題, 供本身之後快速解決問題, 但願也能幫到一樣遇到此類問題的同窗, 若是有更好的方法,但願你能分享給我
git地址php
插件:
Turn.js, Fabric.js, Touch.js, jQuery.js, jQuery-ui.js, ES6-Promisecss
問題都是些本身覺的比較難解決的, 比較片面, 若有其餘疑問能夠留言交流或者Bingjquery
Turn.js
當你從Turn官網下載下來文件後它裏面會提供5種事例代碼, 根據需求我用的是docs, 先看一段簡單的事例代碼:git
<div id="flipbook"></div>
$('#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則不能(只是猜測沒有驗證).es6
Fabric.js
這裏每一頁內容都是由圖片, 文字, 線段組成的, 因此用了canvas.github
第一個問題是背景平鋪問題, 由於在Fabric文檔中好像不支持背景平鋪, 也多是我沒有找到, 因此就用了這種方式, 直接給畫布加背景:json
$('#canvas').css({ 'background-image':'url(' + url + ')', 'background-size': 'size' })
第二個問題是繪製貝塞爾曲線問題, 在繪製貝塞爾曲線用的是Path方法, 先看段代碼:canvas
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.api
第三個問題是層級問題, 你想文字在圖片上面, 你想小的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
加載圖片, 同時將promise
push到數組promiseArr
中, 能夠用來判斷圖片是否都下載完和作對比判斷.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}';
因此直接調接口本身寫了個