1. /* 로 시작하는 주석은 사라져버리기에, 대신 //로 수정하였고 (심지어 css 안에서도)
2. <img 태그를 실제 이미지로 처리하려고 하여, <img 대신 <img 를 사용했는데, 일부는 그대로 노출 되는 경우가 있습니다.
정확한 코드는 원 출처나, 강좌글 원본 (구글문서) 를 참조하세요.
차근차근/JAVA Script
http://sir.co.kr/bbs/board.php?bo_table=pb_lecture&wr_id=247&page=9
6. 반응형 이미지
반응형 웹을 제안한 Ethan Marcotte (이하 EM)가, 유동형 그리드 (fluid grids)글과 함께 2009년에 제안했던 기법으로, 화면의 폭보다 큰 이미지를 화면폭에 맞춰주도록 max-width:100%로 주는 것을 뜻합니다.
1 | img { |
2 | max-width: 100%; |
3 | } |
뿐만아니라, 대부분의 비디오 태그에도 max-width 를 적용하는 것으로 대부분의 문제는 해결됩니다.
1 | img, |
2 | embed, |
3 | object, |
4 | video { |
5 | max-width: 100%; |
6 | } |
물론 기대를 저버리지 않는 IE 구버전은 max-width를 지원하지 않습니다. 한가지 방법은, 해당 브라우져에서는 width 자체를 100%으로 만드는 방법도 있습니다.
1 | img { |
2 | width: 100%; |
3 | } |
하지만 더 큰 문제는, 큰 이미지가 축소될때 몇몇 OS/브라우져가 제대로 작업을 하지 못하는 경우입니다. (IE 6 과 Windows FF 3 이전버전)
놀랍게도, IE 구버전의 경우, AlphaImageLoader 를 사용하면 이 문제가 해결된다고 합니다. IE7에서 이 방법을 사용하지 않았을때의 이미지와 사용했을때의 이미지를 보면 차이를 알 수 있습니다. EM이 사용한 스크립트는 여기서 다운로드 할 수 있습니다.
Chris Coyier의 ‘유연한 이미지 (flexible images)’는 max-width와 더불어, height를 auto로 잡아주어서 가로 세로 비율을 ‘강제로’ 유지하는 것도 필요하다고 합니다. (출처: 링크) 또한 -ms-interpolation-mode 를 이용해서 위와 같은 문제를 해결할 수도 있다고 합니다.
1 | img { |
2 | max-width: 100%; |
3 |
4 | // just in case, to force correct aspet ratio */ |
5 | height: auto !important; |
6 | } |
7 | img { |
8 | -ms-interpolation-mode: bicubic; |
9 | } |
하지만, EM의 댓글에서 보면, 위 -ms-interpolation-mode: bicubic이 작동은 하지만, 너무 느리다고 지적하고 있습니다.
위 유동형 이미지 글에서 다뤘듯이, 비디오도 간단히 max-width:100% 로 처리한다고 했지만, 몇몇 경우에는 간단히 처리되지 않을 수 있습니다. 구체적인 문제점으로 가로/세로 비율이 맞지 않거나 비디오 오브젝트의 종류에 따라서 달리 처리해야 합니다.
Css-tricks.com의 Chris Coyier와 Paravel 이 제작한 Fitvids.js 는 유동형/반응형 비디오를 처리하기 위한 간단한 jQuery 플러그인 입니다. 사용방법은 다음과 같습니다. (출처: github/fitvids.js)
1 | <script src= "path/to/jquery.min.js" ><!--script--> |
2 | <script src= "path/to/jquery.fitvids.js" ><!--script--> |
3 | <script> |
4 | $(document).ready( function (){ |
5 | // Target your .container, .wrapper, .post, etc. |
6 | $( "#thing-with-videos" ).fitVids(); |
7 | }); |
8 | <!--script--> |
이러한 코드가 적용되면, 해당 요소 (이경우는 #thing-with-videos)를 둘러싸는 div.fluid-width-video-wrapper 가 생성되고 필요한 CSS가 적용됩니다. 현재 처리되는 비디오 소스로는, youtube, vimeo, blip.tv, viddler, kickstarter 라고 합니다.
그렇다면 유동형 이미지와 반응형 이미지의 차이점은 무엇일까요? 즉 유동형 이미지만으로 해결되지 않는 문제점은 무엇일까요? 대표적인 문제점으로, 데스크탑에서 사용하는 화일크기가 큰 이미지를, 모바일에서 단순히 이미지 가로/세로만 줄인다는 것입니다.
이 문제점을 해결하기 위한 합리적인 방법은, 데스크탑용과 모바일용 이미지를 선별적으로 제공/사용하는 것일것입니다. 반응형 이미지는, 이러한 선별적 이미지 제공/사용을 처리하기 위한 기법들을 뜻합니다. (참고로, 본 강좌에서는, ‘반응형 이미지’ 가 ‘유동형 이미지’를 포함하는 개념/기법으로 사용합니다.)
다음은 이전에 포스팅한 제 블로그 글을 발췌했습니다.
반응형 이미지의 선택적 화일 사용은 기본적으로 데스크탑용 이미지 화일과 모바일 기기용 (여러크기의) 이미지 화일들을 미리 준비해두어야 합니다. 이렇게 준비된 기기별 이미지를 전송하는 접근 방법은, 모바일용 이미지를 기본으로 보내는 방법 (모바일 퍼스트)과 기기에 따라서 선별적으로 보내는 방법으로 나눌 수 있습니다.
기본적으로 모바일용 작은 이미지는 기본적으로 로딩을 하고, 데스크탑 환경에서는 큰 이미지 화일을 별도로 ‘더’ 다운 받는 방법입니다.
출처: filamemt group - Responsive Images Experimenting with Context Aware Image Sizing
.htaccess와 별도의 js (responsiveimgs.js) 를 이용하여, 화면폭이 480px보다 클때 큰 이미지 화일을 다운받는 방법입니다. 사용방법은 다음과 같습니다.
1 | <script src= "responsiveimgs.js" ><!--script--> |
2 | <img src= "images/test.png?full=images/test-full.png" > |
이를 사용하기 위해서는 mod_rewrite가 허용된 서버에서 다음과 같은 .htaccess를 설정해야 합니다.
01 | # Responsive Images |
02 | # Mobile-First images that scale responsively and responsibly |
03 | # Copyright 2010, Scott Jehl, Filament Group, Inc |
04 | # Dual licensed under the MIT or GPL Version 2 licenses. |
05 | # //Start Responsive Images |
06 | RewriteEngine On |
07 | # direct image requests to temp |
08 | RewriteCond %{QUERY_STRING} full=(.*)&? |
09 | RewriteRule (.*)rwd-router/.*\.(jpe?g|png|gif|webp) $1 %1 [L] |
10 | # ignore trap for non-image requests, rewrite URL without trap segment |
11 | RewriteRule (.*)rwd-router/(.*)$ $1 $2 |
12 | # //End Responsive Images |
단점은, IE8 미만에서는 작동하지 않고 기본 (작은) 그림만 보여주는 것이고, 스크린 경계치를 하나 (480px 기본이고, 옵션을 주어서 다른 경계치를 사용할 수 있습니다.).
출처: Responsive Images Using CSS3
방법1과는 좀 다른 접근 방법으로, css3의 media-query와 data 필드, attr()함수를 이용하여 스크린 크기에 따라 선택적으로 큰 이미지 화일로 교체하는 방법입니다.
1 | <img src= "image.png" data-src-600px= "image-600px.png" > |
2 | @media (min-device-width:600px) { |
3 | img[data-src-600px] { |
4 | content: attr(data-src-600px, url); |
5 | } |
6 | } |
위 1번 방법과 비교하면, js가 불필요하다는 장점이 있습니다.
모바일 퍼스트와는 달리, 서버 쪽에서 대상 스크린에 선택적으로 이미지를 보내는 접근방법으로, 대상 스크린의 크기를 취득하여 저장하는 구체적인 기법이 필요합니다. User agent를 이용한 방법도 가능하겠고, 아래와 같이 쿠키를 이용한 방법도 가능할 것 같습니다.
특히 user agent를 사용하는 방법은, 다음 강인 서버측 접근방법 (RESS)에서 더 자세히 다루겠습니다.
링크: Responsive Images using Cookies
웹페이지에서는 스크린 크기를 쿠키에 저장하고
1 | document.cookie = "device_dimensions=" + screen.width + "x" + screen.height; |
서버쪽에서 그 쿠기값을 이용하여 선택적으로 이미지 화일을 보냅니다. 이렇게 저장된 쿠키값을 이용하여 적절한 이미지화일을 전송하게 됩니다. (완전한 코드는 위 링크를 참조하세요)
01 | <!--?php |
02 | $device_width = 0; |
03 | $file = $_SERVER [ 'QUERY_STRING' ]; |
04 |
05 | $dimensi ons = explode ( 'x' , $_COOKIE [ 'device_dimensions' ]); |
06 | $device_width = intval ( $dimensions [0]); |
07 |
08 | $fileext = pathinfo ( $file , PATHINFO_EXTENSION); |
09 |
10 | // Low resolution image |
11 | if ( $device_width <= 800) { |
12 | $output_file = substr_replace( $file , '-low' , - strlen ( $fileext )-1, 0); |
13 | } |
14 |
15 | // check the file exists |
16 | if (isset( $output_file ) && file_exists ( $output_file )) { |
17 | $file = $output_file ; |
18 | } |
19 |
20 | // return the file; |
21 | readfile( $file ); |
22 | ?--> |
23 |
24 | <img src= "images/?test.png" > |
와 같이 사용하면, 화면폭이 작은 경우 (이 경우 800px), test.png 대신, test-low.png 를 전송하게 됩니다.
이러한 방법의 장점은, 모바일 퍼스트와는 달리, 한 이미지만 전송한다는 점입니다. 단점으로는, 쿠키를 사용해야 한다는 점입니다.
쿠키를 이용하는 방법으로 Adaptive Image 도 있습니다.
대표적으로 Sencha.io 가 있습니다.
sencha의 서비스를 사용하게 되면, 자동으로 각 기기마다 최적으로 크기/품질이 조정된 이미지를 제공하는 서비스입니다.
비슷한 고민에서 시작된, 여러 브라우저에서 display:none 을 이용하여 선택적으로 다운로딩 할 수 있는지의 실험이 있습니다.
원글: http://timkadlec.com/2012/04/media-query-asset-downloading-results/
제 블로그: http://blog.gnuboard.org/2012/04/media-query-image-downloads/
결론적으로, background-image 의 부모 태그에 display:none 을 적용하는 경우 (실험의 test # 3), 거의 모든 (모바일) 웹 브라우져에서 해당 백그라운드 이미지를 다운로드 하지 않는다고 합니다.
01 | <div id= "test3" > |
02 | <div></div> |
03 | </div> |
04 | #test3 div { |
05 | background-image:url( 'images/test3.png' ); |
06 | width:200px; |
07 | height:75px; |
08 | } |
09 | @media all and (max-width: 600px) { |
10 | #test3 { |
11 | display:none; |
12 | } |
13 | } |
물론, 미디어쿼리로 각 기기별로 완전히 분리된 조건(실험의 test # 5)으로 다운로드 할 수도 있습니다.
01 | <div id= "test5" ></div> |
02 | @media all and (min-width: 601px) { |
03 | #test5 { |
04 | background-image:url( 'images/test5-desktop.png' ); |
05 | width:200px; |
06 | height:75px; |
07 | } |
08 | } |
09 | @media all and (max-width: 600px) { |
10 | #test5 { |
11 | background-image:url( 'images/test5-mobile.png' ); |
12 | width:200px; |
13 | height:75px; |
14 | } |
15 | } |
하지만 이렇게 되면, CSS3 미디어쿼리를 사용하지 못하는 경우, 백그라운드 이미지가 아예 사용되지 않는 문제점이 있습니다.
이와 같이 별도의 기법으로 처리하지 말고, HTML 표준 (picture과 srcset)으로 넣으려는 노력이 있습니다.
picture 요소의 사용방법 예는 다음과 같습니다.
1 | <picture> |
2 | <source media= "(min-width: 40em)" srcset= "big.jpg" > |
3 | <source srcset= "small.jpg 1x" > |
4 | <img src= "fallback.jpg" alt= "" > |
5 | </picture> |
예에서 보듯이, 미디어 쿼리가 source 속성으로 들어가서 해당 조건에 맞는 경우에 srcset으로 설정된 이미지 화일을 사용합니다. 여기서 사용된 srcset은 기존의 img 요소에도 적용될 수 있도록 제안되었습니다.
1 | <img src= "fallback.jpg" alt= "" srcset= "small.jpg 640w 1x, small-hd.jpg 640w 2x, med.jpg 1x, med-hd.jpg 2x " > |
즉, 스크린 폭이 640px보다 작을때는 small.jpg, 그렇지 않을때는 med.jpg를 소스로 사용하고, 또한 고해상도 (2x)일때는 각각 small-hd.jpg와 med-hd.jpg를 사용하도록 설정할 수 있습니다.
또한, 화일 크기 뿐만아니라 (resolution switching), 화면 폭에 따라서 이미지의 어느 부분을 사용하는 가 (art direction) 도 고려되고 있습니다. 아래 그림에서 보듯이, 스크린의 크기에 따라서 이미지의 특정 부분만을 사용하도록 설정하는 접근방법입니다.
위와 같은 표준을 현재 기술로 (비슷하게) 구현한 기법도 존재합니다.
fillament group의 Scott Jehl가 picturefill.js를 이용하여 제안하는 방법입니다.
01 | <div data-alt= "A giant stone face at The Bayon temple in Angkor Thom, Cambodia" data-picture= "" > |
02 | <div data-src= "small.jpg" ></div> |
03 | <div data-src= "medium.jpg" data-media= "(min-width: 400px)" ></div> |
04 | <div data-src= "large.jpg" data-media= "(min-width: 800px)" ></div> |
05 | <div data-src= "extralarge.jpg" data-media= "(min-width: 1000px)" ></div> |
06 | <!-- Fallback content for non-JS browsers. Same img src as the initial, unqualified source element. --> |
07 | <noscript> |
08 | <img src= "external/imgs/small.jpg" alt= "A giant stone face at The Bayon temple in Angkor Thom, Cambodia" > |
09 | </noscript> |
10 | </div> |
data-picture 로 선언된 div에 대해서는 자동으로 ‘반응형 이미지’를 처리해줍니다.
위 표준으로 제안된 태그들 (picture/source)을 직접 이용할 수 있도록 jQuery 플러그인이 제안되기도 했습니다.
1 | <picture alt= "A Half Brained Idea" > |
2 | <source src= "assets/images/small.png" > |
3 | <source src= "assets/images/medium.png" media= "(min-width:440px)" > |
4 | <source src= "assets/images/large.png" media= "(min-width:600px)" > |
5 | <noscript> |
6 | <img src= "assets/images/large.png" alt= "A Half Brained Idea" > |
7 | </noscript> |
8 | </picture> |
1 | $( function (){ |
2 | $( 'picture' ).picture(); |
3 | }); |
그밖에 이미지는 아니지만, 비 텍스트 요소들의 반응형 기법들에 대한 (완전하지 않은) 자료 링크들입니다. 특히 반응형 광고는, 나중에 시간이 되면 더 많은 자료 조사 후 별도의 강의로 만들려고 합니다.
js 이미지 리사이즈
목적 : 부모 div박스안에 이미지를 비율에 맞게 컨트롤 한다.
유용한게 쓰던 스크립트는 오늘 새로 손을 보았다.
int_resizeimage2=0;
resizeimage2 = function(obj,boxsize_w,boxsize_h,outsize_w,outsize_h,isFill,longpic_proc,callback) {
var ratio=0,box_ratio=0,target_w,target_h,$parent = $(obj).parents('div');
if(typeof(isFill)=="undefined") isFill=false;//default value
try{
if(boxsize_w=="auto") boxsize_w=$parent.width();
boxsize_h = boxsize_h || boxsize_w;
ratio=$(obj).width()/$(obj).height();
box_ratio=boxsize_w/boxsize_h;
longpic_proc = longpic_proc || false;
if(ratio==0 || $(obj).width()==0 || $(obj).height()==0){
int_resizeimage2=setinterval(function() { resizeimage2(obj,boxsize_w,boxsize_h,outsize_w,outsize_h,longpic_proc); },500);
return;
}else{
ratio=parseInt(ratio*100)/100;
box_ratio=parseInt(box_ratio*100)/100;
}
if(longpic_proc && Math.abs(ratio)>2.5){ //긴그림처리
boxsize=boxsize*(1.5);
}
if(ratio>box_ratio){//가로
target_w = isFill ? parseInt(ratio*boxsize_h) : boxsize_w;
target_h = isFill ? boxsize_h : parseInt((1/ratio)*boxsize_w);
}else if(ratio<box_ratio){//세로
target_w = isFill ? boxsize_w : parseInt(ratio*boxsize_h);
target_h = isFill ? parseInt((1/ratio)*boxsize_w) : boxsize_h;
}else{//정사이즈 or 오류
target_w = boxsize_w;
target_h = boxsize_h;
}
$(obj).width(target_w);
$(obj).height(target_h);
outsize_w = outsize_w || boxsize_w;
outsize_h = outsize_h || boxsize_h;
if(isFill) $parent.css("overflow","hidden");
$(obj).css("position","absolute").css("top",(outsize_h-$(obj).height())/2+"px").css("left",(outsize_w-$(obj).width())/2+"px");
clearinterval(int_resizeimage2);
if(typeof(callback)=="function") callback();
}catch(e){
}
}
http://poponyang.tistory.com/entry/javascript-img-resize
$('.class thum_image').each(function(){
var bi = document.getElementById("bigimage");
var bi_width = bi.style.width;
var bi_height =bi.style.height;
var maxWidth = bi_width; // 이미지의 최대 가로 사이즈
var maxHeight = bi_height; //이미지의 최대 세로 사이즈
var ratio = 0; // used for aspect ratio
var width = $(this).width(); //현재 이미지의 가로
var height = $(this).height(); // 현재 이미지의 세로
//현재 이미지가 최대 이미지보다 큰지 체크
if (width > maxWidth){
ratio = maxWidth / width; // 이미지의 비율 구함
height = height * ratio ; //비율에 맞는 가로,세로 길이 구함
widhth = width * ratio;
$(this).width(width); // 수정된 길이를 이미지에 적용
$(this).height(height);
}
});
=> 나한테 맞게 수정한 건데 안됨.
function doShow(imgSrc){
var bi = document.getElementById("bigimage");
var bi_width = bi.style.width;
var bi_height =bi.style.height;
var maxWidth = bi_width; // 이미지의 최대 가로 사이즈
var maxHeight = bi_height; //이미지의 최대 세로 사이즈
var ratio = 0; // used for aspect ratio
var width = $(imgSrc).width(); //현재 이미지의 가로
var height = $(imgSrc).height(); // 현재 이미지의 세로
// Check if the current width is larger than the max
if(width > maxWidth){
ratio = maxWidth / width; // get ratio for scaling image
$(imgSrc).css("width", maxWidth); // Set new width
$(imgSrc).css("height", height * ratio); // Scale height based on ratio
height = height * ratio; // Reset height to match scaled image
width = width * ratio; // Reset width to match scaled image
}
// Check if current height is larger than max
if(height > maxHeight){
ratio = maxHeight / height; // get ratio for scaling image
$(imgSrc).css("height", maxHeight); // Set new height
$(imgSrc).css("width", width * ratio); // Scale width based on ratio
width = width * ratio; // Reset width to match scaled image
height = height * ratio; // Reset height to match scaled image
}
$(imgSrc).width = width;
$(imgSrc).height = height;
document.getElementById("bigimage").src = imgSrc;
}
=> 나한테 맞게 수정한 건데 안됨.
$(document).ready(function() {
$('.story-small img').each(function() {
var maxWidth = 100; // Max width for the image
var maxHeight = 100; // Max height for the image
var ratio = 0; // Used for aspect ratio
var width = $(this).width(); // Current image width
var height = $(this).height(); // Current image height
// Check if the current width is larger than the max
if(width > maxWidth){
ratio = maxWidth / width; // get ratio for scaling image
$(this).css("width", maxWidth); // Set new width
$(this).css("height", height * ratio); // Scale height based on ratio
height = height * ratio; // Reset height to match scaled image
width = width * ratio; // Reset width to match scaled image
}
// Check if current height is larger than max
if(height > maxHeight){
ratio = maxHeight / height; // get ratio for scaling image
$(this).css("height", maxHeight); // Set new height
$(this).css("width", width * ratio); // Scale width based on ratio
width = width * ratio; // Reset width to match scaled image
height = height * ratio; // Reset height to match scaled image
}
});
});
/**
* Conserve aspect ratio of the orignal region. Useful when shrinking/enlarging
* images to fit into a certain area.
*
* @param {Number} srcWidth Source area width
* @param {Number} srcHeight Source area height
* @param {Number} maxWidth Fittable area maximum available width
* @param {Number} maxHeight Fittable area maximum available height
* @return {Object} { width, heigth }
*/
function calculateAspectRatioFit(srcWidth, srcHeight, maxWidth, maxHeight) {
var ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
return { width: srcWidth*ratio, height: srcHeight*ratio };
}
$('#productThumb img').each(function() {
var maxWidth = 140; // Max width for the image
var maxHeight = 140; // Max height for the image
var ratio = 0; // Used for aspect ratio
var width = $(this).width(); // Current image width
var height = $(this).height(); // Current image height
// Check if the current width is larger than the max
if(width > height){
height = ( height / width ) * maxHeight;
} else if(height > width){
maxWidth = (width/height)* maxWidth;
}
$(this).css("width", maxWidth); // Set new width
$(this).css("height", maxHeight); // Scale height based on ratio
});
<script type="text/javascript">
$(function(){
$('#slider img').each(function(){
var ReqWidth = 1000; // Max width for the image
var ReqHeight = 300; // Max height for the image
var width = $(this).width(); // Current image width
var height = $(this).height(); // Current image height
// Check if the current width is larger than the max
if (width > height && height < ReqHeight) {
$(this).css("min-height", ReqHeight); // Set new height
}
else
if (width > height && width < ReqWidth) {
$(this).css("min-width", ReqWidth); // Set new width
}
else
if (width > height && width > ReqWidth) {
$(this).css("max-width", ReqWidth); // Set new width
}
else
(height > width && width < ReqWidth)
{
$(this).css("min-width", ReqWidth); // Set new width
}
});
});
</script>
touchSlider (0) | 2014.10.14 |
---|---|
자바스크립트 이미지 비율 유지 / 썸네일 크게 보이기 (0) | 2014.09.25 |
자바스크립트 예제 모음 (0) | 2014.09.25 |
[자바스크립트] 이미지 리사이징 (0) | 2014.09.24 |
섬네일 이미지 클릭시 큰 이미지로 보여주기 (0) | 2014.09.15 |