何保持頁面樣式基本不變的前提下將HTML頁面導出為PDF,下面提供一些示例代碼,純屬個人原創,如對你有幫助請記得加關注、加收藏、點贊、轉發、分享~謝謝~~
<div>
<!-- 要打印的內容區 -->
<div ref="contentRef">
<div class="print-item print-out-flow">這是脫離文檔流的內容區域</div>
<div class="print-item">這是一行內容,也是最小葉子元素內容</div>
</div>
<!-- 打印內容容器 -->
<div ref="printContainerRef" class="print-container"></div>
</div>
/**
* 1.使用一個隱藏div裝載有滾動條的div.innerHTML
* 2.隱藏div使用position: absolute, z-index: -999, left: -9999px, width: 900px 控制讓用戶無感知
* 3.根據需要覆寫隱藏div內html樣式(例如textarea多行顯示有問題, 可以新增一個隱藏的div
* 包裹textarea的綁定值, 然后在打印樣式中覆寫樣式, 隱藏textarea并顯示對應div)
*/
handleExport() {
// 下面是VUE組件內獲取DOM元素代碼,將內容放置到打印區(定義的隱藏DIV)中
const contentRef = this.$refs.contentRef as HTMLElement;
const printContainerRef = this.$refs.printContainerRef as HTMLElement;
// 打印區的需額外處理絕對定位值, 調整使得第一個元素的.top值為0, 以便于頁面計算
printContainerRef.innerHTML = contentRef.innerHTML;
// 所有葉子div元素加上 print-item 樣式名, 脫離文檔流的額外添加 print-out-flow
handlePrintItem(printContainerRef); // 解決多頁內容可能被切割問題
html2canvas(printContainerRef, {allowTaint: false, useCORS: true}).then((canvas: any) => {
const contentHeight = canvas.height;
const contentWidth = canvas.width;
// pdf每頁顯示的內容高度
const pageHeight = contentWidth / 595.28 * 841.89;
// 未生成pdf的頁面高度
let offsetHeight = contentHeight;
// 頁面偏移值
let position = 0;
// a4紙的尺寸[595.28, 841.89], canvas圖片按a4紙大小縮放后的寬高
const imgWidth = 595.28;
const imgHeight = 595.28 / contentWidth * contentHeight;
const dataURL = canvas.toDataURL('image/jpeg', 1.0);
const doc = new jsPDF('p', 'pt', 'a4');
if (offsetHeight < pageHeight) {
doc.addImage(dataURL, 'JPEG', 0, 0, imgWidth, imgHeight);
} else {
while (offsetHeight > 0) {
doc.addImage(dataURL, 'JPEG', 0, position, imgWidth, imgHeight);
offsetHeight -= pageHeight;
position -= 841.89;
if (offsetHeight > 0) {
doc.addPage();
}
}
}
doc.save(this.generateReportFileName());
printContainerRef.innerHTML = '';
});
}
上干貨代碼:上面分頁導出PDF可能網上能看到類型代碼,但絕對找不到下面的代碼,純手搓解決分頁元素被切開問題(思路:獲取自身定位,如自己剛好在被分頁處,則加上一定的margin-top值將內容向下移)
/**
* 處理打印元素項, 修復分頁后被切割的元素
* @param printContainerRef 打印內容div容器
* @param itemClassName 打印最小元素標識類名
* @param outFlowClassName 脫離文檔流的元素標識類名
*/
export function handlePrintItem(
printContainerRef: HTMLElement,
itemClassName: string = 'print-item',
outFlowClassName: string = 'print-out-flow'
): void {
const rootClientRect = printContainerRef.getBoundingClientRect();
// 初始化頁面相關數據
const totalHeight = rootClientRect.height; // 內容總高度
const a4PageHeight = (printContainerRef.clientWidth / 595.28) * 841.89; // a4紙高度
let pageNum = Math.ceil(totalHeight / a4PageHeight); // 總頁數
let addPageHeight = 0; // 修正被分割元素而增加的頁面高度總和
let currentPage = 1; // 當前正在處理切割的頁面
const splitItemObj: { [key: number]: HTMLElement[] } = {}; // 內容中各頁被切割元素存儲對象
const printItemNodes: NodeListOf<HTMLElement> = printContainerRef.querySelectorAll(`.${itemClassName}`);
for (let item of printItemNodes) {
// 如果當前頁已經是最后一頁, 則中斷判斷
if (currentPage >= pageNum) {
break;
}
// 獲取元素絕對定位數據
const clientRect = item.getBoundingClientRect();
let top = clientRect.top;
const selfHeight = clientRect.height;
// 如果當前元素距離頂部高度大于當前頁面頁腳高度, 則開始判斷下一頁頁腳被切割元素
if (top > currentPage * a4PageHeight) {
// 換頁前修正上一頁被切割元素
addPageHeight += fixSplitItems(currentPage, a4PageHeight, splitItemObj[currentPage], outFlowClassName);
pageNum = Math.ceil((totalHeight + addPageHeight) / a4PageHeight);
top = item.getBoundingClientRect().top;
currentPage++;
}
// 如果元素剛好處于兩頁之間, 則記錄該元素
if (top > (currentPage - 1) * a4PageHeight && top < currentPage * a4PageHeight && top + selfHeight > currentPage * a4PageHeight) {
if (!splitItemObj[currentPage]) {
splitItemObj[currentPage] = [];
}
splitItemObj[currentPage].unshift(item);
// 如果當前元素是最后一個元素, 則直接處理切割元素, 否則交由處理下一頁元素時再處理切割
if (item === printItemNodes[printItemNodes.length - 1]) {
fixSplitItems(currentPage, a4PageHeight, splitItemObj[currentPage], outFlowClassName);
}
}
}
}
/**
* 修復當前頁所有被切割元素
* @param currentPage 當前頁
* @param pageHeight 每頁高度
* @param splitElementItems 當前被切割元素數組
* @param outFlowClassName 脫離文檔流的樣式類名
*/
function fixSplitItems(
currentPage: number,
pageHeight: number,
splitElementItems: HTMLElement[],
outFlowClassName: string
): number {
if (!splitElementItems || !splitElementItems.length) {
return 0;
}
const yMargin = 5; // y方向距離頁眉的距離
const splitItemsMinTop = getSplitItemsMinTop(splitElementItems);
if (!splitItemsMinTop) {
return 0;
}
let fixHeight = currentPage * pageHeight - splitItemsMinTop + yMargin;
const outFlowElement = splitElementItems.find((item) => item.classList.contains(outFlowClassName));
if (outFlowElement && outFlowElement.parentElement) {
const parentPreviousElement = outFlowElement.parentElement.previousElementSibling as HTMLElement;
fixHeight += getMarinTopNum(parentPreviousElement, outFlowElement.parentElement);
outFlowElement.parentElement.style.marginTop = `${fixHeight}px`;
return fixHeight;
}
splitElementItems.forEach((splitElement) => {
splitElement.style.marginTop = `${fixHeight}px`;
});
return fixHeight;
}
/**
* 獲取被切割元素數組中最小高度值(如一行有多個元素被切割,則選出距離頂部最小的高度值)
* @param splitElementItems 當前被切割元素數組
*/
function getSplitItemsMinTop(
splitElementItems: HTMLElement[]
): number | undefined {
// 獲取元素中最小top值作為基準進行修正
let minTop: number | undefined;
let minElement: HTMLElement | undefined;
splitElementItems.forEach((splitElement) => {
let top = splitElement.getBoundingClientRect().top;
if (minTop) {
minTop = top < minTop ? top : minTop;
minElement = top < minTop ? splitElement : minElement;
} else {
minTop = top;
minElement = splitElement;
}
});
// 修正當前節點及其前面同層級節點的margin值
if (minTop && minElement) {
const previousElement = splitElementItems[splitElementItems.length - 1].previousElementSibling as HTMLElement;
minTop -= getMarinTopNum(previousElement, minElement);
}
return minTop;
}
/**
* 通過前一個兄弟元素和元素自身的位置確認一個距離頂部高度修正值
* @param previousElement 前一個兄弟元素
* @param curElement 當前元素
*/
function getMarinTopNum(previousElement: HTMLElement, curElement: HTMLElement): number {
let preMarginNum = 0;
let curMarginNum = 0;
if (previousElement) {
// 獲取外聯樣式需要getComputedStyle(), 直接.style時對象的值都為空
const previousMarginBottom = window.getComputedStyle(previousElement).marginBottom;
preMarginNum = previousMarginBottom ? Number(previousMarginBottom.replace('px', '')) : 0;
}
const marginTop = window.getComputedStyle(curElement).marginTop;
curMarginNum = marginTop ? Number(marginTop.replace('px', '')) : 0;
return preMarginNum > curMarginNum ? preMarginNum : curMarginNum;
}
以上純原創!歡迎加關注、加收藏、點贊、轉發、分享(代碼閑聊站)~
位:1. 靜態定位 2.相對定位 3.絕對定位
1.值:static 默認的標準流;
2.值:relative 相對自身進行定位,沒有脫離標準流;
3.值:absolute 父元素
a.沒有父元素的時候,根據body進行;
b.有父元素但是父元素沒有定位,根據body定位;
c.有父元素并且父元素有定位(非靜態),根據父元素進行定位;
d.脫離標準流的一種技術;
子絕父相
浮動也是脫離標準流
思考:什么時候用定位?什么使用用浮動?
首選浮動進行模塊分區
一些出現疊壓效果的時候,或者特殊效果的時候才用定位!
如何讓小盒子在大盒子中既定位并且水平居中?
1.先left: 50%,將小盒子在大盒子平移大盒子的一半,
2. 設置margin-left:-(小盒子寬度的一半),注意一定是負數。
2.4 fixed:固定定位
background-attachment:fixed
position:fixed
使用的時候也要配合TRBL屬性來使用
特點:
1.不管頁面有多大,trbl永遠是相對于瀏覽器的邊框來的。
2.固定定位的元素也脫離了標準流(不在頁面上占據位置)
3.1 圖文對齊
文本與圖片在同一行中,文字與圖片的默認對齊方式是文字的基線對齊圖片的底線。
vertical-align:設置文本與圖片的對齊方式 top middle bottom
middle:將中線對齊
圖片:margin-top的時候,圖片和文字會同時下移
pà display:inline-block
圖文繞拍
圖片 float : left
Border: border-width | border-style | border-color
Border-width: 1px
Border-top-width:1px
Border-top: border-width | border-style | border-color
路徑查找方式:
1.確定HTML頁為基準;
2.向下查找 images/images/ 01.jpg
3.向上查找
background-postion: x y;
1.當直接加載的時候,圖片的左上角與容器的左上角是(0,0);
2.X為正向右偏移 Y為正向下偏移 ,負數反之;
3.英文
4.數值 + 英文的方式
*行高是具有繼承性的*
概念: 在html頁面,其實就相當于在這個頁面中擺盒子。
margin(外邊距)--盒子與盒子之間的間隙
作用:設置盒子與盒子之間的距離。
margin: 10px;
上下左右
margin: 10px 10px;
上下,左右
margin: 10 px 20px 10px;
上 左右 下
margin:10px 10px 20px 10px;
上右下左
浮動的特點
標準流與浮動:
標準流就是瀏覽器按順序擺放的一種方式
主流網頁設計的布局方式:
a.框架式網站 兩欄式 三欄式
b.通欄式布局
c.響應式網頁 (國內并不多)bootstrap
d.流式布局
更多內容關注大牛哥教育
tml的主體結構
標簽的分類
標簽的關系
sublime快捷鍵
單標簽
雙標簽
路徑
超鏈接額外知識運用
錨點
空連接
超鏈接的優化寫法 寫在head標簽中
特殊標記符
列表
<!doctype html><html><head>
單標簽
<!doctype html>
雙標簽
<head></head>
包含(嵌套關系、父子關系)
<head>
并列
<head></head><body></body>
快捷鍵 | 作用 |
---|---|
html:xt + tab | html4.01模板【新版本可能失效】 |
html + tab | html5模板 |
tab | 補全標簽 |
ctrl + shift + d | 快速復制一行 |
ctrl + shift + k | 快速刪除一行 |
ctrl + 鼠標左鍵單擊 | 集體輸入 |
ctrl + h | 查找替換 |
ctrl + f | 查找 |
ctrl + / | 注釋 |
ctrl + L | 快速選中當前行 |
ctrl + shift + ↑(↓) | 代碼的快速上移和下移 |
<!-- --> 注釋標簽<br /> 換行標簽<hr /> 水平線標簽<img src="logo.gif" alt="logo" title="這是淘寶的logo" width="200" height="100" />圖片標簽
<p></p> 段落標簽<h1></h1> 標題標簽 h1 - h6<font></font> 文本標簽<strong></strong> 文本加粗標簽,有語音加強<b></b> 文本加粗標簽<em></em> 文字傾斜,有語音加強<i></i> 文字傾斜<del></del> 刪除線,有語音加強<s></s> 刪除線<ins></ins> 下劃線,有語音加強<u></u> 下劃線<a title="百度" target="_blank">百度</a> 超鏈接
相對路徑
同一個目錄下直接寫文件的名稱就可以
文件和圖片在下一級目錄中,需要文件夾名稱 + \ + 文件名稱
圖片在上一級目錄中 ../ + 文件名稱
圖片在上一級的其它文件夾中 ../ + 文件夾名稱 + 文件名稱
總結:找到下級目錄使用/,找到上一級目錄使用../
絕對路徑
從盤符中開始的,這種路徑不能使用!因為項目最后都要移動,文件的路徑都是會變的。如:c:\baidu\logo.jpg
錨點
1.設置一個錨點 設置一個id
<div id="top"></div>
2.超鏈接到錨點
<a href="#top"></a>
空連接
<a href="#"></a>
超鏈接的優化寫法 寫在head標簽中
<base targer="_blank">
讓所有的超鏈接都是從新窗口中打開
空格 | |
---|---|
< | < |
> | > |
? | © |
更多信息請查閱
無序列表
<ul type="disc">
類型:disc 默認小黑點 circle 空心小圓點 square 小方塊
有序列表
<ol type="A" start="C">
類型:a A 字母順序 i I羅馬順序 1數字 start 表示開始的位置
自定義列表
<dl>
*請認真填寫需求信息,我們會在24小時內與您取得聯系。