溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

JavaScript圖片打印功能怎么實(shí)現(xiàn)

發(fā)布時(shí)間:2023-03-22 15:28:45 來(lái)源:億速云 閱讀:151 作者:iii 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要講解了“JavaScript圖片打印功能怎么實(shí)現(xiàn)”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“JavaScript圖片打印功能怎么實(shí)現(xiàn)”吧!

其實(shí)瀏覽器 window 對(duì)象提供了 print 方法,就可以對(duì)整個(gè)頁(yè)面進(jìn)行打印。只需要點(diǎn)擊按鈕執(zhí)行以下方法即可。

window.print()

調(diào)用此方法,會(huì)打印出整個(gè) html 里的內(nèi)容,即 document 對(duì)象下所有的頁(yè)面節(jié)點(diǎn)。而我們需要的是只打印頁(yè)面的某個(gè)元素部分,即只打印圖片。

很遺憾,瀏覽器在 具體的dom 節(jié)點(diǎn)上并沒(méi)有部署 print 方法,不過(guò)我們可以轉(zhuǎn)變個(gè)思路,我們可以將需要打印的元素提取出來(lái),同時(shí)構(gòu)造一個(gè)新的window對(duì)象,將提取出來(lái)的元素插入到這個(gè)window對(duì)象下,再調(diào)用打印即可。

<button @click="print">打印</button>
<div id="box">
	<img src="/test.jpg"/>
</div>

例如我們只需要打印id="box"下的 img

print(){
    const el = document.querySelector("#box")
    var newWindow=window.open("打印窗口","_blank");
    var docStr = el.innerHTML;
    newWindow.document.write(docStr);
    newWindow.document.close();
    newWindow.print();
    newWindow.close();
},

通過(guò) window.open 方式返回一個(gè)新的 window 對(duì)象,再調(diào)用 document.write 寫(xiě)入我們獲取到指定節(jié)點(diǎn),再打印即可。

這種方式有點(diǎn)不好的就是需要重新開(kāi)一個(gè) window ,并且設(shè)置一些打印的樣式會(huì)比較麻煩。所以不推薦。

我查閱了一些知名的打印插件,都是采用的 iframe 來(lái)構(gòu)造頁(yè)面來(lái)實(shí)現(xiàn)局部打印的。iframe 有個(gè)屬性 srcdoc可以渲染指定的html內(nèi)容

<iframe srcdoc="<p>Hello world!</p>"></iframe>

以往我們都是通過(guò)src來(lái)加載一個(gè)指定的頁(yè)面地址,這里通過(guò) srcdoc 來(lái)渲染指定的html內(nèi)容。下面實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的點(diǎn)擊按鈕打印圖片功能:

// 打印
function btnClick(){
	const iframe = document.createElement('iframe')
	// 視覺(jué)上隱藏 iframe
    iframe.style.height = 0
    iframe.style.visibility = 'hidden'
    iframe.style.width = 0
	const str = 
	`<html>
            <style media='print'>
                 @page{size:A4 landscape};margin:0mm;padding:0}
            </style>
            <body>
                 <div id="box"></div>
            </body>
	</html>
	`
    iframe.setAttribute('srcdoc', str);
    document.body.appendChild(iframe);
	// 一定要加載完成后執(zhí)行
	iframe.addEventListener("load",()=>{
        const image = document.querySelector('img').cloneNode();
        image.style.display = 'block'
        const box = iframe.contentDocument.querySelector('#box');
        box.appendChild(image);
		// 一定要圖片加載完再打印
        image.addEventListener('load', function () {
			// 打印
            iframe.contentWindow.print();
        });
    })
	iframe.contentWindow.addEventListener('afterprint', function () {
		iframe.parentNode.removeChild(iframe);
	});
}

對(duì)于打印的樣式設(shè)置,可以通過(guò)在style標(biāo)簽上添加media=print來(lái)設(shè)置

<style media='print'>
	@page{size:A4 landscape};margin:0mm;padding:0}
</style>

上述就指定了打印機(jī)默認(rèn)格式為A4紙張 橫向打印 ,margin設(shè)置成0毫米是為了保證不出現(xiàn)頁(yè)眉頁(yè)腳。

基礎(chǔ)功能的打印實(shí)現(xiàn)了,可是為了讓打印體驗(yàn)更好,產(chǎn)品經(jīng)理又提出了需求點(diǎn):

  • 當(dāng)圖片是橫圖時(shí),即寬度大于高度的圖片時(shí),需要將A4紙張橫向打印,然后圖片在A4里面上下左右都居中。同時(shí)要將這張圖片盡可能地鋪滿A4紙張,也不能改變圖片的寬高比(即不變形)。

  • 當(dāng)圖片是縱圖時(shí),即寬度小于高度的圖片時(shí),需要將A4紙張縱向打印,然后圖片在A4里面上下左右都居中。同時(shí)要將這張圖片盡可能地鋪滿A4紙張,也不能改變圖片的寬高比(即不變形)。

  • 圖片不要緊挨著紙張邊緣,留出一定邊距。

實(shí)現(xiàn)思路: 由于要保證紙張邊緣留有一定的空白區(qū)域,這個(gè)時(shí)也可以使用 margin 來(lái)實(shí)現(xiàn)。

<style media='print'>
	@page{size:A4 landscape;margin:10mm;}
</style>

但是不將 margin 設(shè)置成 0 的話,又會(huì)默認(rèn)出現(xiàn)頁(yè)眉頁(yè)腳。這顯然是矛盾的。這個(gè)時(shí)候我想到了一個(gè)好的思路,就是將圖片放置到一個(gè) div 容器里,這個(gè) div 寬高設(shè)置成 A4 一樣的大小。同時(shí)將div里面的圖片通過(guò) flex 布局來(lái)實(shí)現(xiàn)上下左右都居中。然后打印區(qū)域設(shè)置成這個(gè)容器就可以了。

JavaScript圖片打印功能怎么實(shí)現(xiàn)

由于 div 和 A4 紙張一樣大,所以 @page 里可以設(shè)置成 margin:0mm 來(lái)規(guī)避頁(yè)眉頁(yè)腳的出現(xiàn)。然后里面的圖片需要居中

// 獲取圖片寬高比
const rate = owidth/oheight
// 橫圖的話容器寬度就是A4的高度,即29.7cm,縱圖的話寬度就是21cm,由于剛好設(shè)置成21cm會(huì)溢出,多出一張紙,原因未明,所以我設(shè)置成20.9
const boxWidthCM = `${rate >1 ? 29.7 : 20.9}cm`
// 容器高度
const boxHeightCM = `${rate >1 ? 20.9 : 29.7}cm`

const str = 
`<html>
	<style media='print'>
		@page{size:A4 ${rate>1 ? 'landscape':'portrait'};margin:0mm;padding:0}
	</style>
	<style>
		*{padding:0;margin:0}
		body{height:100%}
		#box{
			width:${boxWidthCM};
			height:${boxHeightCM};
			display:flex;
			align-items:center;
			justify-content:center;
		}
	</style>
	<body>
		<div id="box"></div>
	</body>
</html>`
iframe.setAttribute('srcdoc', str);

居中問(wèn)題解決了,接下來(lái)就是解決圖片盡可能鋪滿紙張問(wèn)題。這個(gè)時(shí)候我們需要結(jié)合容器大小以及圖片寬高比來(lái)手動(dòng)計(jì)算圖片寬高,算法如下:

let imgW = null;
let imgH = null;
if(rate > 1){ // 橫圖
	if(rate>1.414){
		imgW = 29.7
		imgH = 29.7/rate
	} else {
		imgH = 20.9
		imgW = 20.9*rate
	}
} else {
	if(rate>(1/1.414)){
		imgW = 20.9
		imgH = 20.9/rate
	} else {
		imgH = 29.7
		imgW = 29.7*rate
	}
}

// 預(yù)留1cm邊距
imgW = imgW - 1
imgH = imgW/rate
iframe.addEventListener("load",()=>{
	const image = document.createElement("img")
	image.style.width = item.width
	image.style.height = item.height
	image.style.display = 'block'
	image.src = item.newUrl || item.url || item.original_content_url
	image.style.width = `${imgW}cm`
	image.style.height = `${imgH}cm`
	const box = iframe.contentDocument.querySelector('#box');
	box.appendChild(image);
	image.addEventListener('load', function () {
		iframe.contentWindow.print();
	});
})

完整代碼:

print(item){
	const { owidth,oheight,height } = item
	const rate = owidth/oheight
	const imgHeight = height.replace("px","")
	const iframe = document.createElement('iframe')
	iframe.style.height = 0
	iframe.style.visibility = 'hidden'
	iframe.style.width = 0
	const boxWidthCM = `${rate >1 ? 29.7 : 20.9}cm`
	const boxHeightCM = `${rate >1 ? 20.9 : 29.7}cm`
	let imgW = null;
	let imgH = null;
	if(rate > 1){ // 橫圖
            if(rate>1.414){
                imgW = 29.7
                imgH = 29.7/rate
            } else {
                imgH = 20.9
                imgW = 20.9*rate
            }
	} else {
            if(rate>(1/1.414)){
                imgW = 20.9
                imgH = 20.9/rate
            } else {
                imgH = 29.7
                imgW = 29.7*rate
            }
	}

	// 預(yù)留1cm邊距
	imgW = imgW - 1
	imgH = imgW/rate

	const str = 
	`<html>
            <style media='print'>
                  @page{size:A4 ${rate>1 ? 'landscape':'portrait'};margin:0mm;padding:0}
            </style>
            <style>
                    *{padding:0;margin:0}
                    body{height:100%}
                    #box{
                        width:${boxWidthCM};
                        height:${boxHeightCM};
                        display:flex;
                        align-items:center;
                        justify-content:center;
                    }
            </style>
            <body>
                  <div id="box"></div>
            </body>
	</html>`
	iframe.setAttribute('srcdoc', str);
	document.body.appendChild(iframe);
	iframe.addEventListener("load",()=>{
		const image = document.createElement("img")
		image.style.width = item.width
		image.style.height = item.height
		image.style.display = 'block'
		image.src = item.newUrl || item.url || item.original_content_url
		image.style.width = `${imgW}cm`
		image.style.height = `${imgH}cm`
		const box = iframe.contentDocument.querySelector('#box');
		box.appendChild(image);
		image.addEventListener('load', function () {
			iframe.contentWindow.print();
		});
	})
	iframe.contentWindow.addEventListener('afterprint', function () {
		iframe.parentNode.removeChild(iframe);
	});
}

感謝各位的閱讀,以上就是“JavaScript圖片打印功能怎么實(shí)現(xiàn)”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)JavaScript圖片打印功能怎么實(shí)現(xiàn)這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI