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

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

第看看圖片馬賽克風格化效果用CSS怎么實現(xiàn)?一、image-rendering介紹

CSS中有一個有趣的特性叫image-rendering,它可以通過算法來更好地顯示被縮放的圖片。

假設我們有一張尺寸較小的二維碼截圖(下方左,僅為示意圖不可掃),將其放大10倍后圖像會被虛化(下方右):

這時給放大的圖片加上image-rendering:pixelated的特性,CSS會通過算法將其像素化展示,使其圖像輪廓具有更銳利的邊緣:

該特性非常適合應用在色彩單一、輪廓分明、需要被放大的圖片上,可以營造出一種偽矢量的既視感(減少放大后的失真)。

對于色彩豐富、細節(jié)較多的照片,image-rendering:pixelated使用后會營造出一種馬賽克的外觀:

這離本文標題所希望實現(xiàn)的馬賽克效果還有段距離目前圖片需要被放大后才能顯示出效果,而我們希望能在保有原圖尺寸的基礎上,給圖片覆蓋等尺寸馬賽克。

然而image-rendering特性對尺寸未發(fā)生縮放的元素是不會生效的:

MDN-Thispropertyhasnoeffectonnon-scaledimages.

二、踩坑等尺寸馬賽克的實現(xiàn)

等尺寸馬賽克的原理相當于先把一張照片模糊化,然后再經(jīng)過銳化算法處理得到各種小方格。

image-rendering:pixelated幫我們實現(xiàn)了銳化的步驟,我們得想想怎么實現(xiàn)模糊。

首先使用濾鏡的模糊方案是行不通的,因為image-rendering和圖像縮放系數(shù)強相關,所以應當思考可以怎樣利用圖片的縮放能力。

這里得說一句,WEB上的圖片像極了Photoshop里的智能對象你可以任意修改它的尺寸(例如放大很多倍讓其變模糊),但最后再把圖片改回原本的大小時,圖片會變回原來的樣子(沒有任何失真)。

如何保留圖片放大后的模糊信息,是優(yōu)先需要解決的問題。

聰明的小伙伴已經(jīng)想到了可以嘗試使用canvas來處理,畢竟canvas可以輕松獲取、繪制圖像,且繪制出來的圖像信息是純數(shù)據(jù)的,而非圖形對象(Image),故經(jīng)其放大繪制的圖片數(shù)據(jù)再進行縮小繪制(到原尺寸)會失真(這正好是我們所希望發(fā)生的)。

但這里也存在一些坑:

外部圖像通過image-rendering:pixelated算法處理后顯示的信息,canvas是無法拿到的,因為那是顯示層的東西。canvas拿到的依舊是未經(jīng)銳化的、模糊的原生圖像內(nèi)容;

canvas本身如果沒有縮放的話,給canvas添加image-rendering:pixelated沒有任何意義。

這意味著你無法把圖片在canvas外面放大銳化,然后再寫入canvas去縮小繪制(并不斷迭代處理)來得到銳化后的原尺寸圖片。

三、有趣的canvas拉伸

在解決上述問題時,我們先來看看canvas一個有趣的特性。

如果我們在canvas標簽里定義了寬高:

canvaswidth=100height=50/canvas

同時又給canvas在樣式中定義了另一個寬高:

canvas{

width:200px;

height:200px;

}

那么canvas會以哪個尺寸來顯示呢?

答案是以CSS的尺寸來顯示,但畫布的內(nèi)容尺寸會以畫布標簽內(nèi)定義的寬高為準。這意味著雖然我們看到的是200px*200px的畫布,但它的內(nèi)容實際被拉伸了(寬被拉伸了2倍,高被拉伸了4倍)。

注:左邊為畫布,右邊為原圖

這也是canvas作為可替換元素的一個特性CSS無法修改其內(nèi)容。試想一下,如果CSS可以動態(tài)地修改canvas內(nèi)容的尺寸,意味著canvas的內(nèi)容會被裁剪掉一部分,或者多出來一部分空白區(qū)域,這顯然是不可取的。所以canvas在保留內(nèi)容完整的前提下,整體伸縮到樣式規(guī)定尺寸,是合理的瀏覽器行為。

利用canvas的這個特性,我們可以這樣來實現(xiàn)等尺寸馬賽克:

創(chuàng)建一個畫布,通過樣式規(guī)定好其寬高,并設置image-rendering:pixelated特性;

計算圖片最佳展示尺寸(以類似background-size:contAIn的形式展示);

將畫布的寬高(非樣式)設置為樣式寬高的1/N;

繪制圖像,繪制的圖像寬高為最佳展示尺寸的1/N。

如此一來,我們實際繪制了一個尺寸僅為最佳尺寸1/N的圖像,再通過canvas的N倍放大又變回了視覺上的最佳尺寸。圖像因為走的canvas繪制,所以放大回最佳尺寸后會保持模糊,從而滿足了image-rendering的匹配需求。

注:這里提到的最佳尺寸,指的是步驟2里確保完整展示圖像所對應的最佳尺寸,而非圖片原生尺寸。

四、代碼實現(xiàn)

我們按照上方步驟來書寫對應代碼,當然我們希望靈活一些,例如上述的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ī)定好畫布的外觀尺寸,并配置image-rendering:pixelated特性。另外img標簽只是一個傳遞用戶所選圖片到畫布的中介,可以直接隱藏:

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形式設置圖片尺寸

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大小的圖像,畫布寬高屬性設為樣式寬高的1/N,從而實現(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í)行效果:

選中文件/點擊按鈕后,能按壓縮倍數(shù)得到對應的像素風格藝術照。

五、Mosaic插件封裝

通過上方示例我們學習了如何利用canvas特性來設計等尺寸的馬賽克效果,現(xiàn)在我們嘗試把該功能封裝為一個簡易插件,可以讓頁面上的圖片列表一鍵Mosaicing。

插件的實現(xiàn)方案也很簡單用戶點擊按鈕時,往圖片容器上插入一個和容器等尺寸的畫布(尺寸通過樣式設置),再繪制覆蓋畫布的圖像,并縮小畫布的寬高屬性來放大畫布內(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;

//通過樣式初始化畫布尺寸為容器尺寸

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ù)傳入,默認為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. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論