Mais conteúdo relacionado
Semelhante a WPD-Fes #3 2015年のサバイバル学習術 Web開発技術の税引後利益 を最大化しよう! (20)
WPD-Fes #3 2015年のサバイバル学習術 Web開発技術の税引後利益 を最大化しよう!
- 1. 1 © Takahashi Fumiki
2015年のサバイバル学習術
Web開発技術の税引後利益
を最大化しよう!
WP-D Fes #03
- 2. 2 © Takahashi Fumiki
高橋 文樹
2001年、幻冬舎主催の文学賞を受賞し、大
学在学中に作家デビュー。その後、長い冬
の時代を過ごし、2007年に「自身の作品を
Webで発表する技術を身につける」を目標
にWeb業界に転職。
2010年に独立して株式会社破滅派を設立。趣味は家づくり。
- 4. 4 © Takahashi Fumiki
なぜGrunt?
• Sassコンパイル, JS圧縮はCodekitで満足していた
• プラグインなどOSSを配布する以上、有償ツール
じゃない方がいいかなと思った
• 共同作業でもCodekit買わない人が多かった
- 7. 7 © Takahashi Fumiki
その他の情報によると……
• Gruntはかれこれ1年ぐらい新規開発が止まっている
らしい
• Gulpの方が簡潔に書けて、速度も多少早いらしい
• GulpはGoogleのWeb Starter Kitにも採用された
https://developers.google.com/web/starter-kit/
- 11. 11 © Takahashi Fumiki
収支決算
出資 資産
Grunt学習時間 Gruntの知識
Grunt固有の知識 Grunt終了のお知らせ
タスクランナーの知識
Gulp学習時間 Gulpの知識
Gulp学習時間 Gulp固有の知識
税引後利益
これを最大化しよう!
どんなツールも
いつかなくなる
- 13. 13 © Takahashi Fumiki
2008年、Flashはすごかった (1)
• はじめて就職した会社で、「コーダー」「デザイナー」と
「Flasher」の間には明確な給与の差があった
• FlashできないWebデザイナーの給料は額面30万超えないと言
われた
• LoftworkのサイトにFlash+CMS連携で1500万と書いてあった
- 14. 14 © Takahashi Fumiki
2008年、Flashはすごかった (2)
• ブラウザへのインストール率も95%ぐらいで、もっとも普
及した実行環境だった
• JavascriptでFlashと同等の表現をするのは至難の業だった
• ActionScript 3.0が出た頃で、「まともなプログラミング言
語になった」と言われていた
- 15. 15 © Takahashi Fumiki
2008年、Flashはすごかった (3)
• TextLayoutFrameworkというプロジェクトがすごかった
• AdobeならではInDesign並の組版(縦書き・フォント・
禁則処理・縦中横)
• 僕は小説家なので、Webで書籍と同じように小説を読め
るようにしたかった
- 16. 16 © Takahashi Fumiki
Flash累計学習時間
0
1500
3000
4500
6000
2007年 2008年 2009年 2010年 2011年 2012年 2013年
- 18. 18 © Takahashi Fumiki
完成した結果
• WordPressでコンテンツを入稿すると、Flashで縦書き表示。フォントもヒラギノ
明朝でアンチエイリアスも効いており、大変美しい。ページめくり。
• 超頑張ってルビ・自動縦中横・自動行頭下げも実現した。
• SEO対策もばっちり。Flashは一度書き出されたHTMLをXMLとして再解釈し、レ
ンダリングするからボットでも安心。
• コピペ対策もばっちりで、お気に入りの箇所をブックマークできた。
• ページ内検索で、検索ワードが作品内に何個登場するかも実現できた。
- 27. 27 © Takahashi Fumiki
失ったもの
• Flash Builder(2回ぐらいアップデートしたので9万ちょい?)
• Flash固有の知識に費やした学習時間
• Flashのライブラリについての知識
• MXMLなどのタグ名
• Font埋め込みに関する知識
- 28. 28 © Takahashi Fumiki
得たもの
• 暗号化、フォント埋め込みなど、それまで普通にWebサイトを作っているだけでは必要がなかった知識
• 鬼の正規表現
• ライブラリを使うのではなく、作るとはどういうことか
• Nightly Buildを利用することにまつわる苦労。最先端は辛いな! いやー、つれーわ!
• フロントエンドとバックエンドの連携
• 非同期処理についての基本知識(フォント5M、ルビ書き出しのためのレンダリング規則)
• 文字コードに関する深い知識
• タレントを探す嗅覚(クリエイターズクリエイター)
- 30. 30 © Takahashi Fumiki
たとえば、正規表現
public
static
function
tcy(xml:XML,
textToTcy:String):XML{
//すべてのノードにアクセス
for(var
idx:String
in
xml..*){
//テキストノードにのみ処理を行う
if(xml..*[idx].nodeKind()
==
"text"){
var
replacedTcy:String
=
xml..*[idx].toString();
//
FIXME:
とりあえず1∼2文字の場合だけ変換
if(replacedTcy.match(/^[a-‐zA-‐Z0-‐9!?]{1,2}$/)){
replacedTcy
=
replacedTcy.replace(/([a-‐zA-‐Z0-‐9!?]{1,2})/,
"<flow:tcy>$1</flow:tcy>");
}else{
//中間を修正
replacedTcy
=
replacedTcy.replace(/([^a-‐zA-‐Z0-‐9,
.&!?'"
-‐])([a-‐zA-‐Z0-‐9!?]{1,2})([^a-‐zA-‐
Z0-‐9!?,
.&'"
-‐])/g,"$1<flow:tcy>$2</flow:tcy>$3");
//FIXME:
一字挟んでtcyがあった場合(22∼23など。行頭・行末はうまく行く)
replacedTcy
=
replacedTcy.replace(/(</flow:tcy>[^a-‐zA-‐Z0-‐9!?,
.&'"
-‐])([a-‐zA-‐Z0-‐9!?]{1,2})([^a-‐
zA-‐Z0-‐9!?,
.&'"
-‐])/g,
"$1<flow:tcy>$2</flow:tcy>$3");
//先頭だけを修正
replacedTcy
=
replacedTcy.replace(/(^[a-‐zA-‐Z0-‐9!?]{1,2})([^a-‐zA-‐Z0-‐9,
.&!?'"])/,"<flow:tcy>$1</
flow:tcy>$2");
//最後だけを修正
replacedTcy
=
replacedTcy.replace(/([^a-‐zA-‐Z0-‐9,
.&!?'"])([a-‐zA-‐Z0-‐9!?]{1,2})$/,"$1<flow:tcy>$2</
flow:tcy>");
}
//横に寝てしまう文字を起こす
//参考情報
http://forums.adobe.com/thread/646184?tstart=0
//FIXME:
UTF-‐8でEast
Asian
Widthがambiguousであるかどうかを知るにはどうしたら?
//tcyが連続になっていると横につながってしまうので、spanに修正
var
regStr:String
=
"▲△▼▽☆★*①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅨⅩⅰⅱⅲⅳⅴⅵⅶⅷαβγΩ‰
℃Å♪♩♫♬";
if(textToTcy
!=
"")
regStr
+=
textToTcy;
var
reg:RegExp
=
new
RegExp("(["
+
regStr
+
"])",
"g");
replacedTcy
=
replacedTcy.replace(reg,"<flow:span
textRotation="rotate270">$1</flow:span>");
replacedTcy
=
replacedTcy.replace(/(°F)/g,
"<flow:span
textRotation="rotate270">$1</flow:span>");
//元のノードに入れ直す
xml..*[idx]
=
replacedTcy;
}
}
return
new
XML(xml.toXMLString().replace(/<(/?)flow:([^&]*?)>/g,"<$1flow:$2>"));
}
- 31. 31 © Takahashi Fumiki
たとえば、暗号化
package
com.hametuha.cypher
{
import
flash.utils.ByteArray;
import
com.hurlant.crypto.symmetric.*;
import
com.hurlant.crypto.prng.Random;
import
com.hurlant.crypto.Crypto;
import
com.hurlant.crypto.hash.*;
import
com.hurlant.util.Hex;
import
com.hurlant.util.Base64;
public
class
Crypto
{
/**
*
暗号を解読して返す
*
@param
data
ByteArray
*
@return
String
*/
public
static
function
decrypt(data:ByteArray,
pswd:String):String
{
var
pad:IPad
=
new
NullPad();
var
cipher:ICipher
=
com.hurlant.crypto.Crypto.getCipher("blowfish-‐
ecb",Hex.toArray(Hex.fromString(pswd)),pad);
pad.setBlockSize(cipher.getBlockSize());
if
(cipher
is
IVMode)
{
var
ivmode:IVMode
=
cipher
as
IVMode;
ivmode.IV
=
Hex.toArray("");
}
cipher.decrypt(data);
data.position
=
0;
return
data.readMultiByte(data.length,
"utf-‐8");
}
}
}
- 32. 32 © Takahashi Fumiki
たとえば、アニメーション
package
com.hametuha.utils.Math
{
import
flash.geom.Point;
public
class
Dimension
{
public
function
Dimension()
{
}
/**
*
内容物が縦横比を保ったままコンテナの中に収まるようサイズを取得する
*
@param
content
内容物の幅と高さ
*
@param
container
コンテナの幅と高さ
*
@return
Point 新しい内容物の幅と高さ
*/
public
static
function
rectangleMaxLimit(content:Point,
container:Point):Point
{
var
adjustedContent:Point
=
new
Point();
//内容物の方が縦長の場合、高さで制限する
if(isHigher(content,
container)){
if(content.y
>
container.y){
adjustedContent.y
=
container.y;
adjustedContent.x
=
content.x
/
content.y
*
container.y;
}else{
adjustedContent.x
=
content.x;
adjustedContent.y
=
content.y;
}
}
//内容物の方が横長の場合、幅で制限する
else{
if(content.x
>
container.x){
adjustedContent.x
=
container.x;
adjustedContent.y
=
content.y
/
content.x
*
container.x;
}else{
adjustedContent.y
=
content.y;
adjustedContent.x
=
content.x;
}
}
return
adjustedContent;
}
/**
*
オブジェクトがどんな形をしているかを返す
*
@param
content
形を知りたいオブジェクト
*
@return
String
"square",
"high",
"broad"のいずれか
*/
public
static
function
getShape(content:Point):String
{
var
shape:String;
if(content.x
==
content.y)
shape
=
"square";
else
if(content.x
<
content.y)
shape
=
"high";
else
shape
=
"broad";
return
shape;
}
/**
*
2つのオブジェクトを比較して、1つ目のオブジェクトの方が縦長だったらtrue
*
@param
sub
比較したいオブジェクト
*
@param
obj
比較対象のオブジェクト
*
@return
Boolean
*/
private
static
function
isHigher(sub:Point,
obj:Point):Boolean
{
if(sub.y
/
sub.x
>
obj.y
/
obj.x)
return
true;
else
return
false;
}
}
}
package
com.hametuha.book.animation
{
import
com.hametuha.book.events.PagenatorEvent;
import
flash.display.Sprite;
import
flash.events.Event;
import
flash.events.EventDispatcher;
import
flash.events.IEventDispatcher;
import
flash.events.TimerEvent;
import
flash.geom.Point;
import
flash.utils.Timer;
public
class
PagenatorFlip
extends
EventDispatcher
{
private
var
originalPoint:Point
=
new
Point(0,0);
private
var
leftPoint:Point
=
new
Point(-‐100,0);
private
var
rightPoint:Point
=
new
Point(100,
0);
private
var
accel:Number
=
1.5;
private
var
timer:Timer;
private
var
interval:int
=
33;
private
var
vanishSpeed:Number;
private
var
showSpeed:Number;
private
var
buffer:Number
=
5;
private
var
from:Sprite;
private
var
to:Sprite;
private
var
tategaki:Boolean;
private
var
showPoint:Point;
private
var
vanishPoint:Point;
public
function
next(_from:Sprite,
_to:Sprite,
_tategaki:Boolean):void
{
from
=
_from;
to
=
_to;
tategaki
=
_tategaki;
//消失点と表示点を設定
showPoint
=
(tategaki)
?
leftPoint
:
rightPoint;
vanishPoint
=
(tategaki)
?
rightPoint
:
leftPoint;
pageMove();
}
public
function
previous(_from:Sprite,
_to:Sprite,
_tategaki:Boolean):void
{
from
=
_from;
to
=
_to;
tategaki
=
_tategaki;
//消失点と表示点を設定
showPoint
=
(tategaki)
?
rightPoint
:
leftPoint;
vanishPoint
=
(tategaki)
?
leftPoint
:
rightPoint;
pageMove();
}
private
function
pageMove():void
{
//表示設定
from.alpha
=
1;
to.alpha
=
0;
to.visible
=
from.visible
=
true;
setPoint(from,
originalPoint);
setPoint(to,
showPoint);
//スピードの設定
vanishSpeed
=
(vanishPoint.x
-‐
originalPoint.x)
/
10;
timer
=
new
Timer(interval);
timer.addEventListener(TimerEvent.TIMER,vanishHandler);
timer.start();
dispatchEvent(new
Event(PagenatorEvent.PAGENATION_START));
}
private
function
vanishHandler(event:TimerEvent):void
{
//アニメーションが終了していたら
if(isAnimationFinish(from,
vanishPoint,
vanishSpeed)){
//表示を元に戻す
from.visible
=
false;
from.alpha
=
0;
setPoint(from,
originalPoint);
//速度を設定
showSpeed
=
vanishSpeed;
//リスナーを削除
timer.removeEventListener(TimerEvent.TIMER,vanishHandler);
timer.addEventListener(TimerEvent.TIMER,showHandler);
}
//アニメーションを実行
else{
vanishSpeed
*=
accel;
from.x
+=
vanishSpeed;
from.alpha
/=
accel;
dispatchEvent(new
Event(PagenatorEvent.PAGENATION_EXECUTING));
}
}
private
function
showHandler(event:TimerEvent):void
{
//アニメーションが終了していたら、イベントを発行
if(isAnimationFinish(to,
originalPoint,
showSpeed)){
//表示を元に戻す
to.visible
=
true;
to.alpha
=
1;
setPoint(to,
originalPoint);
//リスナーを削除
timer.removeEventListener(TimerEvent.TIMER,
showHandler);
timer.stop();
timer
=
null;
dispatchEvent(new
Event(PagenatorEvent.PAGENATION_ENDS));
}
//アニメーションを実行
else{
showSpeed
/=
accel;
to.x
+=
showSpeed;
if(to.alpha
==
0)
to.alpha
+=
.2;
else
- 33. 33 © Takahashi Fumiki
たとえば、目標とするクリエイターの発見
"新藤愛大(Yoshihiro Shindo)――19
歳という若さでありながら、国内でも屈
指のActionScripterとして活躍する彼は、
フリーランスとしてFlash/ActionScript
にその身をささげている。"
http://www.itmedia.co.jp/enterprise/
articles/0805/12/news007.html
- 34. 34 © Takahashi Fumiki
収支決算
出資 資産
flash学習時間 flashの知識
flash固有の知識 flash終了のお知らせ
GUI設計の知識
Xの学習時間 Xに固有の知識
税引後利益
ものすごくたくさんの
知識=資産
Xが何かはまだ
わからない
- 35. 35 © Takahashi Fumiki
スキル習得の秘訣
• 実戦投入する
• 情報の荒野まで邁進する
• 学習曲線の坂を登ることを厭わない
- 36. 36 © Takahashi Fumiki
1. 実戦投入
それとも
お前何十年も修行して
達人にでもなるのを待ってから
戦場に出るつもりか?
気の長なげェ話だな
ベルセルク 第24巻
- 37. 37 © Takahashi Fumiki
2. 情報の荒野まで邁進する
https://forums.adobe.com/thread/646184
- 39. 39 © Takahashi Fumiki
上り終えた梯子は
捨て去られねばならない
ルートヴィヒ・ウィトゲンシュタイン『論理哲学論考』より