2016-12-06 56 views
11

我正在構建一個從數據生成pdf文件的工具,我需要構建兩種格式:105mm * 148mm和105mm * 210mm。所以我得到了我的整個文檔,現在是時候插入分頁符了。我用一個簡單的類來做:計算Vuejs中DOM元素之間距離的最佳方法是什麼?

.page-break { display: block; page-break-before: always; } 

現在我必須將這個類插入到我的v-for循環中。所以一個基本的想法是計算一個間隔,就像每個索引是6的倍數一樣,我插入一個。但這不是最好的方式,我想在內容超過90毫米時插入一箇中斷。

爲了做到這一點,我想計算兩個休息點之間的距離,如果距離接近90毫米,則插入一個新休息點。但是,我無法找到訪問我的動態DOM元素的方法...

所以問題很簡單:如何計算這個距離?或者如果有更好的方法來實現我的目標,我可以改進什麼?

+0

是有可能添加一些代碼第一次嘗試。 –

+0

@ hardik-satasiya done –

回答

3

我相信你在每個v-for中加入一個div/component,你可以爲每個div添加一個唯一的id。現在下面的方法可以給你一個div的高度px,你將有一些方法來將px轉換爲mm

如果您正在使用jquery,你可以做

$('#nthDiv').height(); 

如果沒有,你能做到以下幾點:

inner height

document.getElementById('#nthDiv').clientHeight; 

outer height

document.getElementById('#nthDiv').offsetHeight; 

如果你有下面的代碼:

<div v-for="(item, index) in items" :class="{'page-break': isBreakNeeded(index)}" :id="index + 'thDiv'"> 
    ///Your code 
</div> 

您需要添加下面的方法:

isBreakNeeded (index) {  
    var height = 0 
    do { 
     index -= 1; 
     height += document.getElementById('#' + index + 'thDiv').offsetHeight; 
     } while (index >= 0 || pageBreakAdded[index] == true) 
     if(height > threshold){ 
     pageBreakAdded[index] = true 
     return true 
     } 
     else{ 
     return false 
     } 
} 

您需要添加下列散列以及在VUE元素的數據屬性,這將保持在您添加哪些索引分頁追蹤:

pageBreakAdded: {} 
+0

用'v-if'條件的好主意,也許它會更快。 –

+0

@GeorgeAbitbol DId你發現這個方法很有用,你看到這裏有什麼問題嗎? – Saurabh

+0

@Saurabh,似乎你掌握了vue.js.我需要你的幫助。看看這裏:http://stackoverflow.com/questions/41843823/how-to-display-button-link-with-vue-js –

2

所以,我嘗試這種方法:

  1. 插入page-break我的循環模板內(div v-for each data text element
  2. 選擇所有page-break使用getBoundingClientRect()
    1. 遍歷選擇
    2. 渲染
    3. 計算後得到當前的休息之間的距離,如果它在可接受範圍之外,則將其從DOM中刪除。

這種方法的作品,但它是非常難看,這是非常難以計算一個良好的範圍,這是超貴!用一個小數據集很不錯,但有一整本書,它太長了......

這是做(與Vue模板)

<template> 
    <div class="content"> 
    <div class="pages"> 
     <div class="page-footer"> 
     <div class="page-break"></div> 
     </div> 

     <div class="dynamic"> 
     <div v-for="(entry, index) in conv" class="row"> 
      <div v-if="entry.msgs[0].value === 'break'"> 
      <span class="date">{{entry.msgs[0].metadate}}</span> 
      </div> 

      <div v-else> 
      <span class="author">{{ entry.user }}</span> 
      <span class="hour">{{ entry.msgs[0].metahour }}</span> 
      <div class="phrases"> 
       <span v-for="msg in entry.msgs"> 
       {{ msg.value }} 
       </span> 
      </div> 
      </div> 

      <div class="page-footer" :data-base="index"> 
      <span class="page-number" :data-base="index">{{ pageNumberFor(index) }}</span> 
      <div class="page-break"></div> 
      </div> 
     </div> 
     </div> 

     <div class="page-footer" data-base="end"> 
     <span class="page-number" data-base="end">{{ pageNumberFor('end') }}</span> 
     <div class="page-break"></div> 
     </div> 
    </div> 
    </div> 
</template> 

<script> 

import und from 'underscore' 

export default { 
    name: "Data", 

    data() { 
    return { 
     conv: null, 
     cleaned: false, 
     pageNumbers: {} 
    } 
    }, 

    computed: { 
    mmScale:() => 0.264583333, 
    heightBreak:() => 210 
    }, 

    mounted() { 
    this.$http.get('static/data_sorted_backup.json').then(
    // this.$http.get('static/data_sorted.json').then(
     (response) => { 
     this.conv = this.groupBy(response.data) 
     }, 
     (response) => { 
     console.log('error'); 
     } 
    ) 


    }, 

    updated() { 
    console.log('updated'); 
    if(!this.cleaned) this.cleanPageBreak() 
    }, 

    methods: { 
    groupBy (json) { 
     let result = [] 
     result.push(json[0]) 

     let punc = new RegExp(/[\?\.\!\;\(\)]?$/, 'ig') 

     for (var i = 1; i < json.length; i++) { 
     let val = json[i].msgs[0].value 
     val = val.charAt(0).toUpperCase() + val.slice(1); 
     if(punc.test(val) === false) val += '.' 
     json[i].msgs[0].value = val 

     let len = result[result.length -1].msgs.length 
     // if it's not the same day 

     let origin = result[result.length -1].msgs[len - 1].metadate 
     let new_entry = json[i].msgs[0].metadate 
     // console.log(i, origin, new_entry); 
     if(origin !== new_entry){ 
      result.push({ 
      msgs: [{ 
       value:"break", 
       metadate: json[i].msgs[0].metadate 
      }] 
      }) 
      i-- 
      continue; 
     } 

     // if the previous author is the same 
     if(result[result.length -1].user === json[i].user){ 
      result[result.length -1].msgs.push({ 
      value: json[i].msgs[0].value, 
      metadate: json[i].msgs[0].metadate, 
      metahour: json[i].msgs[0].metahour 
      }) 

     }else{ 
      result.push(json[i]) 
     } 
     } 

     return result 
    }, 

    cleanPageBreak() { 
     console.log('cleanPageBreak'); 
     let breaks = this.$el.querySelectorAll('.page-footer') 
     let distance 
     let enough 
     let previousTop = breaks[0].getBoundingClientRect().top 

     let seuil = this.heightBreak * 0.85 

     console.log(breaks.length, seuil); 

     for (let i = 1; i < breaks.length; ++i) { 
     console.log(i); 
     distance = (breaks[i].getBoundingClientRect().top - previousTop) * this.mmScale 

     enough = distance < this.heightBreak && distance >= seuil 


     if (enough) { 
      previousTop = breaks[i].getBoundingClientRect().top 
     } else if(i != breaks.length -1) { 
      breaks[i].remove() 
     } 
     } 
     this.cleaned = true 
     this.mapNumbers() 
    }, 

    mapNumbers() { 
     console.log('mapNumbers'); 
     let numbers = Array.from(this.$el.querySelectorAll('.page-number')) 

     numbers.map((elem, index) => { 
     this.pageNumbers[elem.dataset.base] = {} 
     this.pageNumbers[elem.dataset.base].index = index + 1 
     }) 
    }, 

    pageNumberFor (index) { 
     if(this.pageNumbers[index]) return this.pageNumbers[index].index 
     return 0 
    } 
    } 
} 
</script> 

<style lang="scss"> 
@import url('https://fonts.googleapis.com/css?family=Abel|Abhaya+Libre'); 


.page-footer{ 
    position: relative; 
    margin: 12mm 0; 
    // border: 1px dotted black; 

    .page-break { 
    display: block; 
    page-break-before: always; 
    } 

    .page-number { 
    position: absolute; 
    left: 50%; 
    transform: translate(-50%, 0); 
    top: -28mm; 
    } 
} 

.content { 
    padding: 0 16mm 0 10mm; 
    font-family: 'Abhaya Libre', serif; 

    .pages{ 
    position: relative; 
    } 
} 
.row { 
    margin: 0; 
    font-size: 0; 

    span{ 
    font-size: 13px; 
    } 
    span:first-letter { 
    text-transform: uppercase; 
    } 

    .date, .hour { 
    font-family: 'Abel', sans-serif; 
    } 
    .date { 
    font-size: 15px; 
    text-align: center; 
    display: block; 
    padding-top: 10mm; 
    padding-bottom: 2mm; 
    } 
    .author{ 
    display: block; 
    text-transform: uppercase; 
    text-align: center; 
    } 
    .hour { 
    margin-bottom: 3mm; 
    margin-top: -2px; 
    display: block; 
    text-align: center; 
    font-size: 9px; 
    } 
    .phrases{ 
    text-indent:5mm; 
    } 
} 

.row + .row { 
    margin-top: 5mm; 
} 
</style> 
相關問題