




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第看看圖片馬賽克風(fēng)格化效果用CSS怎么實(shí)現(xiàn)?一、image-rendering介紹
CSS中有一個(gè)有趣的特性叫image-rendering,它可以通過(guò)算法來(lái)更好地顯示被縮放的圖片。
假設(shè)我們有一張尺寸較小的二維碼截圖(下方左,僅為示意圖不可掃),將其放大10倍后圖像會(huì)被虛化(下方右):
這時(shí)給放大的圖片加上image-rendering:pixelated的特性,CSS會(huì)通過(guò)算法將其像素化展示,使其圖像輪廓具有更銳利的邊緣:
該特性非常適合應(yīng)用在色彩單一、輪廓分明、需要被放大的圖片上,可以營(yíng)造出一種偽矢量的既視感(減少放大后的失真)。
對(duì)于色彩豐富、細(xì)節(jié)較多的照片,image-rendering:pixelated使用后會(huì)營(yíng)造出一種馬賽克的外觀:
這離本文標(biāo)題所希望實(shí)現(xiàn)的馬賽克效果還有段距離目前圖片需要被放大后才能顯示出效果,而我們希望能在保有原圖尺寸的基礎(chǔ)上,給圖片覆蓋等尺寸馬賽克。
然而image-rendering特性對(duì)尺寸未發(fā)生縮放的元素是不會(huì)生效的:
MDN-Thispropertyhasnoeffectonnon-scaledimages.
二、踩坑等尺寸馬賽克的實(shí)現(xiàn)
等尺寸馬賽克的原理相當(dāng)于先把一張照片模糊化,然后再經(jīng)過(guò)銳化算法處理得到各種小方格。
image-rendering:pixelated幫我們實(shí)現(xiàn)了銳化的步驟,我們得想想怎么實(shí)現(xiàn)模糊。
首先使用濾鏡的模糊方案是行不通的,因?yàn)閕mage-rendering和圖像縮放系數(shù)強(qiáng)相關(guān),所以應(yīng)當(dāng)思考可以怎樣利用圖片的縮放能力。
這里得說(shuō)一句,WEB上的圖片像極了Photoshop里的智能對(duì)象你可以任意修改它的尺寸(例如放大很多倍讓其變模糊),但最后再把圖片改回原本的大小時(shí),圖片會(huì)變回原來(lái)的樣子(沒(méi)有任何失真)。
如何保留圖片放大后的模糊信息,是優(yōu)先需要解決的問(wèn)題。
聰明的小伙伴已經(jīng)想到了可以嘗試使用canvas來(lái)處理,畢竟canvas可以輕松獲取、繪制圖像,且繪制出來(lái)的圖像信息是純數(shù)據(jù)的,而非圖形對(duì)象(Image),故經(jīng)其放大繪制的圖片數(shù)據(jù)再進(jìn)行縮小繪制(到原尺寸)會(huì)失真(這正好是我們所希望發(fā)生的)。
但這里也存在一些坑:
外部圖像通過(guò)image-rendering:pixelated算法處理后顯示的信息,canvas是無(wú)法拿到的,因?yàn)槟鞘秋@示層的東西。canvas拿到的依舊是未經(jīng)銳化的、模糊的原生圖像內(nèi)容;
canvas本身如果沒(méi)有縮放的話,給canvas添加image-rendering:pixelated沒(méi)有任何意義。
這意味著你無(wú)法把圖片在canvas外面放大銳化,然后再寫入canvas去縮小繪制(并不斷迭代處理)來(lái)得到銳化后的原尺寸圖片。
三、有趣的canvas拉伸
在解決上述問(wèn)題時(shí),我們先來(lái)看看canvas一個(gè)有趣的特性。
如果我們?cè)赾anvas標(biāo)簽里定義了寬高:
canvaswidth=100height=50/canvas
同時(shí)又給canvas在樣式中定義了另一個(gè)寬高:
canvas{
width:200px;
height:200px;
}
那么canvas會(huì)以哪個(gè)尺寸來(lái)顯示呢?
答案是以CSS的尺寸來(lái)顯示,但畫布的內(nèi)容尺寸會(huì)以畫布標(biāo)簽內(nèi)定義的寬高為準(zhǔn)。這意味著雖然我們看到的是200px*200px的畫布,但它的內(nèi)容實(shí)際被拉伸了(寬被拉伸了2倍,高被拉伸了4倍)。
注:左邊為畫布,右邊為原圖
這也是canvas作為可替換元素的一個(gè)特性CSS無(wú)法修改其內(nèi)容。試想一下,如果CSS可以動(dòng)態(tài)地修改canvas內(nèi)容的尺寸,意味著canvas的內(nèi)容會(huì)被裁剪掉一部分,或者多出來(lái)一部分空白區(qū)域,這顯然是不可取的。所以canvas在保留內(nèi)容完整的前提下,整體伸縮到樣式規(guī)定尺寸,是合理的瀏覽器行為。
利用canvas的這個(gè)特性,我們可以這樣來(lái)實(shí)現(xiàn)等尺寸馬賽克:
創(chuàng)建一個(gè)畫布,通過(guò)樣式規(guī)定好其寬高,并設(shè)置image-rendering:pixelated特性;
計(jì)算圖片最佳展示尺寸(以類似background-size:contAIn的形式展示);
將畫布的寬高(非樣式)設(shè)置為樣式寬高的1/N;
繪制圖像,繪制的圖像寬高為最佳展示尺寸的1/N。
如此一來(lái),我們實(shí)際繪制了一個(gè)尺寸僅為最佳尺寸1/N的圖像,再通過(guò)canvas的N倍放大又變回了視覺(jué)上的最佳尺寸。圖像因?yàn)樽叩腸anvas繪制,所以放大回最佳尺寸后會(huì)保持模糊,從而滿足了image-rendering的匹配需求。
注:這里提到的最佳尺寸,指的是步驟2里確保完整展示圖像所對(duì)應(yīng)的最佳尺寸,而非圖片原生尺寸。
四、代碼實(shí)現(xiàn)
我們按照上方步驟來(lái)書寫對(duì)應(yīng)代碼,當(dāng)然我們希望靈活一些,例如上述的N可以由用戶自定義。另外本章的代碼可以在Github上獲取。
4.1HTML部分
主要為選擇圖片的input控件、畫布、方便畫布獲取圖像的img、供用戶自定義縮放倍數(shù)的文本框、執(zhí)行按鈕:
inputid=filetype=fileaccept=image/*/
canvasid=canvas/canvas
imgid=img-raw/
labelfor=compress-times壓縮倍數(shù):/label
inputid=compress-timestype=numbervalue=12
button馬賽克化/button
4.2CSS部分
我們需要通過(guò)樣式規(guī)定好畫布的外觀尺寸,并配置image-rendering:pixelated特性。另外img標(biāo)簽只是一個(gè)傳遞用戶所選圖片到畫布的中介,可以直接隱藏:
canvas{
display:block;
border:graysolid1px;
width:600px;
height:600px;
image-rendering:pixelated;
img{
display:none;
}
4.3JS部分
letimgBlobUrl;
constfile=document.getElementById(file
constimg=document.getElementById(img-raw
constcompressTimes=document.getElementById(compress-times
constdefaultCompressTimes=compressTimes.value|0;
constcanvas=document.getElementById(canvas
constbutton=document.querySelector(button
constboundingRect=canvas.getBoundingClientRect();
constctx=canvas.getContext(2d
constcanvas_w=boundingRect.width;
constcanvas_h=boundingRect.height;
//以background-size:contain形式設(shè)置圖片尺寸
functionmatchImgSizeToCanvas(imgElem=img){
letw=imgElem.width;
leth=imgElem.height;
if(wcanvas_w||hcanvas_h){
letradio=Math.max(h/canvas_h,w/canvas_w);
radio=Number(radio.toFixed(2));
imgElem.width=parseInt(w/radio);
imgElem.height=parseInt(h/radio);
//繪制1/N大小的圖像,畫布寬高屬性設(shè)為樣式寬高的1/N,從而實(shí)現(xiàn)畫布內(nèi)容的N倍放大
functionrun(){
letct=parseInt(compressTimes.value)||defaultCompressTimes;
canvas.width=parseInt(canvas_w/ct);
canvas.height=parseInt(canvas_h/ct);
ctx.drawImage(img,0,0,parseInt(img.width/ct),parseInt(img.height/ct));
functioncleanCanvas(){
ctx.clearRect(0,0,canvas_w,canvas_h);
functionreset(){
img.removeAttribute(width
img.removeAttribute(height
cleanCanvas();
matchImgSizeToCanvas(img);
run();
file.addEventListener(change,function(e){
window.URL.revokeObjectURL(imgBlobUrl);
constpicFile=this.files[0];
imgBlobUrl=window.URL.createObjectURL(picFile);
img.onload=functioninit(){
reset();
img.src=imgBlobUrl;
},false);
button.addEventListener(click,reset,false);
執(zhí)行效果:
選中文件/點(diǎn)擊按鈕后,能按壓縮倍數(shù)得到對(duì)應(yīng)的像素風(fēng)格藝術(shù)照。
五、Mosaic插件封裝
通過(guò)上方示例我們學(xué)習(xí)了如何利用canvas特性來(lái)設(shè)計(jì)等尺寸的馬賽克效果,現(xiàn)在我們嘗試把該功能封裝為一個(gè)簡(jiǎn)易插件,可以讓頁(yè)面上的圖片列表一鍵Mosaicing。
插件的實(shí)現(xiàn)方案也很簡(jiǎn)單用戶點(diǎn)擊按鈕時(shí),往圖片容器上插入一個(gè)和容器等尺寸的畫布(尺寸通過(guò)樣式設(shè)置),再繪制覆蓋畫布的圖像,并縮小畫布的寬高屬性來(lái)放大畫布內(nèi)容:
5.1插件腳本
/**@filemosaic.js**/
classMosaic{
constructor(url,container,options={}){
if(typeofcontainer===string){
container=document.querySelector(container);
if(!url||!container.style){
console.error(參數(shù)不正確
this.url=url;
this.options=options;
this.container=container;
this.init();
init(){
constimg=newImage();
constcanvas=document.createElement(canvas
canvas.style.position=absolute
canvas.style.zIndex=999;
canvas.style.imageRendering=pixelated
this.img=img;
this.canvas=canvas;
this.ctx=canvas.getContext(2d
constcontainerBoundingRect=this.container.getBoundingClientRect();
constcontainer_w=containerBoundingRect.width;
constcontainer_h=containerBoundingRect.height;
//通過(guò)樣式初始化畫布尺寸為容器尺寸
canvas.style.width=container_w+px
canvas.style.height=container_h+px
img.onload=()={
this.run(container_w,container_h);
img.src=this.url;
run(w,h){
//縮小倍數(shù),可以由參數(shù)傳入,默認(rèn)為12
constcompressTimes=parseInt(pressTimes)||12;
letcompress_w=parseInt(w/compressTimes);
letcompress_h=parseInt(h/compressTimes);
//修改畫布尺寸屬性為1/縮小倍數(shù)
this.canvas.width=compress_w;
this.canvas.height=compress_h;
//繪制圖片覆蓋縮小后的畫布
this.ctx.drawImage(this.img,0,0,compress_w,compress_h);
this.container.prepend(this.c
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年工業(yè)互聯(lián)網(wǎng)平臺(tái)光通信技術(shù)升級(jí):產(chǎn)業(yè)鏈布局與競(jìng)爭(zhēng)格局報(bào)告
- 中式快餐連鎖品牌2025年擴(kuò)張戰(zhàn)略與標(biāo)準(zhǔn)化運(yùn)營(yíng)模式創(chuàng)新與實(shí)踐報(bào)告
- 小兒化膿性腦膜炎護(hù)理疑難病例
- 做賬實(shí)操-網(wǎng)咖公司全盤賬務(wù)處理會(huì)計(jì)分錄案例
- 腦卒中吞咽障礙的護(hù)理
- 精神科常見(jiàn)護(hù)理診斷及措施
- 永輝消防課件
- 部門培訓(xùn)規(guī)劃安排
- 氣胸病人護(hù)理課件
- 氣相沉積技術(shù)課件
- 林權(quán)林地轉(zhuǎn)租協(xié)議書
- 2025年自來(lái)水筆試題及答案
- 廣東省深圳市福田區(qū)耀華實(shí)驗(yàn)學(xué)校2025年六年級(jí)下學(xué)期5月模擬預(yù)測(cè)數(shù)學(xué)試題含解析
- 2025年安徽中醫(yī)藥高等??茖W(xué)校單招職業(yè)適應(yīng)性測(cè)試題庫(kù)有答案
- 2025年山東省威海市市屬事業(yè)單位招聘(綜合類)考試筆試高頻重點(diǎn)模擬試卷提升(共500題附帶答案詳解)
- 成績(jī)單申請(qǐng)書
- 高校人事檔案數(shù)字化建設(shè)實(shí)踐調(diào)研
- 2025年高中歷史會(huì)考會(huì)考全套知識(shí)復(fù)習(xí)
- 特殊作業(yè)安全管理監(jiān)護(hù)人專項(xiàng)培訓(xùn)課件
- 科幻中的物理學(xué)學(xué)習(xí)通超星期末考試答案章節(jié)答案2024年
- 全過(guò)程造價(jià)咨詢項(xiàng)目保密及廉政執(zhí)業(yè)措施
評(píng)論
0/150
提交評(píng)論