2016-07-16 1 views
1

Я использую следующий код для рендеринга элементов DOM в качестве данных холста, а затем создаю PDF-файл с ними.PDFMake цикл с использованием данных холста не поддерживает правильный порядок

мне пришлось создать цикл для этого, потому что, если все это было одно изображение, невозможно правильно разместить данные на несколько страниц.

$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 визуализатора вы начали. Когда вызываемый обратный вызов вызывается, уменьшите счет на единицу. Когда счетчик равен нулю, вы знаете, что все документы были обработаны, поэтому вы можете вызвать createPdf.

Ниже приведены изменения

$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 
    } 

} 

Единственное, что я не был уверен, был заказ вы хотели pdfElements появляться. Изменения будут размещать отображаемый контент в массиве содержимого в том же порядке, что и document.getElementsByClassName("pdfElement");.

Если вы хотите документы в content.reverse вызова реверс порядка(), когда счетчик возвращается к нулю, и вы готовы создать PDF.

Закрытие - очень мощная функция Javascript. Если вы не знаете, как работает закрытие, то обзор стоит того времени.

MDN closures как хорошее место как любой, чтобы начать, и есть много ресурсов в сети, чтобы узнать.

+0

большое спасибо, что нашли время, чтобы написать это, у меня есть метод, который работает немного быстрее, что я буду добавлять в ответ прямо сейчас. ура! – Taylorsuk

3

Кажется, что html2canvas возвращает обещание:

$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

такой же проблема здесь, не работает? –

 Смежные вопросы

  • Нет связанных вопросов^_^