Archive for the ‘Programming’ Category

jQuery_logo

マウスオーバーで画像を切替える方法はいくつかあります。
大別してCSSを使ってやる方法とJavascriptを使ってやるというのが主流かと思います。

CSSでやる場合、ボタンの切り替えはどうしても瞬間的に切り替わるものになってしまいます。
(ふわっと切り替える方法もあるのかな・・・)

でもやっぱり僕的には「ふわり」と切り替わるエフェクトの方が好みなんです。
そこで今回はJavascriptを使ってやる方法を選択してみました。

Javascriptを使って簡単にアニメーションを実装といえばもちろんjQueryさんの出番です。

と言う事で、HTMLのHEAD内にまずはjQueryをインポートしてしまいましょう。

<head>
	<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
	<script type="text/javascript" src="./scripts/smart-crossfade.js"></script>
</head>

2行目googleのライブラリからjQueryを引っ張ってきてインポート。
3行目でインポートしてる”smart-crossfade.js”が今回の肝にあたるライブラリです。

こいつを使うとどうなるのか。

こちらにサンプルを用意しました。
smart-crossfade demo

このとおりふわりと画像が切り替わるのですね!

使用するには色違いの画像を2枚用意して、それぞれのファイル名の末尾を”_on”,”_off”としてあげます。
“button_off.jpg”,”button_on.jpg”といった具合にですね。

_offをつけている方はマウスが画像から外れている時に表示する画像。
_onをつけている方がマウスオーバーした時に表示する画像となっています。

後はその画像をaタグで囲ってあげると自動的に、ふわっと画像が切り替わるマウスオーバーエフェクトが実装されています。

以下実装ソースです。

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>smart-crossfade demo</title>
<script src="js/jquery-1.11.3.min.js"></script>
<script src="js/smart-crossfade.js"></script>
</head>
<body>
<a href="#"><img src="img/facebook_off.png"></a>
<a href="#"><img src="img/twitter_off.png"></a>
<a href="#"><img src="img/google_off.png"></a>
<a href="#"><img src="img/rss_off.png"></a>
</body>
</html>

ライブラリのソースも一応アップしときます。

function smartRollover() {
	if(document.getElementsByTagName) {
		var images = document.getElementsByTagName("img");

		for(var i=0; i < images.length; i++) {
			if(images[i].getAttribute("src").match("_off."))
			{
				images[i].onmouseover = function() {
					this.setAttribute("src", this.getAttribute("src").replace("_off.", "_on."));
				}
				images[i].onmouseout = function() {
					this.setAttribute("src", this.getAttribute("src").replace("_on.", "_off."));
				}
			}
		}
	}
}

if(window.addEventListener) {
	window.addEventListener("load", smartRollover, false);
}
else if(window.attachEvent) {
	window.attachEvent("onload", smartRollover);
}


// cross fade

new function(){
  function setRollOver2(){
    if(!document.images){return;}
    var imgs = document.images;
    var insert = [];
    for(var i=0;i<imgs.length;i++){
      var splitname = imgs[i].src.split('_off.');
      if((splitname[1])&&(imgs[i].parentNode.tagName=='A')){
        var rolloverImg = document.createElement('img');
        rolloverImg.src = splitname[0]+'_on.'+splitname[1];
        var alpha = 0;
        rolloverImg.currentAlpha = alpha;
        rolloverImg.style.opacity = alpha/100;
        rolloverImg.style.filter = 'alpha(opacity='+alpha+')';
        rolloverImg.style.position = 'absolute';


        addEvent(rolloverImg,'mouseover',function(){setFader(this,100);});
        addEvent(rolloverImg,'mouseout',function(){setFader(this,0);});

        insert[insert.length] = {position:imgs[i],element:rolloverImg};
      }
    }
    for(var i=0;i<insert.length;i++){
      var parent = insert[i].position.parentNode;
      parent.insertBefore(insert[i].element,insert[i].position);
    }
  }


  function setFader(targetObj,targetAlpha){
    targetObj.targetAlpha = targetAlpha;
    if(targetObj.currentAlpha==undefined){
      targetObj.currentAlpha = 100;
    }
    if(targetObj.currentAlpha==targetObj.targetAlpha){
      return;
    }
    if(!targetObj.fading){
      if(!targetObj.fader){
        targetObj.fader = fader;
      }
      targetObj.fading = true;
      targetObj.fader();
    }
  }

  function fader(){
    this.currentAlpha += (this.targetAlpha - this.currentAlpha)*0.2;
    if(Math.abs(this.currentAlpha-this.targetAlpha)<1){
      this.currentAlpha = this.targetAlpha;
      this.fading = false;
    }
    var alpha = parseInt(this.currentAlpha);
    this.style.opacity = alpha/100;
    this.style.filter = 'alpha(opacity='+alpha+')';
    if(this.fading){
      var scope = this;
      setTimeout(function(){fader.apply(scope)},30);
    }
  }

  function addEvent(eventTarget, eventName, func){
    if(eventTarget.addEventListener){
      eventTarget.addEventListener(eventName, func, false);
    }else if(window.attachEvent){
      // IE
      eventTarget.attachEvent('on'+eventName, function(){func.apply(eventTarget);});
    }
  }

  addEvent(window,'load',setRollOver2);

}

ちなみにフェードインのスピードは87行目
setTimeout(function(){fader.apply(scope)},30);
の30という数字をいじる事で変更する事が可能です。

と言う事で、僕の知る限り最も簡単なマウスオーバーでのハイクオリティな画像切替方法でした。

Today's latte, Summer is the season of Python!

Amazonで欲しい物がありました。
その商品は値段の乱高下激しく、ある時は6,000円台、またある時は4,000円台の事もある商品でした。

そこで僕は底値を探るべく、値段が下がった事を知らせてくれるシステムを作ろうと考えました。

という事で今回作ったシステムの概要を説明します。

■ システム概要

1. 欲しい商品のhtmlを取得。
2. 価格の部分を抜き出す。
3. 過去と現在の価格を比較して処理

という仕様を組みました。

■ 1.欲しい商品のhtmlを取得

まずは欲しい商品のhtmlを取得する際に使ったプログラムを示します。
プログラミングに使う言語はPythonを使いましたよ。

ちなみに欲しかった商品はコレ

import urllib2
f = urllib2.urlopen('http://www.amazon.co.jp/%E3%82%A2%E3%83%87%E3%82%A3%E3%83%80%E3%82%B9-adidas-FORUM-G1654900-%E3%83%9B%E3%83%AF%E3%82%A4%E3%83%88/dp/B003TJ91L8/ref=wl_it_dp_o_piT1_nS_nC?ie=UTF8&colid=2NPMF5TUB79UB&coliid=ISBLWHXEIDBUX')
html = f.read()

htmlの取得には”urllib2″というモジュール(ライブラリ)を使います。こいつをimportしてからurllib2のurlopen()関数を使用。結果を変数fに格納。

f.read()で変数htmlに該当Amazonページのhtmlソースが格納されてます。

■ 2.価格の部分を抜き出す

まずはソースを

import re
targetCol = re.search(r'priceLarge.*',html)
matchPrice = re.search(r'\d,\d+',targetCol.group(0))
nowPrice = matchPrice.group(0).replace(",","")

価格の部分を抜き出す為に、「正規表現」を用います。正規表現とは記号と文字で表現されたパターンを用いて文字列を検索する仕組みです。
正規表現を使うためには”re”というモジュールをimportします。

抜き出したい価格の部分は、htmlを調査してみると

<span class="priceLarge">¥ 3,905 - ¥ 6,615 </span>

の部分である事がわかりました。

と言う事で2行目では、パターンを使って文字列を検索するsearch()関数を使ってこの部分を抽出しています。

文字列の前にrをつけているのは、次の文字列はraw stringであるという事の宣言です。raw stringはエスケープシーケンスを無効にします。

正規表現では文字列中にエスケープ文字である”\”(バックスラッシュ)を多用しますので、通常の文字列だと正規表現で数字を表す”\d”を”\\d”としなければならず、冗長になるので最初からエスケープシーケンスを無効にしています。

正規表現のパターンとマッチした文字列はtargetColのMatch Objectにセットされます。こいつを取り出すにはgroup()関数を用います。引数の数値は複数のマッチが在った場合何番目のマッチ文字列を取り出すかの指定に使います。’priceLarge.*’パターンを使って

priceLarge">�� 3,905 - �� 6,615

を取り出します。さらにこの結果に対して’\d,\d+’のパターンを使って”3,905″を抜き出してカンマを削除して3905という数字を取り出しました。

これで価格を抜き出す事に成功です。

■ 3.過去と現在の価格を比較して処理

import commands
oldPrice = commands.getoutput('tail -1 /var/log/amazon/priceLog.txt')

mailCmd = 'echo "now price %s" | mail -s "price is changing"  example@gmail.com' %nowPrice
logCmd = 'echo %s >> /var/log/amazon/priceLog.txt' %nowPrice

if int(nowPrice) < int(oldPrice):
    commands.getoutput(mailCmd)

commands.getoutput(historyCmd)

ここでは価格を比較して、最新の価格が依然の価格よりやすかったらメールを発送するという処理を行います。
これらの実行にはLinuxシェルを使うのが簡単なので”commands”モジュールをimportします。

まず’/var/log/amazon/priceLog.txt’を作って、そこに今の価格を手入力します。
これを踏まえて、2行目ではoldPriceにpriceLogの最後の行の価格がはいってきます。
mailCmdにはLinuxでメールを送る用のコマンドを予めセット。
(Linux上でメールを使う方法は後日記事にアップします)
logCmdも同様、スクレイピングした価格をlogに追記する用のコマンドをセット。

7行目では現在価格が前回の価格よりも安ければ携帯にメールを送信。
最後に、価格をpriceLog.txtにセットしてます。

あとは30分毎にでも実行するようにcronにセットしてやれば、価格が下がった時にメールでお知らせが来るようになります。

最後にソース全文を置いておきます。

import urllib2
f = urllib2.urlopen('http://www.amazon.co.jp/%E3%82%A2%E3%83%87%E3%82%A3%E3%83%80%E3%82%B9-adidas-FORUM-G1654900-%E3%83%9B%E3%83%AF%E3%82%A4%E3%83%88/dp/B003TJ91L8/ref=wl_it_dp_o_piT1_nS_nC?ie=UTF8&colid=2NPMF5TUB79UB&coliid=ISBLWHXEIDBUX')
html = f.read()

import re
targetCol = re.search(r'priceLarge.*',html)
matchPrice = re.search(r'\d,\d+',targetCol.group(0))
nowPrice = matchPrice.group(0).replace(",","")

import commands
oldPrice = commands.getoutput('tail -1 /var/log/amazon/priceLog.txt')

mailCmd = 'echo "now price %s" | mail -s "price is changing"  example@gmail.com' %nowPrice
logCmd = 'echo %s >> /var/log/amazon/priceLog.txt' %nowPrice

if int(nowPrice) < int(oldPrice):
    commands.getoutput(mailCmd)

commands.getoutput(historyCmd)

余談:Ubuntuではファイルの作成日時がわからないのでアレなんですが2ヶ月くらい前から監視してて、最高価格6,615円の日がありましたが、最終的に3,900円くらいでゲットしました。

end

photo by: yukop
python-logo-master-v3-TM

ちょっとしたウェブページを作るという案件において、デザイナーから上がってきたイラストレーター形式のデータをHTMLに落としこむという作業をしました。

イラストレーターのデータは基本的に単位が「mm」なので、ピクセル単位で管理するHTML&CSSに落としこむには単位の変換が必要です。

最初の段階でサイトの横幅は950pxにしようと決めていました。
デザイナーさんから上がってきたイラストの横幅は315mmでした。

それで、例えば横幅50mm縦幅60mmのイラストパーツをピクセルに変換しようと思ったら

315 : 950 = 50 : x の式を立てて
x = (950 * 50) / 315 
x ≒ 150px

の計算で950ピクセルを総横幅としたサイトにおける50mmのピクセル換算が求められます。
答えはおよそ150ピクセルですね。

続いて縦幅を求めます。

50 : 60 = 150 : y
y = (60 * 150) / 50
y = 180px

総横幅315mm の中にある50mm × 60mm のパーツは 総横幅950pxの場において 150px × 180px に変換される事が分かりました。

実際サイトを作り始めるとこの様な計算を何度もやらないと行けないので、この仕事をこなすためのプログラムをPythonで書きました。

#! /usr/bin/python

fullWidth_mm = 315
fullWidth_px = 950

input_width_mm= raw_input('Width=: ')
answer_w = float(input_width_mm) * fullWidth_px / fullWidth_mm
print answer_w

input_height_mm = raw_input('Height=: ')
answer_h = float(input_height_mm) * answer_w / float(input_width_mm)
print answer_h

ここで重要なのはraw_input()関数ですね。
この関数を用いる事で、input_width_mm,input_height_mmに値を入力する事ができます。
引数は文字列で、入力を求める時に表示する文字を設定できます。

加えて、raw_input()によって入力された値は文字列になっていますのでfloat()によって浮動小数点数にキャストしています。
Pythonは計算において一番複雑なオペランドの型にすべてのオペランドを合わせて計算しますので、結果はfloatで返って来ます。
ちなみにPythonには4つの数値型があり、複雑さの序列は
整数型 < 長整数型 < 浮動小数点型 < 複素数型 の様になっています。 さて、こいつを実行するとこんな感じです。

Width=: 50 #input
150.793650794
Height=: 60 #input
180.952380952

と言う事でこんな感じに変換して、イラストレーターのデータをHTMLに落としこむ事に成功しました。

まあ・・・もともとイラストレーターにこういう事を簡単にこなす機能がありそうですが・・・。
end