html2canvas 生成圖片踩坑記

本次作h5 活動,遇到一個需求,點擊button 把html 生成圖片,長按保存功能 因爲html的結構比較複雜,使用canvas 直接畫相對來講增長了不小工做量,因此使用html2canvas ,html2canvas的使用比較簡單,可是坑也不少css

老生常談的跨域問題

談到跨域問題,應該只要入了canvas toDataURL 轉成圖片的坑就應該遇到過這個問題,若是不進行跨域處理生成圖片不能跨域的圖片會空白處理 這個沒有好的解決方案, 圖片服務器須要配置Access-Control-Allow-Origin 因爲公司的開發build 與 js 是兩個團隊在作,build 團隊的圖片地址都是不可跨域的,並且頁面因此的圖片設置都是background image 的形式,針對這個問題我作了以下處理html

  1. 把以前build 圖片下載從新上傳到支持跨域的cnd 服務器
  2. 把須要生成圖片的html css 樣式背景圖片進行重寫

固然這樣尚未結束,配置html2canvasvue

html2canvas(dom, {
        backgroundColor: null,
        canvas,
        //allowTaint: true,
        useCORS: true
    })
複製代碼

useCORS 設置容許跨域,特別提醒 allowTaint 也是容許跨域,可是這個容許跨域只是容許你跨域生成canvas ,可是仍是不能把canvas轉化成圖片,要想解決toDataURL 的跨域問題,還須要使用useCORS。可是這兩個屬性不能共生web

生成的圖片模糊

把scale 設置成二倍直接上代碼算法

* 根據window.devicePixelRatio獲取像素比
 */
function DPR() {
    if (window.devicePixelRatio && window.devicePixelRatio > 1) {
        return window.devicePixelRatio;
    }
    return 1;
}

.....

  // DOM 節點計算後寬高
    const width = parseValue(box.width);
    const height = parseValue(box.height);
    // 獲取像素比
    const scaleBy = DPR()*2;
    // 建立自定義 canvas 元素
    var canvas = document.createElement('canvas');
    // 設定 canvas 元素屬性寬高爲 DOM 節點寬高 * 像素比
    canvas.width = width * scaleBy;
    canvas.height = height * scaleBy;
    // 設定 canvas css寬高爲 DOM 節點寬高
    canvas.style.width = `${width}px`;
    canvas.style.height = `${height}px`;
     // 獲取畫筆
    const context = canvas.getContext('2d');

    // 將全部繪製內容放大像素比倍
    context.scale(scaleBy, scaleBy);
    // imageSmoothingEnabled Canvas 2D API 用來設置圖片是否平滑的屬性,true表示圖片平滑(默認值),false表示圖片不平滑,默認的改變大小的算法會形成圖片模糊而且破壞圖片原有的像素。 若是那樣的話,設置屬性值爲false。
    context.mozImageSmoothingEnabled = false;
    context.webkitImageSmoothingEnabled = false;
    context.msImageSmoothingEnabled = false;
    context.imageSmoothingEnabled = false;
.....

html2canvas(dom, {
        backgroundColor: null,
        canvas,
        width: width, // 設置width
        height: height, // 設置height
        scale: scaleBy,// 設置scaleBy
        useCORS: true
    })
複製代碼

過程當中使用的雪碧圖最容易出現模糊的狀況,因此圖片須要使用2倍圖canvas

生成圖片過程當中會出現html閃現

可能這個題目不是很好的描述問題。我先描述一下問題所在,因爲html2canvas 生成圖片所在的html 必須是真實存在的,不然生成canvas爲空白。也就是須要生成html不能設置 disabled: none; visibility: hidden; 等屬性。 所以代表在調用html2canvas 生成canvas 過程當中必須dom 節點渲染完成。所以這就會致使在生成canvas 會出現原有html 的閃現 這個問題其實也比較好解決,用了一個小技巧,使用top 屬性,把html 移除視野 top:100% 固然這個解決方案比較多,目前我用的是這個跨域

動態渲染html 生成canvas會出現樣式錯亂

這個問題,自己須要生成的html 中有一部分是輪播圖,這樣html dom 會動態渲染, 解決方案很簡單,取消輪播圖,直接用 v-if(注:工程使用vue 開發)斷定進行html 渲染,取消輪播bash

生成的圖片background-repeat: no-repeat;不生效,致使圖片重複

這個問題我也沒找到緣由,結果就是雖然設置了background-repeat: no-repeat; 可是圖片底部會出現大約1像素的重複。 因爲沒有找到根本緣由,使用了最直接的的方案解決,直接把圖片高度增長2像素,成功避免了這個問題。(哈哈哈哈,我真是一個投機取巧的鬼才)服務器

html2canvas 不支持 display: -webkit-box

因爲代碼中有段文字須要多行末尾省略號,因此出現以下cssdom

display: -webkit-box;
    overflow: hidden;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    text-overflow: ellipsis;
複製代碼

在html2canvas中,會將css中的display中的值映射成一個數字,而在下圖的映射表中,只要找到了flex的映射值,並無--webkit-flex的映射值,因此-webkit-flex被映射成了DISPLAY.NONE,從而致使了isVisible的計算值返回了false,最終致使了沒法生成想要的canvas

解決方案不使用flex佈局,js 實現文字溢出,此方案僅限於文字個數具體的狀況下,因此比較侷限,你們有好的方案歡迎補充 css

height:2倍的line-height; /*根據實際需求更改*/ 
display:inline-block;
複製代碼

js

contentText(num){
        const ellipsis = oldContentText.length > num?'...':''
        return oldContentText.slice(0,num) + ellipsis
  }
複製代碼
相關文章
相關標籤/搜索