검색
다른 검색어로 검색을 시도하시기 바랍니다.
구너갤러리 15.11.2
구너갤러리가 업데이트 되었습니다.
관리를 위해 썸네일을 모두 한자리에서 관리하도록 처리 하였습니다.
업데이트사항
- 썸네일을 루트폴더에 /ggthumbnail 에서 모두 관리.
기본 기능
- 모바일/PC 반응형 웹
- PC이용시 키보드로 제어
- 한곡 반복
- 파일 하나로 하위디렉토리 전체 갤러리화
- 디렉토리 구분 출력
- 압축파일 다운로드 가능하도록 출력
- 외부 라이브러리 다운받을 필요 없도록 만듬.(jQuery 등)
- 이미지 바로 다운로드 받기 지원.
!! 파일 하나로 내 서버가 갤러리가된다!
!! one-file php image gallery 구너갤러리.
jQuery 플러그인과 swipebox 플러그인을 이용했습니다.(swipebox 는 약간의 수정이 있었습니다.)
두가지 파일이 필요합니다.
.htaccess 와 index.php 두개입니다.
아래 파일을 받아주세요.
1 2 3 | // /Music/ 은 index.php 가 있는 경로(서버루트로부터의 상대경로)를 말합니다. // .htaccess 는 아파치 웹서버를 사용시에 적용이되며 이를 지원하지 않는 환경에서는 기존방법을 이용하여야 합니다. DirectoryIndex /Pictures/index.php |
아래는 index.php 의 php 부분입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | <?php /** * * 상구너 http://blog.sanguneo.com * 구너갤러리 15.11 * **/ $uri = rawurldecode( str_replace ( "/Pictures" , "." , $_SERVER [ "REQUEST_URI" ])); if (isset( $_GET [ "dn" ])&& $_GET [ "dn" ]== "y" ){ $filepath = explode ( "?" , $uri )[0]. $_GET [ "path" ]; $path = explode ( "?" , $uri )[0]; $filesize = filesize ( $filepath ); $path_parts = pathinfo ( $filepath ); $filename = $path_parts [ 'basename' ]; $extension = $path_parts [ 'extension' ]; $mime = getImageSize ( $filepath )[ 'mime' ]; header( "Pragma: public" ); header( "Expires: 0" ); header( "Content-Type: application/octet-stream" ); header( "Content-Disposition: attachment; filename=\"" . $_GET [ "path" ]. "\"" ); header( "Content-Transfer-Encoding: binary" ); header( "Content-Length: " . $filesize ); ob_clean(); flush (); readfile( $filepath ); } function startsWith( $haystack , $needle ) { return $needle === "" || strrpos ( $haystack , $needle , - strlen ( $haystack )) !== FALSE;} function endsWith( $haystack , $needle ){ return $needle === "" || substr ( $haystack , - strlen ( $needle )) === $needle ; } function humanFileSize( $size ){ if ( $size >= 1073741824) { return round ( $size / 1024 / 1024 / 1024, 1) . 'GB' ; } elseif ( $size >= 1048576) { return round ( $size / 1024 / 1024, 1) . 'MB' ; } elseif ( $size >= 1024) { return round ( $size / 1024, 1) . 'KB' ; } else { return $size . ' bytes' ; } return '-' ; } function cut_str( $str , $len , $suffix = "…" ) { $s = mb_strimwidth( $str , 0, $len *2, "" , "utf-8" ); $cnt = 0; for ( $i =0; $i < strlen ( $s ); $i ++) if (ord( $s [ $i ]) > 127) $cnt ++; $s = mb_strimwidth( $str , 0, $len *2, "" , "utf-8" ); if ( strlen ( $s ) >= strlen ( $str )) $suffix = "" ; return $s . $suffix ; } ///변환된함수 // 원본 이미지 -> 썸네일로 만드는 함수 function thumbnail( $file , $max_width , $max_height ) { global $uri ; if ( strpos ( $uri , "ggthumbnails" ) !== false ) return $file ; // if(!file_exists($uri.".thumbnails/".$file)){ $exist = "./ggthumbnails/" . str_replace ( "/" , "$" , str_replace ( "./" , "" ,( $uri . $file ))); if (! file_exists ( $exist )){ $img_info = getImageSize ( $uri . $file ); //원본이미지의 정보를 얻어옵니다 $mime = $img_info [ 'mime' ]; switch ( $mime ) { case 'image/jpeg' : $image_create_func = 'imagecreatefromjpeg' ; $image_save_func = 'imagejpeg' ; $quality = 100; break ; case 'image/png' : $image_create_func = 'imagecreatefrompng' ; $image_save_func = 'imagepng' ; $quality = 9; break ; case 'image/gif' : $image_create_func = 'imagecreatefromgif' ; $image_save_func = 'imagegif' ; break ; default : throw Exception( 'Unknown image type.' ); } $src_img = $image_create_func ( $uri . $file ); //JPG파일로부터 이미지를 읽어옵니다 $img_width = $img_info [0]; $img_height = $img_info [1]; if (( $img_width / $max_width ) == ( $img_height / $max_height )) { //원본과 썸네일의 가로세로비율이 같은경우 $dst_width = $max_width ; $dst_height = $max_height ; } elseif (( $img_width / $max_width ) < ( $img_height / $max_height )) { //세로에 기준을 둔경우 $dst_width = $max_height *( $img_width / $img_height ); $dst_height = $max_height ; } else { //가로에 기준을 둔경우 $dst_width = $max_width ; $dst_height = $max_width *( $img_height / $img_width ); } $dst_img = imagecreatetruecolor( $dst_width , $dst_height ); //타겟이미지를 생성합니다 switch ( $mime ) { case 'image/png' : $background = imagecolorallocate( $dst_img , 0, 0, 0); imagecolortransparent( $dst_img , $background ); imagealphablending( $dst_img , false); imagesavealpha( $dst_img , true); break ; case 'image/gif' : $background = imagecolorallocate( $dst_img , 0, 0, 0); // removing the black from the placeholder imagecolortransparent( $dst_img , $background ); break ; } Imagecopyresampled( $dst_img , $src_img , 0, 0, 0, 0, $dst_width , $dst_height , $img_width , $img_height ); $image_save_func ( $dst_img , $exist , $quality ); //실제로 이미지파일을 생성합니다 ImageDestroy( $dst_img ); ImageDestroy( $src_img ); } //error_log(rawurlencode($uri.$file)); return "/Pictures/" . $exist ; } function dirlist(){ global $uri ; $default_dir = $uri ; if (! $dh = @opendir( $default_dir )) { return false; } $filelist = Array(); $ziplist = Array(); while (( $file = readdir( $dh )) !== false) { if (endsWith( $file , "zip" )||endsWith( $file , "rar" )||endsWith( $file , "tar" )||endsWith( $file , "gz" )||endsWith( $file , "bz2" )) array_push ( $ziplist , $file ); if (startsWith( $file , "." ) || $file == "ggthumbnails" ||startsWith( $file , "$" ) || $file == "." || ! is_dir ( $default_dir . $file )) continue ; // . , .. , 디렉토리는 무시 array_push ( $filelist , $file ); } array_push ( $filelist , ".." ); sort( $filelist ); foreach ( $filelist as $dirname ) { echo "<li class=\"nimg dir\" data-dirname=\"" . $dirname . "\">\n<div>\n" . $dirname . "</div></li>\n" ; } sort( $ziplist ); foreach ( $ziplist as $dirname ) { echo "<li class=\"nimg archive\" data-dirname=\"" . $dirname . "\">\n<a href=\"" . $dirname . "\">\n" . $dirname . "</a></li>\n" ; } closedir ( $dh ); } function filelist(){ global $uri ; $default_dir = $uri ; if (! $dh = @opendir( $default_dir )) { return false; } $filelist = Array(); while (( $file = readdir( $dh )) !== false) { //if ($file == "." || $file == ".." || !endsWith($file, "mp3")) // continue; // . 과 .. 디렉토리는 무시 //$filelist[] = $file . "|" . humanFileSize(filesize($file)); if (startsWith( $file , "." )) continue ; if (endsWith( $file , "jpg" )||endsWith( $file , "jpeg" )||endsWith( $file , "gif" )||endsWith( $file , "png" )) { $filelist [] = $file . "|" . humanFileSize( filesize ( $default_dir . $file )); } } sort( $filelist ); if (isset( $filelist [1])) $filefirst = explode ( "|" , $filelist [1])[0]; foreach ( $filelist as $filename ) { echo "\t<li><a class=\"swipebox\" title=\"" . explode ( "|" , $filename )[0]. "\" href=\"" . explode ( "|" , $filename )[0]. "\"><ul class=\"listentity\" data=\"" . explode ( "|" , $filename )[0] . "\">\n\t\t<li class=\"img\" style=\"background-image:url(" . thumbnail( explode ( "|" , $filename )[0], "150" , "150" ) . ");\"></li><li class=\"mtitle\">" . cut_str( explode ( "|" , $filename )[0],9) . "</li>\n\t\t</ul></a></li>\n" ; } if (isset( $filelist [0])) $filefirst = explode ( "|" , $filelist [0])[0]; closedir ( $dh ); } ?> |
설치는 대략 이렇습니다.
1. 이미지파일들이 잔뜩 있는 폴더(디렉토리)에 압축을 풀어 넣고
2. 에디터로 경로를 수정합니다.
3. 해당 페이지를 브라우저로 접속합니다.
끝
사용상 문의는 댓글로 ^^
'Develop' 카테고리의 다른 글
mWeb Mac버전 배포 (4) | 2016.11.22 |
---|---|
개발자 후원하기. (0) | 2016.07.13 |
구너갤러리 15.11 (0) | 2015.11.04 |
구너 플레이어 15.11 (1) | 2015.11.04 |
베지에 곡선 (Bezier Curve) (1) | 2015.09.04 |
구너갤러리 15.11
구너갤러리가 개발되었습니다.
기본 기능
- 모바일/PC 반응형 웹
- PC이용시 키보드로 제어
- 한곡 반복
- 파일 하나로 하위디렉토리 전체 갤러리화
- 디렉토리 구분 출력
- 압축파일 다운로드 가능하도록 출력
- 외부 라이브러리 다운받을 필요 없도록 만듬.(jQuery 등)
- 이미지 바로 다운로드 받기 지원.
!! 파일 하나로 내 서버가 갤러리가된다!
!! one-file php image gallery 구너갤러리.
jQuery 플러그인과 swipebox 플러그인을 이용했습니다.(swipebox 는 약간의 수정이 있었습니다.)
두가지 파일이 필요합니다.
.htaccess 와 index.php 두개입니다.
아래 파일을 받아주세요.
1 2 3 | // /Music/ 은 index.php 가 있는 경로(서버루트로부터의 상대경로)를 말합니다. // .htaccess 는 아파치 웹서버를 사용시에 적용이되며 이를 지원하지 않는 환경에서는 기존방법을 이용하여야 합니다. DirectoryIndex /Pictures/index.php |
아래는 index.php 의 php 부분입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | <?php /** * * 상구너 http://blog.sanguneo.com * 구너갤러리 15.11 * **/ $uri = rawurldecode( str_replace ( "/Pictures" , "." , $_SERVER [ "REQUEST_URI" ])); if (isset( $_GET [ "dn" ])&& $_GET [ "dn" ]== "y" ){ $filepath = explode ( "?" , $uri )[0]. $_GET [ "path" ]; $path = explode ( "?" , $uri )[0]; $filesize = filesize ( $filepath ); $path_parts = pathinfo ( $filepath ); $filename = $path_parts [ 'basename' ]; $extension = $path_parts [ 'extension' ]; $mime = getImageSize ( $filepath )[ 'mime' ]; header( "Pragma: public" ); header( "Expires: 0" ); header( "Content-Type: application/octet-stream" ); header( "Content-Disposition: attachment; filename=\"" . $_GET [ "path" ]. "\"" ); header( "Content-Transfer-Encoding: binary" ); header( "Content-Length: " . $filesize ); ob_clean(); flush (); readfile( $filepath ); } function startsWith( $haystack , $needle ) { return $needle === "" || strrpos ( $haystack , $needle , - strlen ( $haystack )) !== FALSE;} function endsWith( $haystack , $needle ){ return $needle === "" || substr ( $haystack , - strlen ( $needle )) === $needle ; } function humanFileSize( $size ){ if ( $size >= 1073741824) { return round ( $size / 1024 / 1024 / 1024, 1) . 'GB' ; } elseif ( $size >= 1048576) { return round ( $size / 1024 / 1024, 1) . 'MB' ; } elseif ( $size >= 1024) { return round ( $size / 1024, 1) . 'KB' ; } else { return $size . ' bytes' ; } return '-' ; } function cut_str( $str , $len , $suffix = "…" ) { $s = mb_strimwidth( $str , 0, $len *2, "" , "utf-8" ); $cnt = 0; for ( $i =0; $i < strlen ( $s ); $i ++) if (ord( $s [ $i ]) > 127) $cnt ++; $s = mb_strimwidth( $str , 0, $len *2, "" , "utf-8" ); if ( strlen ( $s ) >= strlen ( $str )) $suffix = "" ; return $s . $suffix ; } ///변환된함수 // 원본 이미지 -> 썸네일로 만드는 함수 function thumbnail( $file , $max_width , $max_height ) { global $uri ; if (! file_exists ( $uri . ".thumbnails/" . $file )){ $img_info = getImageSize ( $uri . $file ); //원본이미지의 정보를 얻어옵니다 $mime = $img_info [ 'mime' ]; switch ( $mime ) { case 'image/jpeg' : $image_create_func = 'imagecreatefromjpeg' ; $image_save_func = 'imagejpeg' ; $quality = 100; break ; case 'image/png' : $image_create_func = 'imagecreatefrompng' ; $image_save_func = 'imagepng' ; $quality = 9; break ; case 'image/gif' : $image_create_func = 'imagecreatefromgif' ; $image_save_func = 'imagegif' ; break ; default : throw Exception( 'Unknown image type.' ); } $src_img = $image_create_func ( $uri . $file ); //JPG파일로부터 이미지를 읽어옵니다 $img_width = $img_info [0]; $img_height = $img_info [1]; if (( $img_width / $max_width ) == ( $img_height / $max_height )) { //원본과 썸네일의 가로세로비율이 같은경우 $dst_width = $max_width ; $dst_height = $max_height ; } elseif (( $img_width / $max_width ) < ( $img_height / $max_height )) { //세로에 기준을 둔경우 $dst_width = $max_height *( $img_width / $img_height ); $dst_height = $max_height ; } else { //가로에 기준을 둔경우 $dst_width = $max_width ; $dst_height = $max_width *( $img_height / $img_width ); } $dst_img = imagecreatetruecolor( $dst_width , $dst_height ); //타겟이미지를 생성합니다 switch ( $mime ) { case 'image/png' : $background = imagecolorallocate( $dst_img , 0, 0, 0); imagecolortransparent( $dst_img , $background ); imagealphablending( $dst_img , false); imagesavealpha( $dst_img , true); break ; case 'image/gif' : $background = imagecolorallocate( $dst_img , 0, 0, 0); // removing the black from the placeholder imagecolortransparent( $dst_img , $background ); break ; } Imagecopyresampled( $dst_img , $src_img , 0, 0, 0, 0, $dst_width , $dst_height , $img_width , $img_height ); $image_save_func ( $dst_img , $uri . ".thumbnails/" . $file , $quality ); //실제로 이미지파일을 생성합니다 ImageDestroy( $dst_img ); ImageDestroy( $src_img ); } return ".thumbnails/" . $file ; } function dirlist(){ global $uri ; $default_dir = $uri ; if (! $dh = @opendir( $default_dir )) { return false; } $filelist = Array(); $ziplist = Array(); while (( $file = readdir( $dh )) !== false) { if (endsWith( $file , "zip" )||endsWith( $file , "rar" )||endsWith( $file , "tar" )||endsWith( $file , "gz" )||endsWith( $file , "bz2" )) array_push ( $ziplist , $file ); if (startsWith( $file , "." ) ||startsWith( $file , "$" ) || $file == "." || ! is_dir ( $default_dir . $file )) continue ; // . , .. , 디렉토리는 무시 array_push ( $filelist , $file ); } array_push ( $filelist , ".." ); sort( $filelist ); foreach ( $filelist as $dirname ) { echo "<li class=\"nimg dir\" data-dirname=\"" . $dirname . "\">\n<div>\n" . $dirname . "</div></li>\n" ; } sort( $ziplist ); foreach ( $ziplist as $dirname ) { echo "<li class=\"nimg archive\" data-dirname=\"" . $dirname . "\">\n<a href=\"" . $dirname . "\">\n" . $dirname . "</a></li>\n" ; } closedir ( $dh ); } function filelist(){ global $uri ; $default_dir = $uri ; if (! $dh = @opendir( $default_dir )) { return false; } $filelist = Array(); $hereis = false; while (( $file = readdir( $dh )) !== false) { //if ($file == "." || $file == ".." || !endsWith($file, "mp3")) // continue; // . 과 .. 디렉토리는 무시 //$filelist[] = $file . "|" . humanFileSize(filesize($file)); if (startsWith( $file , "." )) continue ; if (endsWith( $file , "jpg" )||endsWith( $file , "jpeg" )||endsWith( $file , "gif" )||endsWith( $file , "png" )) { $filelist [] = $file . "|" . humanFileSize( filesize ( $default_dir . $file )); $hereis = true; } } if ( $hereis ){ if (! file_exists ( $uri . ".thumbnails" )){ if ( mkdir ( $uri . ".thumbnails" , 0775,true)) { if ( is_dir ( $uri . ".thumbnails" )) { @ chmod ( $uri . ".thumbnails" , 0775); } } } } sort( $filelist ); if (isset( $filelist [1])) $filefirst = explode ( "|" , $filelist [1])[0]; foreach ( $filelist as $filename ) { echo "\t<li><a class=\"swipebox\" title=\"" . explode ( "|" , $filename )[0]. "\" href=\"" . explode ( "|" , $filename )[0]. "\"><ul class=\"listentity\" data=\"" . explode ( "|" , $filename )[0] . "\">\n\t\t<li class=\"img\" style=\"background-image:url(" . thumbnail( explode ( "|" , $filename )[0], "150" , "150" ) . ");\"></li><li class=\"mtitle\">" . cut_str( explode ( "|" , $filename )[0],9) . "</li>\n\t\t</ul></a></li>\n" ; } if (isset( $filelist [0])) $filefirst = explode ( "|" , $filelist [0])[0]; closedir ( $dh ); } ?> |
설치는 대략 이렇습니다.
1. 이미지파일들이 잔뜩 있는 폴더(디렉토리)에 압축을 풀어 넣고
2. 에디터로 경로를 수정합니다.
3. 해당 페이지를 브라우저로 접속합니다.
끝
사용상 문의는 댓글로 ^^
'Develop' 카테고리의 다른 글
개발자 후원하기. (0) | 2016.07.13 |
---|---|
구너갤러리 15.11.2 (0) | 2015.11.16 |
구너 플레이어 15.11 (1) | 2015.11.04 |
베지에 곡선 (Bezier Curve) (1) | 2015.09.04 |
[구너 플레이어] 15.8 단일파일 php 음악 플레이어. (4) | 2015.08.06 |
구너 플레이어 15.11
구너플레이어가 15.11로 업데이트 되었습니다.
버전 업데이트 사항.
- 여러 폴더(디렉토리) 에 index.php 를 다 넣어주어야했던 부분 개선.
- 디렉토리 구분 출력
- 압축파일 다운로드 가능하도록 출력
- 외부 라이브러리 다운받을 필요 없도록 만듬.(jQuery 등)
기본 기능
- 모바일/PC 관계없이 음악 플레이
- PC이용시 키보드로 제어
- 음악 볼륨 자동 저장
- 한곡 반복
!! 파일 하나로 내 서버가 스트리밍 플레이어가된다!
!! one-file php music player 구너플레이어.
이번버전에는 두가지 파일이 필요합니다.
.htaccess 와 index.php 두개입니다.
아래 파일을 받아주세요.

1 2 3 | // /Music/ 은 index.php 가 있는 경로(서버루트로부터의 상대경로)를 말합니다. // .htaccess 는 아파치 웹서버를 사용시에 적용이되며 이를 지원하지 않는 환경에서는 기존방법을 이용하여야 합니다. DirectoryIndex /Music/index.php |
아래는 index.php 의 php 부분입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | <?php /** * * 상구너 http://blog.sanguneo.com * 구너플레이어 15.11 * **/ // /Music 은 .htaccess 와같이 index.php 가 위치한 경로입니다. $uri = rawurldecode(str_replace( "/Music" , "." ,$_SERVER[ "REQUEST_URI" ])); $filefirst= "" ; function startsWith($haystack, $needle) { return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== FALSE;} function endsWith($haystack, $needle){ return $needle === "" || substr($haystack, -strlen($needle)) === $needle; } function humanFileSize($size){ if ($size >= 1073741824) { return round($size / 1024 / 1024 / 1024, 1) . 'GB' ; } elseif ($size >= 1048576) { return round($size / 1024 / 1024, 1) . 'MB' ; } elseif ($size >= 1024) { return round($size / 1024, 1) . 'KB' ; } else { return $size . ' bytes' ; } return '-' ; } function playlist(){ global $uri,$filefirst; $default_dir = $uri; if (!$dh = @opendir($default_dir)) { return false ; } $dirlist = Array(); $ziplist = Array(); $filelist = Array(); while (($file = readdir($dh)) !== false ) { if (endsWith($file, "mp3" )||endsWith($file, "ogg" )) $filelist[] = $file . "|" . humanFileSize(filesize($uri.$file)); if (endsWith($file, "zip" )||endsWith($file, "rar" )||endsWith($file, "tar" )||endsWith($file, "gz" )||endsWith($file, "bz2" )) array_push($ziplist,$file. "|" .humanFileSize(filesize($default_dir.$file))); if (startsWith($file, "." ) ||startsWith($file, "$" ) ||$file == "." || !is_dir($default_dir.$file)) continue ; // . , .. , 디렉토리는 무시 array_push($dirlist,$file); } array_push($dirlist, ".." ); sort($dirlist); sort($ziplist); sort($filelist); echo "<div id=\"dirlist\">\n" ; { foreach ($dirlist as $dirname) { echo "<ul class=\"listentity\" data=\"" . $dirname . "\">\n<li class=\"mtitle2\">\n" . $dirname . "</li>\n\n<li class=\"msize\">Directory /</li></ul>\n" ; } foreach ($ziplist as $zipname) { echo "<ul class=\"listentity\" data=\"" . rawurlencode(explode( "|" , $zipname)[0]) . "\">\n<li class=\"mtitle2\">\n" . explode( "|" , $zipname)[0] . "</li>\n\n<li class=\"msize\"><a href=\"" . rawurlencode(explode( "|" , $zipname)[0]) . "\">" . explode( "|" , $zipname)[1] . "</a></li></ul>\n" ; } echo "</div>\n" ; echo "<div id=\"playlist\">\n" ; foreach ($filelist as $filename) { echo "\t<ul class=\"listentity\" data=\"" . explode( "|" , $filename)[0] . "\">\n\t\t<li class=\"mtitle\">" . explode( "|" , $filename)[0] . "</li>\n\t\t<li class=\"mcurrent\">▶</li>\n\t\t<li class=\"msize\"><a href=\"" . rawurlencode(explode( "|" , $filename)[0]) . "\">" . explode( "|" , $filename)[1] . "</a></li>\n\t</ul>\n" ; } } echo "</div>" ; $filefirst = explode( "|" , $filelist[0])[0]; closedir($dh); } ?> |
설치는 대략 이렇습니다.
1. 음악파일들이 잔뜩 있는 폴더(디렉토리)에 압축을 풀어 넣고
2. 에디터로 경로를 수정합니다.
3. 해당 페이지를 브라우저로 접속합니다.
끝
사용상 문의는 댓글로 ^^
'Develop' 카테고리의 다른 글
구너갤러리 15.11.2 (0) | 2015.11.16 |
---|---|
구너갤러리 15.11 (0) | 2015.11.04 |
베지에 곡선 (Bezier Curve) (1) | 2015.09.04 |
[구너 플레이어] 15.8 단일파일 php 음악 플레이어. (4) | 2015.08.06 |
PHP html5 css3 음악 플레이어. (0) | 2014.10.18 |
베지에 곡선 (Bezier Curve)
베지에 곡선(Bézier Curve) 이란 n개의 점으로부터 얻어지는 n-1차 곡선 이라고 위키피디아에 나와있습니다.
딱히 그 정의가 중요한것은 아니고 우리는 이 곡선을 어떻게 그릴 것인가 가 중요합니다.
본 글에서는 html5 의 canvas 와 자바스크립트를 이용해 설명하도록 하겠습니다.
사실 html5의 canvas 나 svg 그외 많은 그래픽 라이브러리들이 베지에 곡선 그리기를 기본적으로 제공합니다.
Canvas 기준으로 설명을 하면 Canvas 2D 의 컨텍스트 에는 세점을 이용하는 쿼드레틱(Quadratic Curve) 과 네 점을 이용하는 큐빅(Cubic Curve) 을 지원하는 메소드가 포함되어있습니다.
간단히 소개를 하자면 아래와 같습니다
1 2 3 4 5 6 7 8 9 10 11 12 | // Quadratic sample.ctx.beginpath(); sample.ctx.moveTo(x1,y1); sample.ctx.quadraticCurveTo(x2,y2,x3,y3); sample.ctx.stroke(); sample.ctx.closePath(); // Cubic sample.ctx.beginpath(); sample.ctx.moveTo(x1,y1); sample.ctx.bezierCurveTo(x2,y2,x3,y3,x4,y4); sample.ctx.stroke(); sample.ctx.closePath(); |
--
위처럼 간단하게 세점 혹은 네점만 알면 알아서 계산되고 선을 그을 수 있습니다.
그런데 여기서 세점을 모두 꼭 지나는 곡선이 필요하다고 하면 문제가 조금 복잡해집니다.
선은 끝점과 끝점을 지나고 중간에 있는 좌표들은 곡률을 지정하기위한 변수로만 이용되기때문입니다.
쿼드레틱을 예를들면
P1->P2->P3 로 이어지는 곡선은 P1 에서 P2 로 진행하는것처럼 보이지만 어느새 방향이 P3를 향하고 있습니다.
P1->P2 의 기울기와 P2->P3 의 기울기가 같지않은이상 곡선은 절대 P2를 지날 수 없습니다.
세점을 이용해 직접 구현해보세요.
이는 나중에 설명할 계산식을 참고하면 금방 아실 수 있습니다.
보정(Interpolation)
그래서 세 점을 꼭 지나도록 보정하는 추가 계산이 필요합니다.
쉽게말하면 P1->P2->P3 로 되어있는 좌표를 어떤 계산을 통해 P1-> P2` ->P3
으로 바꾸어서 P2를 지나도록 만듭니다. 상당히 간단한 개념입니다만 이를 계산하는 식은 덧셈뺄셈 정도로 끝나지 않습니다.
보정되는 포인트를 컨트롤 포인트(Control Point:Cx) 라 하겠습니다. 아래는 구현된 Cx를 구하는 함수입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | getControlPoints : function (x0,y0,x1,y1,x2,y2,t){ //x0~y2 는 좌표, t는 탄력(Tension)을 의미하며 곡선의 탄력을 말합니다. var d01=Math.sqrt(Math.pow(x1-x0,2)+Math.pow(y1-y0,2)); var d12=Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2)); // P1->P2 의 기울기, P2->P3의 기울기를 각각 구합니다. var fa=t*d01/(d01+d12); // 두 기울기의 합에서 첫번째 기울기를 나누고 텐션을 곱합니다. 이는 지정 좌표에서 a 점이 얼마나 떨어져있는가를 결정하는 a계수가됩니다. var fb=t-fa; // 텐션에서 a계수를 빼 b 계수를 만듭니다. var p1x=x1+fa*(x0-x2); var p1y=y1+fa*(y0-y2); var p2x=x1-fb*(x0-x2); var p2y=y1-fb*(y0-y2); // P1과 P3 의 거리와 계수를 곱한값을 각각 좌표에서 더하거나 뺍니다. return [p1x,p1y,p2x,p2y]; // 값을 리턴합니다. }, |
위와 같이 하면 곡선은 P1,C1,C2,P3 좌표를 이용하는 곡선이 되며 P1->P2->P3 를 모두지나는 곡선이 됩니다.
보정이없을땐 쿼드래틱이었는데 보정을 하고나니 좌표수가 하나 늘어서 큐빅으로 계산하게 되었네요.
--
곡선의 좌표(Coordinate of Curve)
선을 긋는 정도로 만족한다면 아래쪽은 참고할 필요가 없습니다. 그러나 이 선을 이루는 모든 좌표들을 알고싶다면 또 새로운 작업이 필요합니다.
우리는 구해지는 좌표를 통해, 더이상 기본으로 제공해주는 곡선 메소드를 이용할 필요가 없습니다.(물론 기본제공 메소드가 더 최적화 되어있습니다.) 단지 조금 정확한 혹은 세부적인 작업이 필요한경우 아와같은 방법을 이용할 수 있습니다.
쿼드래틱의 경우
위와 같은 커브를 그린다고 가정할때
각각 선위의 점을 t로 나눈(여기서 t는 텐션이 아닙니다.) 점(DP)의 좌표는 위처럼 구합니다
이런 식이 나오게됩니다.
식을 이용해 기본식을 구하면 위와 같습니다. 저는 위그림의 2번째 줄처럼 구현해보았습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | getQuadraticPoint : function (x0,y0,cx1,cy1,x1,y1){ var qu = 20; var bp = new Array(); var t=1/qu; bp.push(x0); bp.push(y0); for ( var k=1;k<qu;k++) { t+=1/qu; var x = (1-t)*((1-t)*x0+t*cx1)+t*((1-t)*cx1+t*x1); var y = (1-t)*((1-t)*y0+t*cy1)+t*((1-t)*cy1+t*y1); bp.push(x); bp.push(y); } return bp; }, |
베지에의 경우
위와같은 베지에 커브가 있다고 가정하면
각각의 나눈점 좌표는 위와 같으며 위 그림의 마지막줄처럼 결과가 도출이 됩니다.
식을 전개하면 위와 같습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | getBezierPoint : function (x0,y0,cx1,cy1,cx2,cy2,x3,y3){ var qu = 20; var bp = new Array(); var t=1/qu; bp.push(x0); bp.push(y0); for ( var k=1;k<qu;k++) { t+=1/qu; var x = t*(t*(t*x3+(1-t)*cx2)+(1-t)*(t*cx2+(1-t)*cx1))+(1-t)*(t*(t*cx2+(1-t)*cx1)+(1-t)*(t*cx1+(1-t)*x0)); var y = t*(t*(t*y3+(1-t)*cy2)+(1-t)*(t*cy2+(1-t)*cy1))+(1-t)*(t*(t*cy2+(1-t)*cy1)+(1-t)*(t*cy1+(1-t)*y0)); bp.push(x); bp.push(y); } return bp; }, |
쿼드레틱과 베지에 예제 메소드에서 qu 변수는 좌표의개수 즉 두 점사이에 나눈 수를 의미합니다. 나누어지는 수가 늘어나면 곡선은 조금더 자연스러워집니다.
결과는 array 로 도출이되고 이를 이용해 곡선을 따라 움직이는 엘리먼트 등을 구현할 수 있습니다.
두 식에서 굳이 t+=1/qu 로 한이유는 ...
없습니다. 하다보니 머리가 굳어서 안보였어요.. 입맛에맞게 수정하세요..
'Develop' 카테고리의 다른 글
구너갤러리 15.11.2 (0) | 2015.11.16 |
---|---|
구너갤러리 15.11 (0) | 2015.11.04 |
구너 플레이어 15.11 (1) | 2015.11.04 |
[구너 플레이어] 15.8 단일파일 php 음악 플레이어. (4) | 2015.08.06 |
PHP html5 css3 음악 플레이어. (0) | 2014.10.18 |
[구너 플레이어] 15.8 단일파일 php 음악 플레이어.
순수하게 본인의 필요에 의해 만들어진 html5 기반의 음악 플레이어.
브라우저상에서 실행이되며 PHP 와 Http 서버가 필요함(디렉토리 인덱스 체크)
mp3 와 ogg 를 지원하며 소스의 51번 라인 에 wav 등을 추가할 수 있음.
실행화면, 크기 자동조절.
소스상 표시문제로 테그를 -- 로 치환함
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | <?php /** * * 상구너 http://blog.sanguneo.com * 구너플레이어 15.08 * **/ function endsWith( $haystack , $needle ){ return $needle === "" || substr ( $haystack , - strlen ( $needle )) === $needle ; } function humanFileSize( $size ){ if ( $size >= 1073741824) { return round ( $size / 1024 / 1024 / 1024, 1) . 'GB' ; } elseif ( $size >= 1048576) { return round ( $size / 1024 / 1024, 1) . 'MB' ; } elseif ( $size >= 1024) { return round ( $size / 1024, 1) . 'KB' ; } else { return $size . ' bytes' ; } return '-' ; } function dirlist(){ $default_dir = "." ; if (! $dh = @opendir( $default_dir )) { return false; } $dirlist [] = ".." ; $filelist2 = array (); while (( $file = readdir( $dh )) !== false) { if ( $file == "." || $file == ".." || ! is_dir ( $file )) continue ; // . , .. , 디렉토리는 무시 $filelist2 [] = $file ; } sort( $filelist2 ); $dirlist = array_merge ( $dirlist , $filelist2 ); foreach ( $dirlist as $dirname ) { echo "<ul class=\"listentity\" data=\"" . $dirname . "\">\n<li class=\"mtitle2\">\n" . $dirname . "</li>\n\n</ul>\n" ; } closedir ( $df ); } function filelist(){ $default_dir = "." ; if (! $dh = @opendir( $default_dir )) { return false; } while (( $file = readdir( $dh )) !== false) { //if ($file == "." || $file == ".." || !endsWith($file, "mp3")) // continue; // . 과 .. 디렉토리는 무시 //$filelist[] = $file . "|" . humanFileSize(filesize($file)); if (endsWith( $file , "mp3" )||endsWith( $file , "ogg" )) $filelist [] = $file . "|" . humanFileSize( filesize ( $file )); } sort( $filelist ); $filefirst = explode ( "|" , $filelist [1])[0]; foreach ( $filelist as $filename ) { echo "\t<ul class=\"listentity\" data=\"" . explode ( "|" , $filename )[0] . "\">\n\t\t<li class=\"mtitle\">" . explode ( "|" , $filename )[0] . "</li>\n\t\t<li class=\"mcurrent\">▶</li>\n\t\t<li class=\"msize\"><a href=\"" . rawurlencode( explode ( "|" , $filename )[0]) . "\">" . explode ( "|" , $filename )[1] . "</a></li>\n\t</ul>\n" ; } $filefirst = explode ( "|" , $filelist [0])[0]; closedir ( $df ); } ?> <!doctype html> <--html> <head> <meta charset= "UTF-8" > <meta name= "viewport" content= "width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, target-densitydpi=medium-dpi" /> <title>sanguneo player v15.08</title> <--style>body{margin:0;padding:0}.headC{position:relative;height:80px;width:100%;top:0;left:0}#headI{position:fixed;background-color:white;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;border-bottom:gray 1px solid;z-index:100;height:80px}#fakehead{height:80px}.space{width:100%;height:10px}#musictitle{height:30%;width:100%;text-align:center;white-space:nowrap;text-overflow:ellipsis;-o-text-overflow:ellipsis;overflow:hidden;-moz-binding:url( 'ellipsis.xml#ellipsis' )}audio{width:100%}.tailC{position:relative;width:100%;bottom:0;left:0}#faketail{height:70px}#tailI{position:fixed;height:49px;padding:10px 0;border-top:gray 1px solid;background-color:white;text-align:center;z-index:100}#tailI center{font-size:13px;line-height:15px}#tailI input{width:15%;height:calc(100% - 15px);font-size:20pt;-webkit-appearance:button;-webkit-border-radius:0}#dirlist{padding-top:20px}#dirlist .listentity:last-child{border-bottom:0}#playlist{padding-bottom:20px}.listentity{-webkit-margin-before:0;-webkit-margin-after:0;-webkit-padding-start:10px;-webkit-padding- end :10px;width:calc(100% - 20px);height:30px;margin:0 auto;border-top:1px gray dashed;position:relative;clear:left;list-style:none;cursor:pointer}.listentity:hover{background-color:#CCCCCC}.listentity:last-child{border-bottom:1px gray dashed}.listentity li{line-height:30px;vertical-align:middle;font-size:10pt;float:left}.mtitle{width:77%;white-space:nowrap;text-overflow:ellipsis;-o-text-overflow:ellipsis;overflow:hidden;-moz-binding:url( 'ellipsis.xml#ellipsis' )}.mtitle2{width:100%;white-space:nowrap;text-overflow:ellipsis;-o-text-overflow:ellipsis;overflow:hidden;-moz-binding:url( 'ellipsis.xml#ellipsis' )}.mcurrent{width:5%;color:transparent}.msize{text-align:right;width:8%;padding-left:5%}.active{font-weight:bold}.active .mcurrent{color:black}a,a:hover,a:link,a:visited,a:active{color:gray;text-decoration:none}<--/style> <--script type= "text/javascript" > var volume=1;$(document).ready( function (){ var audio; var playlist; var tracks; var current; var loop=false;init(); function init(){current=0;audio=$( '#audio' );playlist=$( '#playlist' );tracks=playlist.find( 'ul' );len=tracks.length-1;audio[0].play();playlist.find( 'ul' ).click( function (e){link=$(this);current=link.index();run(link,audio[0]);});audio[0].onended= function (e){ if (!loop){current++; if (current==len+1){current=0;link=playlist.find( 'ul' )[0];} else {link=playlist.find( 'ul' )[current];}}run($(link),audio[0]);};audio[0].onpause= function (){$( '#play' ).attr( "value" , ">" );};audio[0].onplay= function (){$( '#play' ).attr( "value" , "||" );};} function run(link,player){par=link;document.title=link.attr( 'data' );player.src=encodeURIComponent(link.attr( 'data' ));$( 'html,body' ).animate({scrollTop:link.offset().top-$( '#headI' ).height()},500);$( '#musictitle' ).html(link.attr( 'data' ));par.addClass( 'active' ).siblings().removeClass( 'active' );audio[0].load();audio[0].play();$( '#play' ).attr( "value" , ">" );}$( '#prev' ).click( function (){ if ($( '#audio' )[0].currentTime>3){$( '#audio' )[0].currentTime=0;} else {current--; if (current==-1){current=len;}link=playlist.find( 'ul' )[current];run($(link),audio[0]);}});$( '#play' ).click( function (){ if (audio[0].paused==false){audio[0].pause();$( '#play' ).attr( "value" , ">" );} else {audio[0].play();$( '#play' ).attr( "value" , "||" );}});$( '#next' ).click( function (){current++; if (current==len+1){current=0;link=playlist.find( 'ul' )[0];} else {link=playlist.find( 'ul' )[current];}run($(link),audio[0]);});$( '#loop' ).click( function (){ if (!loop){loop=true;$( '#loop' ).attr( "value" , "!@" );} else {loop=false;$( '#loop' ).attr( "value" , "@" );}});$( '#dirlist' ).find( 'ul' ).click( function (e){location.href=$(this).attr( "data" );});$( 'html' ).keydown( function (e){ var key=e.which; switch (key){ case 32:$( "#play" ).trigger( "click" );e.preventDefault(); break ; case 37:$( "#prev" ).trigger( "click" );e.preventDefault(); break ; case 38: if ($( '#audio' )[0].volume<1){$( '#audio' )[0].volume=parseFloat($( '#audio' )[0].volume.toFixed(1))+0.1;}e.preventDefault(); break ; case 39:$( "#next" ).trigger( "click" );e.preventDefault(); break ; case 40: if ($( '#audio' )[0].volume>0){$( '#audio' )[0].volume=parseFloat($( '#audio' )[0].volume.toFixed(1))-0.1;}e.preventDefault(); break ; default : break ;}}); if ($.type(window.sessionStorage.gouVolume)!= "undefined" ){$( '#audio' )[0].volume=window.sessionStorage.gouVolume;}$( '#audio' )[0].onvolumechange= function (){window.sessionStorage.gouVolume=$( '#audio' )[0].volume;}; var event=document.createEvent( "HTMLEvents" );event.initEvent( "click" ,true,false);playlist.find( 'ul' )[0].dispatchEvent(event); var browserCheckText= new Array( 'iPhone' , 'iPod' , 'BlackBerry' , 'Android' , 'Windows CE' , 'LG' , 'MOT' , 'SAMSUNG' , 'SonyEricsson' , 'Symbian' , 'Windows Phone' , 'webOS' , 'Opera Mini' , 'Opera Mobi' , 'POLARIS' , 'IEMobile' , 'nokia' ); for ( var word in browserCheckText){ if (navigator.userAgent.toUpperCase().match(browserCheckText[word].toUpperCase())!=null){$( '#play' ).attr( "value" , ">" );audio[0].pause();$( '#tailI > center' ).remove();$( '#tailI > input' ).css({ 'height' : "100%" }); break ;} else {$( '#play' ).attr( "value" , "||" );}}}); <--/script> <--/head> <--body> <div id= "headI" class = "headC" > <div class = "space" ></div> <div id= "musictitle" >#music title</div> <audio id= "audio" autoplay= "" controls= "" src= "<?php echo $filefirst; ?>" ></audio> </div> <div id= "fakehead" class = "headC" ></div> <!--플레이리스트 시작--> <div id= "dirlist" > <!--?php echo dirlist();?--> </div> <div id= "playlist" > <!--?php echo filelist();?--> </div> <!--플레이리스트 종료--> <div id= "tailI" class = "tailC" > <center>[← 되감기/이전곡] [Space 일시정지/재생] [→다음곡] [↑↓볼륨조절]</center> <input id= "prev" type= "button" value= "<<" > <input id= "play" type= "button" value= "||" > <input id= "next" type= "button" value= ">>" > <input id= "loop" type= "button" value= "@" > </div> <div id= "faketail" class = "tailC" ></div> <--/body> <--/html> |
사용상 모든 브라우저를 지원하지만 mp3 파일등의 음원은 직접 구해서
플레이어가 있는 디렉터리에 함께 넣어주고 브라우저에서 주소를 열면 된다.
문의는 댓글로.
'Develop' 카테고리의 다른 글
구너갤러리 15.11.2 (0) | 2015.11.16 |
---|---|
구너갤러리 15.11 (0) | 2015.11.04 |
구너 플레이어 15.11 (1) | 2015.11.04 |
베지에 곡선 (Bezier Curve) (1) | 2015.09.04 |
PHP html5 css3 음악 플레이어. (0) | 2014.10.18 |