看看圖片馬賽克風(fēng)格化效果用CSS怎么實(shí)現(xiàn)_第1頁(yè)
看看圖片馬賽克風(fēng)格化效果用CSS怎么實(shí)現(xiàn)_第2頁(yè)
看看圖片馬賽克風(fēng)格化效果用CSS怎么實(shí)現(xiàn)_第3頁(yè)
看看圖片馬賽克風(fēng)格化效果用CSS怎么實(shí)現(xiàn)_第4頁(yè)
看看圖片馬賽克風(fēng)格化效果用CSS怎么實(shí)現(xiàn)_第5頁(yè)
已閱讀5頁(yè),還剩6頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論