JavaScript實現(xiàn)圖片縮放功能
前言
平常,我們在查看圖片的時候,都有放大縮小的功能。如下圖
那么,我們如何在網頁中,對圖像進行縮放呢?
本文,我們來講講如何使用 JavaScript
實現(xiàn)圖片的縮放。當然,我們可以類比到其他的元素,比如視頻的縮放。
更改寬度
是的,很符合第一直覺邏輯的一種實現(xiàn)方式。電腦上查看相片也是使用的這種模式 - 直接保持外側容器的框高不變,等比例地更改圖片的尺寸。
我們來簡單舉個例子:
<div class="container" style="width: 400px; height: 300px;"> <img src="path/to/image.png" id="image" style="width: 400px;" /> </div>
(function(){ const ratio = 4 / 3; // 寬高比例 let imageDom = document.getElementById("image"); imageDom.addEventListener("click", function() { imageDom.style.width = 400 * ratio + "px"; }) })()
上面代碼中,我們設定了外部容器的尺寸是 400 * 300 px
,內部的圖像的寬度等同外部尺寸。當點擊圖片之后,圖像的寬度變?yōu)?nbsp;400 * 4 / 3 px
,外部的容器沒有發(fā)生更改。
那么,我們這種直接更改寬度的方法,在全屏的模式下,生效?
public static gotoFullscreen(dom: any): void { if (dom.requestFullscreen) { dom.requestFullscreen() } else if (dom.mozRequestFullScreen) { dom.mozRequestFullScreen() } else if (dom.webkitRequestFullscreen) { dom.webkitRequestFullscreen() } else if (dom.msRequestFullscreen) { dom.msRequestFullscreen() } else { console.error('當前瀏覽器不支持部分全屏!') } }
也就是通過上面的代碼進入到瀏覽器的全屏模式 gotoFullscreen(document.getElementsByClassName("container")[0])
。
然而,無論我們怎么設定圖像的寬度,比如 document.getElementById("image").style.width = "200%"
,都不會生效的。
我們是否還有其他進行縮放的方法在全屏模式下也能夠實現(xiàn)呢?
更改 Scale
我們可以保持圖片的實際的寬高是不變的,然后更改其 scaleX
和 scaleY
來實現(xiàn)。
<div class="container" style="width: 400px; height: 300px;"> <img src="path/to/image.png" id="image" style="width: 400px;" /> </div>
(function(){ const ratio = 4 / 3; // 框高比例 let imageDom = document.getElementById("image"); imageDom.addEventListener("click", function() { imageDom.style.transform = `scale(4/3, 4/3)`; }) })()
很明顯,與 更改寬度
小節(jié),唯一不同的點就是 imageDom.style.transform = scale(4/3, 4/3)
;,我們在點擊圖片的時候,使用 transform
屬性值 scale(x, y)
對其 x
軸和 y
軸進行縮放。
而且,在全屏的模式下,該方法依舊能夠實現(xiàn)對圖片的縮放。因為圖片的寬度不變。
取舍
兩種方案:更改寬度
和 更改 Scale
。我們應該選擇 更改 Scale
來對圖像進行縮放。因為:
- 更改
Scale
涉及的場景比 更改寬度 要廣 - 更改
Scale
性能比更改寬度性能優(yōu)越。因為更改寬度是對dom
進行操作,會造成回流和重排,而更改Scale
是利用圖形處理器(GPU)
來實現(xiàn)。
更改偏移位置
我們以方案二 - 更改 Scale
為基礎。
當我們希望查看點擊點的圖片。我們需要對其進行放大,并將點擊點放在外容器的中心點的位置。那么,我們就需要對圖像的位置進行處理。
我們可以使用 position: absolute; top: *px; left: *px;
來實現(xiàn),但是通過我們上面取舍小節(jié)的對比。我們有更好的替代方案 - 使用 translate(x, y) 來實現(xiàn)
。
這里我們使用 typescript
結合 angular
來實現(xiàn):
<div id="imageContainer"> <image id="image" [style]="{ width: imageRealWidth, transform: 'scale(' + imageAmplifyMultiple + ', ' + imageAmplifyMultiple + ') translate(' + imageTranslateX + 'px, ' + imageTranslateY + 'px)' }" /> </div>
對應的 javascript
如下:
// 放大圖片區(qū)域 public amplifyImagePortion(event) { let imageContainerCenterLeft : number; let imageContainerCenterTop : number; let _imageContainer: any = document.getElementById('imageContainer'); if(this.imageIsFullscreen) { // 全屏模式 imageContainerCenterLeft = _imageContainer.getBoundingClientRect().width / 2; imageContainerCenterTop =_imageContainer.getBoundingClientRect().height / 2; } else { // 非全屏的模式下 imageContainerCenterLeft = _imageContainer.getBoundingClientRect().left + _imageContainer.getBoundingClientRect().width / 2; imageContainerCenterTop = _imageContainer.getBoundingClientRect().top + _imageContainer.getBoundingClientRect().height / 2; } let clickPointLeft = event.pageX; let clickPointTop = event.pageY; this.imageTranslateX = (this.imageTranslateX * this.imageAmplifyMultiple + ( imageContainerCenterLeft - clickPointLeft)) / this.imageAmplifyMultiple; this.imageTranslateY = (this.imageTranslateY * this.imageAmplifyMultiple +(imageContainerCenterTop - clickPointTop)) / this.imageAmplifyMultiple; // 放大的倍數(shù) this.imageAmplifyMultiple = this.imageAmplifyMultiple * this.multipleStep; }
上面的案例中,我們只是進行放大功能的展示。
引入鼠標滾輪
下面,我們通過引入鼠標滾動,修改下 amplifyVideoPortion
方法來對圖像放大或縮小。
// 滾輪滾動 private mouseWheelFn(event) { if(!this.mouseWheel) { this.mouseWheel = fromEvent(document.getElementById('imageContainer'), 'wheel'); this.subscriptions.push( this.mouseWheel .pipe(throttleTime(50)) .subscribe((wheel: any) => { if(wheel.deltaY > 1) { // 進行局部放大 this.amplifyImagePortion(event, true); } if(wheel.deltaY < -1) { // 進行局部縮小 this.amplifyImagePortion(event, true, 'minify'); } // 重置框選數(shù)據 this.resetCheckBoxVariables(); }) ); } }
我們監(jiān)聽外部容器選中,滾輪滾動,當正向滾動的時候,我們對圖片進行局部放大,當反向滾動的時候,我們對圖片進行局部縮小。我們這里還引入了 rxjs
中的節(jié)流方法 throttleTime
來優(yōu)化滾輪觸發(fā)事件的時機。
對應的 amplifyImagePortion
方法我們更改如下
// 放大圖像區(qū)域 public amplifyImagePortion(event, isWheel, direction?: string) { // isWheel 是否是鼠標滾動 let imageContainerCenterLeft : number; let imageContainerCenterTop : number; let _imageContainer: any = document.getElementById('imageContainer'); if(this.imageIsFullscreen) { // 全屏模式下 imageContainerCenterLeft = _imageContainer.getBoundingClientRect().width / 2; imageContainerCenterTop =_imageContainer.getBoundingClientRect().height / 2; } else { // 非全屏的模式下 if(isWheel) { imageContainerCenterLeft = _imageContainer.getBoundingClientRect().left + _imageContainer.getBoundingClientRect().width / 2; imageContainerCenterTop = _imageContainer.getBoundingClientRect().top + _imageContainer.getBoundingClientRect().height / 2; } } let clickPointLeft: number = 0; let clickPointTop: number = 0; if(isWheel) { clickPointLeft = event.pageX; clickPointTop = event.pageY; } else { clickPointLeft = this.checkboxPositionLeft + this.checkboxWidth / 2; clickPointTop = this.checkboxPositionTop + this.checkboxHeight / 2 } // 計算兩點之間的距離 let diffX: number = imageContainerCenterLeft - clickPointLeft; let diffY: number = imageContainerCenterTop - clickPointTop; if(!isWheel) { this.imageTranslateX = (this.imageTranslateX * this.imageAmplifyMultiple + diffX) / this.imageAmplifyMultiple; this.imageTranslateY = (this.imageTranslateY * this.imageAmplifyMultiple + diffY) / this.imageAmplifyMultiple; } // 縮小的倍數(shù) if(direction == 'minify') { this.imageAmplifyMultiple = this.imageAmplifyMultiple * (1 / this.multipleStep); } else { // 放大的倍數(shù) - 默認 this.imageAmplifyMultiple = this.imageAmplifyMultiple * this.multipleStep; } }
multipleStep
是放大的倍數(shù),1 / multipleStep
是縮小的倍數(shù)。因為寬度變,我們需要對translate
的x
軸和y
軸的偏移進行合理計算,見上面兩份代碼。
擴展
當然,我們還可以圖片縮放的功能進行擴展,比如,對圖片進行區(qū)域的框選進行縮放;比如,另起一個 canvas
對圖片進行繪制縮放等。
以上就是JavaScript實現(xiàn)圖片縮放功能的詳細內容,更多關于JavaScript圖片縮放的資料請關注腳本之家其它相關文章!
相關文章
JavaScript函數(shù)節(jié)流概念與用法實例詳解
這篇文章主要介紹了JavaScript函數(shù)節(jié)流概念與用法,結合實例形式詳細分析了JavaScript函數(shù)節(jié)流的概念、功能,并分析了函數(shù)節(jié)流的用法與使用技巧,需要的朋友可以參考下2016-06-06如何使用moment.js獲取本周、前n周、后n周開始結束日期及動態(tài)計算周數(shù)
使用了momentjs之后發(fā)現(xiàn)這個日期處理控件實在是太強大了,下面這篇文章主要給大家介紹了關于如何使用moment.js獲取本周、前n周、后n周開始結束日期及動態(tài)計算周數(shù)的相關資料,需要的朋友可以參考下2022-09-09手機開發(fā)必備技巧:javascript及CSS功能代碼分享
這篇文章主要介紹了手機開發(fā)必備技巧:javascript及CSS功能代碼分享,本文講解了viewport(可視區(qū)域)操作、鏈接操作、javascript事件等內容,需要的朋友可以參考下2015-05-05