HTML4에서는 플래쉬, 실버라이트 등의 추가 설치가 이뤄진 후에야 동영상 재생이 가능하지만, HTML5에서는 웹브라우저 자체적으로 동영상 태그를 통해 재생이 가능하다. Youtube에서 아래의 태그 덕분에 플래쉬를 배제한 서비스 개발이 가능하게 된 것이다. 더불어 아래 <audio>, <video>, <canvas>, <svg>는 스크립트와 결합하거나, 두 태그들을 적절히 함께 활용하여 새로운 시각화를 나타낼 수 있다.
[정말 나의 게으름으로 글 하나가 또 묻혀져 있었다.]
[지난 번의 1번글을 비슷한 시기에 쓰고, 연달아 정리하려고 했는데]
[또 다시, 뒤 늦게 글을 올리게 되었다. 미안하고 죄송하고, 부끄럽다.]
트위터의 API를 사용하기 위해서 필요한 내용들을 간략하게 정리해 봤다. 세부 내용들과 참고해야할 항목들도 정리했는데, 이전 기억을 살리기 보다는 FQA를 이용해서 접근하였다. 따라서 필요한 내용들은 Twitter의 개발자 가이드와 웹 사이트를 이용해서 확인 가능하다.
간략하게 정리하였지만, 기본적인 API들에 대한 지원은 Twitter에서 라기보다는 이를 이용한 Wraper 클래스들은 우리의 선배 또는 휼륭한 다른 개발자 들이 이미 개발하여 놓았다. 이를 잘 활용하는 것은 또 다른 문제이고, 다른 영역이라 생각하지만, 자신에 맞는 언어와 라이브러리를 잘 찾아 쓰는 것은 시행착오와 시간을 줄여주는 활동이다.
웹사이트에는 Web site를 위해서 Twitter에서 제공되는 기능들도 설명되어져 있다. (나의 관심사와는 좀 거리가 있어서, 생략...)
메가플러그(http://www.megaplug.net/) 유료사이트입니다. 무제한트래픽사이트이고 1G 1개월사용금액이 만원입니다.(부가세, 초기세팅비제외)용량별 기간별 구입이 가능합니다. 자체적으로 jwplayer태그를 제공하기 때문에 소스만 복사해서 가져오시면됩니다. 본인도 사용중인 서비스입니다.
미디어포스팅(http://www.mediaposting.co.kr) 단일파일 50Mb에 총용량은 무제한으로 쓸 수 있는 유료사이트입니다. 총용량과 트래픽은 무제한이고 1개월사용 금액이 만원(부가세제외)정도됩니다. 자체적으로 jwplayer태그를 제공하기 때문에 소스만 복사해서 가져오시면됩니다.
이글루스(http://egloos.com/) 이곳은 블로그 사이트인데.. 5Mb씩 업로드가 가능합니다. jwplayer태그를 만들어주어야 재생가능합니다.
쉐어팩토리(http://www.sharefactory.net) 아직 무료베타시험중인 사이트입니다. 3차베타진행중인데 3월15일까지라네요. 가입 후 24시간이내에 인증을 해주면 사용이 가능하고. 단일파일 80Mb에 총 10기가의 용량을 제공합니다. 자체적으로 jwplayer태그를 제공하기 때문에 소스만 복사해서 가져오시면됩니다.
제대로된 스트리밍 사이트를 이용하려면 유료서비스가 좋습니다.
flv나 mp4경우 플래시as3.0을 사용해서 불러와 재생시키는 방법이 있고 jwplayer(웹플레이어)로 재생시키는 방법이 있습니다.
이 예문은 http://www.dreamwiz.com 페이지를 가로 500픽셀, 높이 300 픽셀의 크기로 왼족위 모서리에 붙게 팝업창으로 열어줍니다. 두 번째 인자인 "dreamwiz" 는 뭐냐구요? 이 부분은 팝업창의 이름을 말하는 것으로 프레임 문서에서 타겟(target) 처럼 사용할 수 있습니다.. 즉, <a href="xxx.html" target="dreamwiz">열기</a> 처럼 사용하게 되면, 현재 드림위즈 홈페이지가 열려있는 팝업창에 xxx.html 문서가 열리게 되는 것이랍니다. 이 두 번째 인자에 아무것도 입력하지 않으려면 그냥 "" 만 표시 해 줍니다. (예) : window.open("http://www.dreamwiz.com", "", "옵션들")
세 번째 인자에는 옵션들을 설정 합니다. 이곳에서 사용할 수 있는 옵션에는 아래와 같은 것들이 있습니다
menubar
yes/no, 1/0
메뉴바를 보여주거나 숨깁니다
toolbar
yes/no, 1/0
도구막대를 보여주거나 숨깁니다
directories
yes/no, 1/0
디렉토리바를 보여주거나 숨깁니다
scrollbars
yes/no, 1/0
스크롤바를 보여주거나 숨깁니다
status
yes/no, 1/0
상태표시줄을 보여주거나 숨깁니다
location
yes/no, 1/0
주소표시줄을 보여주거나 숨깁니다
width
픽셀
팝업 윈도우의 가로크기를 지정합니다
height
픽셀
팝업 윈도우의 높이를 지정합니다
left
픽셀
팝업 윈도우의 x축 위치를 지정합니다
top
픽셀
팝업 윈도우의 y축 위치를 지정합니다
resizable
yes/no 1/0
팝업윈도우의 크기를 사용자가 임의로 수정할 수 있는지 여부를 지정합니다
fullscreen
전체화면 모드로 열어줍니다
channelmode
채널모드 창으로 열어줍니다
옵션인자를 지정하지 않으면 현재 창의 모양과 같은 형태로 팝업윈도우가 열리게 되고, 어느 한가지 옵션만 지정하면 나머지는 모두 디폴트 값으로 no 가 설정 됩니다.
버튼을 클릭하면 아무런 옵션이 없는 팝업 윈도우가 열리게 하는 코드는 아래와 같습니다
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
위에서 보듯이 옵션을 사용하지 않으면 <a href="xxx.html" target="_blank">열기</a> 처럼 태그를 사용한 것과 같은 효과를 줍니다. 이 옵션 인자는 지정하지 않아도 되지만, 두 번재 인자인 name 은 사용하지 않더라도 반드시 "" 으로 표시해 주어야 한다는 것은 명심하기 바랍니다.
그럼, 이번에는 몇가지 옵션만 선별적으로 주는 예를 보겠습니다
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
구축환경은 Flash Builder4 Burrito 이며 , 아마 Flash Builder 4 에서도 되지 싶다. ( Ant적용은 FB4 부터 되지 않았나 기억하기에.. )
지돌스타님의 포스팅을 기본으로 삽질을 했다. ( 참고 URL : http://blog.jidolstar.com/505 ) [ Action Script Project 를 생성한다.]
[ 첨부된 파일의 src 폴더와 build 폴더를 해당 프로젝트에 복사한다. ]
[ 첨부된 모습이다. ]
[ 간단하게 네모를 만든 소스. 컴파일 될 테스트 소스이다.]
[build] 폴더에 build.properties 파일을 연다.
[ 포커싱된 영역이 ftp 업로드될 설정 부분이다. 해당 부분에 ftp 접속 정보와 업로드될 path를 설정한다. ]
이제 가장 포인트가 될. ftp 업로드를 하기 위한 라이브러리를 등록한다.
[메뉴] - [Window] - [preferences] - [Ant] - [Runtime]
에서 Classpath 탭매뉴에 Ant Home Entries 부분에 jar 파일을 등록한다.
[ window - preferences 클릭 ]
[ 파일 첨부한 build 폴더에 libs 폴더에 commons-net-1.4.1.jar 파일을 라이브러리로 등록한다. FTP 업로드를 위한 라이브러리로 이해하면 되겠다.]
Ant를 편히 사용하기 위해 패널을 연다.
[ window - Show View - Other 클릭 ]
[ Ant 폴더에 Ant 패널 클릭 ]
Ant 패널에서 Ant를 통해 build 할 설정 파일을 불러온다.
[ Ant 패널에서 우클릭후 Add Buildfiles 클릭 ]
build.infomation.xml 파일은 지돌스타님 블로그에서 가져온 build.xml 파일이며 여러가지 설정이 담겨있다.
간단히 최소화 하여 , 컴파일 & ftp upload 만 남겨둔 파일이 build.xml 파일이다.
build.information.xml 파일은 참고만 하고 , build.xml 파일을 가지고 컴파일 및 업로드를 한다.
[ build.xml 파일을 클릭하여 등록한다. ]
[ 등록되어 올라온 모습 ]
현재 상태에서는 지돌스타님이 제공해 주신 샘플 파일이 그대로 적용되어진 상태이다.
즉 , 프로젝트가 생성되면서 생겨진 defulat 소스인 Main.as 파일은 적용이 안되고 , 파일을 첨부한 src 폴더안의 소스들만 적용 되어진 상태이다.
이제 Main.as 파일을 적용해보자.
build.xml 파일을 연다.
그림안의 설명을 보면 알수 있듯이 ,
<target name="compile all" depends="compile MyWidgets, compile widget1, compile widget2, compile widget3"/>
을 실행하면 depends 에 걸려 있는(?) 실행 커멘드 들이 같이 일괄적으로 실행된다.
compile all 부분에 위 compile MyApp 을 추가하여 준다. <target name="compile all" depends="compile MyWidgets, compile widget1, compile widget2, compile widget3, compile MyApp"/>
ftp 부분의 노드는 build.properties 파일에 설정한 값을 토대로 업로드를 하는 일을 하므로 건드리지 않는다.
자. 이제 다 끝났다.
기존 첨부파일은 MyWidgets .as , Widgets1.as , Widgets2.as , Widgets3.as 파일을 가지고 각각 컴파일을 하여 bin 폴더에 해당 파일명.swf 파일로 컴파일이 된다.
여기서는 , 직접 우리가 컴파일 하고자 하는 Main.as 파일노드도 추가하고 , 전부 컴파일 되는 커멘드 노드부분에 해당 Main.as 파일 컴파일도 되도록 설정해 주었다.
ftp 업로드 부분에는 해당 폴더의 모든 *.swf 파일을 다 업로드 하므로 같이 업로드 된다.
Ant 를 실행하여 bin 폴더 안에 .swf 파일이 컴파일된 모습과 ftp 에 업로드 된 모습을 확인해 보겠다.
[ FTP 설정한 노드를 확인해 보면 알겠지만 , 전부 컴파일 한후 ftp에 업로드 한다. ]
[ Ant 실행전 폴더모습 ]
[ Ant 실행후 업로드 된 모습 ]
[ Ant 실행. Console 창을 보면 알수 있겠지만 5번의 컴파일과 ftp로 5 files sent 라는 문구를 확인할수 있다. 우측에 bin 폴더에 컴파일 되어진 모습도 볼수 있다.]
Ant로 더 유용한 무언가를 할수 있는지는 추후 사용해 보면서 차차 업데이트 해 나가야 겠다.
우선적으로 여러 파일의 swf 산출물이 연결된 프로젝트에 웹 프로젝트로써 서버에 업로드를 해 주어야 하는 일괄적인 작업들을 Ant 란 놈으로 번거로움을 덜어 줄수 있도록 간단히 구축해 보았다.
package org.papervision3d.core.geom
{
/**
* <p>
* The Lines object is a DisplayObject3D that is designed to contain and handle the rendering of
* Line3D objects. A Line3D is defined by two 3D vertices; one for each end. A line's start and end
* vertices are converted into 2D space and rendered using the Flash drawing API lineTo method.
*
* Line3D can also render curves; add a control vertex using the Line3D.addControlVertex(...) method.
* The line's control vertex is then converted into 2D space and rendered using the Flash drawing API
* curveTo method.
*
* The line's appearance is defined by its LineMaterial.
*
* </p>
*
* <p>
* Example:
* </p>
* <pre><code>
*
* //This example creates a Lines3D DisplayObject3D and adds 100 lines into it.
*
* var numLines : int = 100;
*
* var lines3D : Lines3D = new Lines3D();
* var lineMaterial : LineMaterial = new LineMaterial(0xff0000, 0.8);
* var lineWeight : Number = 5;
*
* for(var i : int = 0; i<numLines; i++)
* {
* var startVertex : Vertex3D = new Vertex3D(Math.random()*200, Math.random()*200, Math.random()*200);
* var endVertex : Vertex3D = new Vertex3D(Math.random()*200, Math.random()*200, Math.random()*200);
*
* var line : Line3D = new Line3D(lines3D, lineMaterial, lineWeight, startVertex, endVertex);
*
* lines3D.addLine(line);
*
* }
* scene.addChild(lines3D);
*
* </code></pre>
* </p>
*
* <p>
* See also : LineMaterial
* </p>
*
* @Author Ralph Hauwert
* @Author Seb Lee-Delisle
* @Author Alan Owen
* */
import org.papervision3d.core.geom.renderables.Line3D;
import org.papervision3d.core.geom.renderables.Vertex3D;
import org.papervision3d.core.log.PaperLogger;
import org.papervision3d.core.render.command.RenderLine;
import org.papervision3d.core.render.data.RenderSessionData;
import org.papervision3d.core.render.draw.ILineDrawer;
import org.papervision3d.materials.special.LineMaterial;
import org.papervision3d.objects.DisplayObject3D;
public class Lines3D extends Vertices3D
{
public var lines:Array;
private var _material:ILineDrawer;
/**
* @param material The default material for this Lines3D. If ommitted then the default
* LineMaterial3D is used.
* @param name An identifier for this Lines object.
*/
public function Lines3D(material:LineMaterial = null, name:String=null)
{
super(null, name);
if(!material) this.material = new LineMaterial();
else this.material = material;
init();
}
private function init():void
{
this.lines = new Array();
}
/**
* Converts 3D vertices into 2D space, to prepare for rendering onto the stage.
*
* @param parent The parent DisplayObject3D
* @param renderSessionData The renderSessionData object for this render cycle.
*
*/
public override function project( parent :DisplayObject3D, renderSessionData:RenderSessionData ):Number
{
// Vertices
super.project( parent, renderSessionData );
var line3D:Line3D;
var screenZ:Number;
var rc:RenderLine;
for each(line3D in lines)
{
if(renderSessionData.viewPort.lineCuller.testLine(line3D))
{
rc = line3D.renderCommand;
rc.renderer = line3D.material;
rc.size = line3D.size;
screenZ += rc.screenZ = (line3D.v0.vertex3DInstance.z + line3D.v1.vertex3DInstance.z)/2;
rc.v0 = line3D.v0.vertex3DInstance;
rc.v1 = line3D.v1.vertex3DInstance;
renderSessionData.renderer.addToRenderList(rc);
}
}
return screenZ/(lines.length+1);
}
/**
* Adds a Line3D object to this Lines3D container.
* @param line The Line3D object to add.
*
*/
public function addLine(line:Line3D):void
{
lines.push(line);
line.instance = this;
if(geometry.vertices.indexOf(line.v0) == -1)
{
geometry.vertices.push(line.v0);
}
if(geometry.vertices.indexOf(line.v1) == -1)
{
geometry.vertices.push(line.v1);
}
if(line.cV){
if(geometry.vertices.indexOf(line.cV) == -1)
{
geometry.vertices.push(line.cV);
}
}
}
/**
* Creates a new line from the parameters passed and adds it.
* @param size The weight of the line.
* @param x0 The line's start x position.
* @param y0 The line's start y position.
* @param z0 The line's start z position.
* @param x1 The line's end x position.
* @param y1 The line's end y position.
* @param z1 The line's end z position.
* @return The line just created.
*
*/
public function addNewLine(size:Number, x0:Number, y0:Number, z0:Number, x1:Number, y1:Number, z1:Number) : Line3D
{
var line:Line3D = new Line3D(this, material as LineMaterial, size, new Vertex3D(x0,y0,z0), new Vertex3D(x1,y1,z1));
addLine(line);
return line;
}
/**
* This is identical to addNewLine, except it breaks up the line into several shorter line segments
* that together make up the full line. This would be useful for improved z-depth sorting.
*
* @param size The weight of the line.
* @param segments The number of segments to break up the line into
* @param x0 The line's start x position.
* @param y0 The line's start y position.
* @param z0 The line's start z position.
* @param x1 The line's end x position.
* @param y1 The line's end y position.
* @param z1 The line's end z position.
* @return An array of the lines just created.
*
*/
public function addNewSegmentedLine(size:Number, segments:Number, x0:Number, y0:Number, z0:Number, x1:Number, y1:Number, z1:Number) : Array
{
//Do line interpolation, and add a bunch of segments for it.
var xStep:Number = (x1-x0)/segments;
var yStep:Number = (y1-y0)/segments;
var zStep:Number = (z1-z0)/segments;
var newLines : Array = new Array;
var line:Line3D;
var pv:Vertex3D = new Vertex3D(x0,y0,z0);
var nv:Vertex3D;
for(var n:Number = 0; n<=segments; n++){
nv = new Vertex3D(x0 + xStep*n, y0+yStep*n, z0+zStep*n);
line = new Line3D(this, material as LineMaterial, size, pv, nv);
addLine(line);
newLines.push(line);
pv = nv;
}
return newLines;
}
/**
* Removes a line.
* @param line The line to remove.
*
*/
public function removeLine(line:Line3D) : void
{
var lineindex : int = lines.indexOf(line);
if(lineindex>-1)
{
lines.splice(lineindex,1);
}
else
{
PaperLogger.warning("Papervision3D Lines3D.removeLine : WARNING removal of non-existant line attempted. ");
}
}
/**
* Removes all the lines.
*
*/
public function removeAllLines():void
{
while ( lines.length > 0 )
{
removeLine( lines[0] ) ;
}
}
}
}