2016-07-16 13 views
1

次のコードを使用して、DOM要素をキャンバスデータとしてレンダリングし、次にそれらを使用してPDFを作成します。キャンバスデータを使用したPDFMakeループが正しい順序を維持しない

これはループを作成する必要がありました。なぜなら、すべて1枚の画像であれば、データを複数のページに正しく配置することができないからです。

$scope.pdfMaker = function() { 

    var content = []; 

    var pdfElement = document.getElementsByClassName("pdfElement"); 
    for (var i = pdfElement.length - 1; i >= 0; i--) { 
     html2canvas(pdfElement[i], { 
      onrendered: function(canvas) { 

       var data = canvas.toDataURL(); 

       content.push({ 
        image: data, 
        width: 500, 
        margin: [0, 5] 
       }); 
       console.log(canvas); 
      } 

     }); 
    } 
    var docDefinition = { 
     content: content 
    }; 

    setTimeout(function() { 
     pdfMake.createPdf(docDefinition).download("Score_Details.pdf"); 
    }, 10000); 

} 

問題:

  1. 私は意地の悪い10秒タイムアウトは、処理のための時間を許可することを持って、どのように私はすべてのキャンバスのデータが行われた後にPDFが作成できるように私のコードを再構築することができます。

  2. 私のキャンバスの要素は、変換時に混ざり合ってきていますが、正しい順序が重要です。どのようにDOM要素の順序を維持できますか?

答えて

1

コードを動作させるには、いくつかの改造が必要です。

説明からの問題は、html2canvasのレンダリング時間が異なるため、未定義の順序になることです。 forループ内のコードを関数にしてインデックスを渡すと、関数は引数の変数を閉じるようになります。レンダリングを配置するために(インデックス上で閉じる) htmlをコンテンツ配列の正しい位置に配置します。

すべてのレンダリングを完了し、pdfに変換できることを確認するには、開始したhtml2canvasレンダラーの数をカウントしてください。 onrenderedコールバックが呼び出されると、カウントが1だけ減少します。カウントがゼロの場合は、すべてのドキュメントがレンダリングされていることが分かるので、createPdfを呼び出すことができます。以下は

は私がわからなかった唯一のことは、あなたがpdfElementsを表示したかったためでし変化

$scope.pdfMaker = function() { 
    var i,pdfElement,content,count,docDefinition; 
    function makeCanvas(index){ // closure ensures that index is unique inside this function. 
     count += 1; // count the new render request 
     html2canvas(pdfElement[index], { 
      onrendered: function(canvas) { // this function closes over index 
       content[index] = { // add the canvas content to the correct index 
        image: canvas.toDataURL(), 
        width: 500, 
        margin: [0, 5] 
       }; 
       count -= 1; // reduce count 
       if(count === 0){ // is count 0, if so then all done 
        // render the pdf and download 
        pdfMake.createPdf(docDefinition).download("Score_Details.pdf"); 
       } 
      } 
     });   
    } 
    // get elements 
    pdfElement = document.getElementsByClassName("pdfElement"); 
    content = []; // create content array 
    count = 0; // set render request counter 
    docDefinition = {content: content}; // 
    for (i = pdfElement.length - 1; i >= 0; i--) { //do the loop thing 
     makeCanvas(i); // call the makeCanvas function with the index 
    } 

} 

です。この変更により、レンダリングされたコンテンツはコンテンツ配列に同じ順序で配置されます(document.getElementsByClassName("pdfElement");)。

ドキュメントを逆順にしたい場合は、カウントがゼロに戻り、pdfを作成する準備ができたらcontent.reverse()を呼び出します。

クロージャは、Javascriptの非常に強力な機能です。閉鎖の仕組みが不明な場合は、レビューに時間を割く価値があります。

MDN closuresは、どのような場所からでも始めることができますし、ネットから学ぶための十分なリソースがあります。 html2canvasが約束を返すようです

+0

は私が少し速く、私は今の答えとして追加することを働く方法を持って、これを書くために時間を割いてありがとうございました。乾杯! – Taylorsuk

3

$scope.pdfMaker = function() { 

    var promises = []; 
    var pdfElements = document.getElementsByClassName("pdfElement"); 

    for (var i = 0; i < pdfElements.length; i++) { 
     promises.push(
      html2canvas(pdfElements[i]).then(function(canvas) { 
       console.log('finished one!'); 
       return { 
        image: canvas.toDataURL(), 
        width: 500, 
        margin: [0, 5] 
       }; 
      }) 
     ); 
    } 

    console.log('done calling'); 
    $q.all(promises).then(function(content) { 
     console.log('all done'); 
     pdfMake.createPdf({ content: content }).download("Score_Details.pdf"); 
     console.log('download one'); 
    }, function(err) { 
     console.error(err); 
    }) 

} 
+0

ここで同じ問題が起きましたか? –

関連する問題