標題看起來很繞口而且也有些詞不達意,所以就簡單的用幾張圖以及說明文字來讓大家了解,
一般做網站都會有要製作圖文上稿的功能,有時候一篇文章還需要指定一張封面圖的需求,
但有時候某些版面的編排製作上,圖片只能夠顯示正方形的圖,如果使用者在後台上了一張長方形的圖,
而前台只能顯示正方形,所以就會變成……
在後台裡,我們是可以在使用者上傳圖片後對圖檔做檢查,只要不是符合正方形的圖片就擋回去,
但有時候我們工程師這樣的作法卻反而會引起很多使用者的反彈,因為不能較使用者都要會圖片裁剪的能力以及工具,
所以跟使用者拉鋸的情況下,使用者多半都會接納圖片變形的結果,而讓網頁看起來就是充滿變形的圖片。
其實這種情況也是有多種解決的方法,
例如說可以用之前介紹的圖片裁剪功能,讓使用者上傳圖片後,再去裁剪要顯示的範圍,不過就要多花功夫去做這部份的功能,
或者是說,使用者上傳圖片之後,讓程式自動去裁剪要顯示的範圍並另存成新圖檔,這也是個不錯的方式,這以後會講到。
不過比較簡單的方式還是透過前端 Javascript 程式的操作,讓前端的圖片自動顯示一個正方形範圍而且還有縮圖的效果,
接下來我們就來練習做這個功能。
其實做這個功能並不是很困難,只要對 CSS 以及 jQuery 有一點點的基礎(例如…我)就可以做出這個功能,
這個功能的關鍵就在於「遮罩」…… 簡單講就是用一個 div 放在 img 的外面,然後設定好 div 的寬與高,然後再對 img 做縮圖處理,就是直接修改 img 的 width 與 height 值,圖片要顯示的範圍會因為圖片是直的還是橫的而有所不同,最後再去算出圖片要顯示的範圍,完成。
這個想法其實是用 imgAreaSelect 所裁剪功能時想到的,
http://odyniec.net/projects/imgareaselect/
看網頁原始碼就知道縮圖區塊的作法
所以我們就可以依照這樣的方式來做這個功能了。
CSS
一開始先設定好要使用的樣式內容,
<style type='text/css'>.container { position: relative; overflow: hidden; }.container img { position: absolute; }</style>
HTML
分別擺上三種不同的圖片,第一張是橫的,第二張是直的,第三張是正方形的,
這三張圖片的 class 都使用 crop,用來作為標示,方便接下來 Javascript 程式中的操作,
<img class="crop" src="http://dl.dropbox.com/u/26764200/Photos/1680x1050_Widescreen_Wallpaper_Summer_1920.jpg"/><br/><img class="crop" src="http://dl.dropbox.com/u/26764200/Photos/eiffel-tower-picture.jpg"><br/><img class="crop" src="http://dl.dropbox.com/u/26764200/Photos/main_picture_large.jpg"><br/>
Javascript
jQuery 使用的是最新版的 1.7.2
第一個方法式先找出 class 為「crop」的 img element,然後在 img element 外面包上一個 div 並且指定其 class 為「container」,
接下來再去設定剛剛動態增加的 div 的寬與高,這是用來顯示圖片的外框,
最後再逐一的對有包裹 div 的 img element 進行下一步驟的操作,
function CropImageToSquare(squareSize)
{$('img.crop').each(function(i, item)
{$(item).wrap('<div class="container" />');});$('div.container').each(function(i, item)
{$(item).css({'height': squareSize + 'px', 'width': squareSize+ 'px' });});$('.container img').each(function(i, item)
{executeToSquare(item, 200);});}
在第二個步驟中,這個 function 就是要逐一處理每張圖片的顯示大小雨顯示區域範圍,
先取得原本圖片的寬與高,然後依據圖片是橫、是直、還是正方形的,判斷後取得顯示範圍的左上位置點的方位值,
最後就是修改圖片的顯示寬與高以及顯示的區域,這樣就完成了。
function executeToSquare(imageItem, squareSize)
{var width = $(imageItem).width();
var height = $(imageItem).height();
var tmp_width = 0;
var tmp_height = 0;
var position_top = 0;
var position_left = 0;
if(width == height)
{tmp_width = squareSize;tmp_height = squareSize;position_top = parseInt(0 - ((tmp_height - squareSize )/2), 10);
position_left = parseInt(0 - ((tmp_width - squareSize )/2), 10);
}else if(width > height){tmp_width = parseInt(((width / height) * squareSize ), 10);
tmp_height = squareSize;position_top = parseInt(((tmp_height - squareSize )/2), 10);
position_left = parseInt(0- ((tmp_width - squareSize )/2), 10);
}else if(height > width){tmp_width = squareSize;tmp_height = parseInt(((height / width) * squareSize), 10);
position_top = parseInt(0 - ((tmp_height - squareSize )/2), 10);
position_left = parseInt(((tmp_width - squareSize )/2), 10);
}$(imageItem).attr('width', tmp_width ).attr('height', tmp_height ).css({ left: position_left, top: position_top });
}
看看 JSFIDDLE 吧
在 IE 7+, Firefox, Opera 上面都可以正常執行,
在縮圖後並且顯示圖片的中間位置,橫的、直的圖片都是顯示中間的區塊,而原本就是正方形的圖片就只是做縮放的處理,
但是 webkit 的 Chrome 與 Safari 就不聽指揮了…
這是因為圖片還沒有載入完全就開始進行縮圖與顯示位置的處理,一開始無法取得圖片正確的寬與高,
所以在 Chrome 與 Safari 就會變成是整張圖縮成正方形的變形狀況,這就不是我們要的結果,所以要來修改一下 Javascript 的部份。
修改
因為圖片還在載入而無法抓到圖片正確的寬度與高度,所以我們就要確保圖片載入完畢後才去執行我們的程式,
有關圖片預先載入的 jQuery Plugin 有很多種,而我所採用的是「jQuery Image Preload Plugin: Smart Preloader」
http://www.egrappler.com/jquery-image-preload-plugin-smart-preloader/
會用它的原因是,我可以在載入每一張圖片時做處理,另外在全部圖片都載入完成後也可以做其他的處理,
而我要的就是確保在全部都載入完成後再去執行我們的程式,所以就是用這個套件啦。
修改過的 HTML 內容:
圖片多加上 id 屬性,另外圖片的來源位置都不放值。
<img class="crop" id="CropImage1" src=""/><br/><img class="crop" id="CropImage2" src=""><br/><img class="crop" id="CropImage3" src=""><br/><script type='text/javascript' src='http://dl.dropbox.com/u/26764200/javascript/smartpreload.js'></script>
一開始的 Javascript 程式就修改為以下的內容:
先準備好要載入的圖片,載入每一張圖片時依照一開始的陣列內容的順序逐一放入正確的 img element 中,
當全部圖片載入完成後就是執行我們原本的 function。
$(document).ready(function(){var cropImageSources =
['http://dl.dropbox.com/u/26764200/Photos/1680x1050_Widescreen_Wallpaper_Summer_1920.jpg',
'http://dl.dropbox.com/u/26764200/Photos/eiffel-tower-picture.jpg',
'http://dl.dropbox.com/u/26764200/Photos/main_picture_large.jpg'
];$(document).smartpreload(
{images: cropImageSources,oneachimageload: function(src)
{$.each(cropImageSources, function(index, value)
{if(value == src) $('#CropImage' + (index+1)).attr('src', src);
});},onloadall: function()
{CropImageToSquare(200);}});});
修改後的程式在 Chrome / Safari 的顯示:
Chrome
Safari
兩個瀏覽器都可以正確的執行並顯示正確的結果。
看看 JSFIDDLE 吧
當然不是這樣就結束,既然是練習,就讓我練習把這個功能給做成一個 jQuery Plugin 吧,這樣以後也可以方便重複使用,
這個 plugin 的功能提供兩種形式:
- 可以一次處理網頁上所有指定的圖片
- 可以單一處理網頁上指定的圖片
這一個 plugin 並沒有做得很彈性,唯一可以彈性處理的就是可以指定 Square 的 size,
而處理的圖片,img element 的 class 必須要設定使用「crop」,其他應該就沒有什麼要特別注意的,
先看看 jQuery plug – CropImageToSquare 的程式內容:
程式寫得很簡陋,請多見諒,有錯的請告訴我,謝謝。
/*!
* CropImageToSquare - jQuery Plugin
* version: 0.0.1 (2012/05/09)
*
* License: kevintsengtw.blogspot.com
*
* Copyright 2012 Kevin Tseng (tw)
*
*/
(function($)
{
if (typeof (jQuery) === 'undefined') { alert('jQuery Library NotFound.'); return; }
var CropImageToSquare = window.CropImageToSquare = {};
jQuery.extend(CropImageToSquare,{
cropAll: function(options)
{
$('img.crop').each(function(i, item)
{
$(item).wrap('<div class="container" />');
});
$('div.container').each(function(i, item)
{
$(item).css({'height': options.squareSize + 'px', 'width': options.squareSize + 'px' });
});
$('.container img').each(function(i, item)
{
CropImageToSquare.executeToSquare(item, options.squareSize);
});
},
executeToSquare: function (imageItem, squareSize)
{
var width = $(imageItem).width();
var height = $(imageItem).height();
var tmp_width = 0;
var tmp_height = 0;
var position_top = 0;
var position_left = 0;
if(width == height)
{
tmp_width = squareSize;
tmp_height = squareSize;
position_top = parseInt(0 - ((tmp_height - squareSize )/2), 10);
position_left = parseInt(0 - ((tmp_width - squareSize )/2), 10);
}
else if(width > height)
{
tmp_width = parseInt(((width / height) * squareSize ), 10);
tmp_height = squareSize;
position_top = parseInt(((tmp_height - squareSize )/2), 10);
position_left = parseInt(0- ((tmp_width - squareSize )/2), 10);
}
else if(height > width)
{
tmp_width = squareSize;
tmp_height = parseInt(((height / width) * squareSize), 10);
position_top = parseInt(0 - ((tmp_height - squareSize )/2), 10);
position_left = parseInt(((tmp_width - squareSize )/2), 10);
}
$(imageItem)
.attr('width', tmp_width ).attr('height', tmp_height )
.css({ left: position_left, top: position_top })
.show();
}
});
$.fn.cropImageToSquare = function(options)
{
$(this).wrap('<div class="container" />');
$(this).parent().css({'height': options.squareSize + 'px', 'width': options.squareSize + 'px' });
CropImageToSquare.executeToSquare(this, options.squareSize);
};
})(jQuery);
第一種的使用情境:全部處理網頁上指定的圖片
HTML
<h1>jQuery Plugin - Crop Image To Square - Index 1</h1>
<hr/>
Square Size: <input type="text" id="TextSquareSize" value="200">px
<input type="button" id="ButtonExecute" value="Crop Image to Square" />
<br><br>
<img class="crop" id="CropImage1" src=""/>
<a class="fancybox default" href="images/1680x1050_Widescreen_Wallpaper_Summer_1920.jpg" target="_blank">Picture1 - Original</a>
<br/><br/>
<img class="crop" id="CropImage2" src="">
<a class="fancybox default" href="images/eiffel-tower-picture.jpg" target="_blank">Picture2 - Original</a>
<br/><br/>
<img class="crop" id="CropImage3" src="">
<a class="fancybox default" href="images/main_picture_large.jpg" target="_blank">Picture3 - Original</a>
<br/><br/>
Javascript
<script type='text/javascript' src='js/jquery-1.7.2.min.js'></script>
<script type="text/javascript" src="js/fancybox/jquery.fancybox.pack.js?v=2.0.5" ></script>
<script type='text/javascript' src='js/CropImageToSquare.js'></script>
<script type='text/javascript' src='js/smartpreload.js'></script>
<script type='text/javascript'>//<![CDATA[
var counter = 0;
$(document).ready(function()
{
$(".default").fancybox({
autoSize: true,
openEffect: 'elastic',
closeEffect: 'elastic'
});
var cropImageSources =
[
'images/1680x1050_Widescreen_Wallpaper_Summer_1920.jpg',
'images/eiffel-tower-picture.jpg',
'images/main_picture_large.jpg'
];
$(document).smartpreload(
{
images: cropImageSources,
oneachimageload: function(src)
{
$.each(cropImageSources, function(index, value)
{
if(value == src) $('#CropImage' + (index+1)).attr('src', src);
});
},
onloadall: function()
{
var sizeValue = $.isNumeric($.trim($('#TextSquareSize').val())) ? parseInt($.trim($('#TextSquareSize').val()), 10) : 200;
CropImageToSquare.cropAll({ squareSize : sizeValue });
}
});
$('#ButtonExecute').click(function()
{
var sizeValue = $.isNumeric($.trim($('#TextSquareSize').val())) ? parseInt($.trim($('#TextSquareSize').val()), 10) : 200;
CropImageToSquare.cropAll({ squareSize : sizeValue });
});
});
//]]>
</script>
執行結果
第二種的使用情境:單一處理網頁上指定的圖片
HTML 與前面的一樣,有稍為變化的就是 Javascript 的部分,
<script type='text/javascript'>//<![CDATA[
var counter = 0;
$(document).ready(function()
{
$(".default").fancybox({
autoSize: true,
openEffect: 'elastic',
closeEffect: 'elastic'
});
var cropImageSources =
[
'images/1680x1050_Widescreen_Wallpaper_Summer_1920.jpg',
'images/eiffel-tower-picture.jpg',
'images/main_picture_large.jpg'
];
$(document).smartpreload(
{
images: cropImageSources,
oneachimageload: function(src)
{
$.each(cropImageSources, function(index, value)
{
if(value == src) $('#CropImage' + (index+1)).attr('src', src);
});
},
onloadall: function()
{
$('#CropImage1').cropImageToSquare({ squareSize: 150 });
$('#CropImage2').cropImageToSquare({ squareSize: 150 });
}
});
});
//]]>
</script>
執行結果:
第三張沒有處理是要做個突顯,與前面兩張有做處理的圖片做個比較。
最後來個無聲的操作影片示意一下:
另外就是這個 jQuery Plugin 的原始檔,下載位置如下:
http://dl.dropbox.com/u/26764200/Lab/20120509_jQuery_CropToSquare.zip
因為我只是想單純的做個練習,所以也沒有去找有無相同功能的 jQuery Plugin,
結果看到今天 (2012-05-09) jQuery4U 的文章「jQuery4U - Recently Released jQuery Plugins」,
其中就有介紹到一個功能一樣卻強大好幾倍 jQuery Plugin ……
jQuery NailThumb
http://www.garralab.com/nailthumb.php
這個 plugin 有縮圖跟顯示範圍的功能外,除了可以指定顯示正方形以外,也可以顯示橫長方形或直長方形,
縮圖的部分,可以顯示裁剪區域,也可以顯示原圖的縮圖或是原圖一比一的裁剪範圍,
縮圖還可以指定動畫,另外比較強的就是可以指定你要顯示的區域,不是只有正中間的那一塊,可以指定九宮格的其中一個區塊,
這個 plugin 功能相當不錯,有興趣的朋友可以前往了解,
因為這個套件的應用相當地多,也只有你前往它的網站並瀏覽「Example」才能夠明白這個套件好用的地方在哪邊。
這一次久違的 jQuery 的練習題就到這邊為止……
更新:
文章發佈後馬上得到 Miau Hunag 的指點,於是就把程式修改如下,不需要用到 smart prload,
看看 JSFIDDEL 的修改與執行結果:
感謝 Miau Hunag
以上
前陣子才寫過類似的功能,
回覆刪除關於webkit的部份,應該不需要請出preload吧,
把$(function(){....});
換成$(window).load(function() { ........ });
就可以了說 : ~
感謝 Miau Huang 的指教,依據你的方式修改後就可以在 WebKit 瀏覽器上正常執行了,
刪除謝謝 ^_^
hi~ 我有問題想請教
回覆刪除如果我加多幾張圖片, 單單在:
var cropImageSources =
[
'images/1680x1050_Widescreen_Wallpaper_Summer_1920.jpg',
'images/eiffel-tower-picture.jpg',
'images/main_picture_large.jpg'
];
加上圖片,
還有在:
$('#CropImage2').cropImageToSquare({ squareSize: 100 });
這裡加, 再引用 CropImage2/3/4/5.... 就可以了吧?
我把div放在table裡面了, 剛開始可以,但之後就顯示不出圖片了
請問這是為什麼呢?
你好,針對你所提供的訊息內容,我不清楚你的 table 與 div , image 的架構為何
刪除僅知道你應該是把圖片放片 table 的 cell(td) 中,然後應該在 td 中有放 div,最後再把 image 放到 div 裡面,
我以這樣的條件來做測試,測試結果是一切正常的,
你可以稍微看一下我所寫的 plugin 內容的話,其實我是在原本的 image 外面動態使用 div 來做 warp,
最後,建議你可以使用 firefox + firebug 或是 chrome 來觀察 DOM 的變化。
您好, 有沒有辦法弄成顯示長方形的按比例置中縮圖?? 我網上找了很久, 只有你這有教學~.~但是正方形不太適合...希望能幫個忙~感謝您~
回覆刪除長方形呀......
刪除我不是很確定你的需求,是將原本就是長方形的圖片作等比縮圖呢?
還是說要把任意尺寸的圖片都一律修改為長方形的致中縮圖呢?
不過我相信應該都是可以的,只要抓出原始圖片的長寬並且決定好你要縮圖的長寬比,
我想應該是可以的,我這篇文章的 javascript 程式相當簡單,應該可以做出修改。
另外我在這篇文章有介紹的[jQuery NailThumb]應該就可以滿足你的需求。
刪除嗯~我是要將任意圖片變成長方形的~
回覆刪除那個[jQuery NailThumb]我在網上也有看過...但是教學沒你這那麼詳細-_-我搞了半天都搞不成...
我是要用在購物車程式裡的~@@商品圖片很多不同大小的圖片