<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>PageTalks &#187; Site Development</title>
	<atom:link href="http://pagetalks.com/category/site-development/feed" rel="self" type="application/rss+xml" />
	<link>http://pagetalks.com</link>
	<description>Pure Web Development &#38; Design Ideas</description>
	<lastBuildDate>Thu, 19 Jan 2012 12:06:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Wrangling with Deflate, Base64 and GZip</title>
		<link>http://pagetalks.com/2012/01/19/wrangling-with-deflate-base64-and-gzip.html</link>
		<comments>http://pagetalks.com/2012/01/19/wrangling-with-deflate-base64-and-gzip.html#comments</comments>
		<pubDate>Thu, 19 Jan 2012 11:35:56 +0000</pubDate>
		<dc:creator>Robin</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[NodeJS]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[base64]]></category>
		<category><![CDATA[deflate]]></category>
		<category><![CDATA[gzip]]></category>
		<category><![CDATA[inflate]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[zlib]]></category>

		<guid isPermaLink="false">http://pagetalks.com/?p=549</guid>
		<description><![CDATA[最近不小心被一些编码相关的东西困扰了。这些从Web诞生便产生的一些编码问题，在2012年的今天仍然可以让一个程序员抓狂。项目的大致需求是这样的，客户端需要将一个字符串进行如下处理... ]]></description>
			<content:encoded><![CDATA[<p>最近不小心被一些编码相关的东西困扰了。这些从Web诞生便产生的一些编码问题，在2012年的今天仍然可以让一个程序员抓狂。项目的大致需求是这样的，客户端需要将一个字符串进行如下处理：</p>
<ol>
<li>将字符串进行Deflate压缩</li>
<li>将压缩后的结果再进行Base64编码</li>
</ol>
<p>那么服务器端，需要进行上述流程的反过程。问题是，由于这是个开放接口，客户端可以使用各种不同的平台进行开发，如JS、Java、Ruby、PHP等。好在，大多数语言都是基于<a href="http://zlib.net/">zlib</a>包装了自己的相关API，那么也算是实现标准了。窘迫的事情时，NodeJS里面zlib的实现是在0.6以后加入的，我们使用的技术仍然是0.4版本的。</p>
<p>迫于时间有限，切换到0.6或者实现zlib的binding都是不靠谱的，于是我打开了万能的Github。果然功夫不负有心人，找到了Deflate的纯JS实现——<a href="https://github.com/dankogai/js-deflate">RawDeflate</a>。顿时对作者的崇拜之心油然而生。殊不知，悲剧就是从这里开始的。<span id="more-549"></span><br />
<h3>Base64算法</h3>
<p>为了测试有效性，我用JS做了客户端编码工作，然后用Ruby实现了服务器端解码工作。代码如下:</p>
<ul>
<li>被我修改过的<a href="https://gist.github.com/1638963#file_deflate.js">deflate.js</a></li>
<li>JS编码脚本,<a href="https://gist.github.com/1638963#file_encode_v1.js">v1</a></li>
<li>Ruby解码脚本,<a href="https://gist.github.com/1638963#file_decode_v1.rb">v1</a></li>
</ul>
<p>这里只把编码脚本和解码脚本贴出来，其他的已经在上面给出了Gist链接。</p>
<h4>编码脚本, v1</h4>
<pre><code>var RawDeflate = require("./deflate"),
    Buffer = require("buffer").Buffer,
    fs = require("fs");

function encode(str) {
  return new Buffer(RawDeflate.deflate(str)).toString("base64");
}

console.log(encode("hello, world!"));
fs.writeFileSync("data.txt", encode("hello, world!"));</code></pre>
<h4>解码脚本，v1</h4>
<pre><code>require 'base64'
require 'zlib'

def decode(str)
  Zlib::Inflate.new(-Zlib::MAX_WBITS).inflate(Base64.decode64(str))
end

str = File.open("data.txt", "r") do |data|
  data.readlines().join()
end

p decode(str)</code></pre>
<p>运行的结果是空串哦，亲！也就是说Ruby竟然不能解出来。Ruby是直接在Zlib上进行包装的，那么其他的语言PHP、Python什么的也应该是同样的结果。</p>
<p>好吧，难道我JS的算法有误差？那么和Ruby的算法进行对比以下吧⋯⋯</p>
<p><a href="https://gist.github.com/1638963#file_compare_test.rb">Ruby的测试脚本</a>，算出的每个步骤都进行md5：</p>
<pre><code>require 'base64'
require 'zlib'
require 'digest/md5'

def deflate(str)
  Zlib::Deflate.new(nil, -Zlib::MAX_WBITS).deflate(str, Zlib::FINISH)
end

def base64(str)
  Base64.encode64(str)
end

def md5(str)
  s = Digest::MD5.hexdigest(str)
end

def encode(str)
  base64(deflate(str))
end

def decode(str)
  Zlib::Inflate.new(-Zlib::MAX_WBITS).inflate(Base64.decode64(str))
end

str = 'hello, world'

p "Test Base64"
p base64(str)
p md5(base64(str))

p "Test Deflate"
p deflate(str)
p md5(deflate(str))

p "Test Encode Defalte and Base64"
p encode(str)
p md5(encode(str))

p "Test Decode Deflate and Base64"
p decode(encode(str))</code></pre>
<p>运行发现，Ruby自己处理自己压缩出来的东西毫无问题。那么JS呢？</p>
<pre><code>var Base64 = require("./b64"),
    RawDeflate = require("./deflate"),
    Buffer = require("buffer").Buffer,
    crypto = require("crypto");

function decode (str) {
  return RawDeflate.inflate(new Buffer(str, "base64").toString());
}

function md5 (str) {
  return crypto.createHash("md5").update(str).digest("hex");
}

function base64 (str) {
  return new Buffer(str).toString("base64");
}

function deflate (str) {
  return RawDeflate.deflate(str);
}

function encode (str) {
  return base64(deflate(str));
}

var str = "hello, world";
console.log("Testing string: " + str);

console.log("Base64 Test");
console.log(base64(str));
console.log(md5(base64(str)));

console.log("Defalte Test");
console.log(deflate(str));
console.log(md5(deflate(str)));

console.log("Test Encode");
console.log(encode(str));
console.log(md5(encode(str)));

console.log("Test Decode");
console.log(decode(encode(str)));</code></pre>
<p>好吧，JS的算法自己处理自己的结果也是正确的。那么比较以下两边各个步骤的md5，可以发现几个现象：</p>
<p><a href="http://www.flickr.com/photos/28352704@N06/6724942605" title="View 'Screen Shot 2012-01-19 at 下午6.43.35' on Flickr.com"><img border="0" style="display:block; margin-left:auto; margin-right:auto;" height="396" src="http://farm8.staticflickr.com/7012/6724942605_db603df767_o.png" alt="Screen Shot 2012-01-19 at 下午6.43.35" width="560" title="Screen Shot 2012-01-19 at 下午6.43.35"/></a></p>
<ul>
<li>仅仅Base64后MD5便不一致</li>
<li>仅仅Deflate后MD5一致</li>
<li>Deflate后再Base64,结果MD5不一致</li>
</ul>
<p>那么就是NodeJS的Base64这么算可能不对了，这时我已经凌乱了，算了，干脆找个JS的Base64实现吧。我的大神啊，原来RawDeflate的作者自己也写了个<a href="https://github.com/dankogai/js-base64">Base64的实现</a>，我觉得这里面有阴谋⋯⋯</p>
<p>用上这位<a href="https://gist.github.com/1638963#file_base64.js">大神的Base64</a>，同时我也发现了RawDeflate里面有一个使用实例。例子里面在Deflate之前，把字符串进行了Base64.<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/V40F_HTML/MAN/MAN1/0398____.HTM">utob</a>操作。但是我们用的测试字符是“hello,world&#8221;貌似没有非ACSII字符。</p>
<p>那么我们<a href="https://gist.github.com/1638963#file_encode_v2.js">新的编码脚本</a>如下：</p>
<pre><code>var RawDeflate = require("./deflate"),
    Buffer = require("buffer").Buffer,
    fs = require("fs"),
    Base64 = require("./base64");

function encode(str) {
  return Base64.toBase64(RawDeflate.deflate(Base64.utob(str)));
}

console.log(encode("hello, world!"));
fs.writeFileSync("data.txt", encode("hello, world!"));</code></pre>
<p>我们仍然使用之前的<a href="https://gist.github.com/1638963#file_decode_v1.rb">解码脚本</a>，结果竟然通过了！ruby得到了“hello,world“！</p>
<p>其中原理不解，有待高人解答，但是灾难还没有结束哦。</p>
<h3>RFC1951、RFC1950和RFC1951</h3>
<p>因为对方服务器目前使用的是JAVA，那么我必须用JAVA测试才能OK。</p>
<p>JAVA的代码如下，只贴出核心代码吧：</p>
<pre><code>InputStream in = new InflaterInputStream(new Base64InputStream(new FileInputStream(compressed)));</code></pre>
<p>第一次试验的结果是，无法解压的，想哭啊，得到“unknown compression method”的错误。</p>
<p>我开始质疑JAVA的实现了。虽然也是zlib的前缀，但是InflaterInputStream<a href="http://docs.oracle.com/javase/1.4.2/docs/api/java/util/zip/InflaterInputStream.html">这个类的JavaDoc</a>里却没有写清楚它对应的算法。</p>
<p>我们知道，HTTP传输里面经常会用到gzip、deflate来压缩内容，只用在header里面写明“Content-encoding&#8221;。Web服务器和浏览器其实都是相当默契的。好吧，我必须承认，浏览器不愧是Web里面最复杂的软件。因为它handle了太多的东西。</p>
<p><a href="http://www.ietf.org/rfc/rfc1950.txt">RFC1950</a>是zlib算法，<a href="http://www.google.com/url?sa=t&#038;rct=j&#038;q=rfc%201951&#038;source=web&#038;cd=1&#038;sqi=2&#038;ved=0CCMQFjAA&#038;url=http%3A%2F%2Fwww.ietf.org%2Frfc%2Frfc1951.txt&#038;ei=E_sXT9OPNsWpiAfVtdybCw&#038;usg=AFQjCNFifaDqn62RJhQ3ODDJ12pO1LsQAA">RFC1951</a>是deflate算法，<a href="http://www.google.com/url?sa=t&#038;rct=j&#038;q=rfc%201952&#038;source=web&#038;cd=1&#038;ved=0CCAQFjAA&#038;url=http%3A%2F%2Fwww.ietf.org%2Frfc%2Frfc1952.txt&#038;ei=I_sXT-ykEpCWiQe0wdmgCw&#038;usg=AFQjCNFA13Eq1NXCeQAGsDxtXuMSMI7bog">RFC1952</a>是Gzip算法。那么他们是三个独立的算法么？</p>
<p>我以为是，其实不是！</p>
<p>在HTTP 1.1的定义里面，也就是<a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">RFC2616</a>是这么定义delfate传输压缩的：</p>
<p><quote>deflate &#8211; The &#8220;zlib&#8221; format defined in RFC 1950 [31] in combination with the &#8220;deflate&#8221; compression mechanism described in RFC 1951 [29].</quote></p>
<p>原来zlib和deflate是同时使用的！zlib仅仅作为一种容器格式，来承载通过deflate算法压缩的内容。就像AVI其实是个视频容器格式，里面的压缩算法可以是XVID也可以H.262！</p>
<p>回来想想RawDeflate的主页上也仅仅说明是RFC1951的实现，而且人家是”Raw“Deflate，Raw！看来是我自己不懂啊⋯⋯</p>
<p>跟我一样苦逼的人还是不少的，看这个<a href="http://stackoverflow.com/questions/3932117/handling-http-contentencoding-deflate">帖子</a>，有一个回复已经给出了JAVA里面的解决方案。</p>
<p>如果要解决单纯使用Deflate压缩的文件，必须传入一个自定义Inflater。</p>
<pre><code>InputStream in = new InflaterInputStream(conn.getInputStream()), new Inflater(true));</code></pre>
<p>更新了JAVA脚本之后，的确问题解决了。顺手把其他语言解码方案也试验出来了。基本上，除了JAVA需要，其他实现都不需要进行额外的判断，所以JAVA实在不是一个敏捷语言啊⋯⋯</p>
<h4>Ruby解码实现</h4>
<pre><code>require 'base64'
require 'zlib'

def decode(str)
  Zlib::Inflate.new(-Zlib::MAX_WBITS).inflate(Base64.decode64(str))
end

File.open("data.txt", "r") do |data|
  str = data.readlines
  p decode str.join
end</code></pre>
<h4>Python解码实现</h4>
<p>Python在压缩的时候，想得到纯粹的Deflate流也是需要额外的加工的，详见此处：<a href="http://stackoverflow.com/questions/1089662/python-inflate-and-deflate-implementations">http://stackoverflow.com/questions/1089662/python-inflate-and-deflate-implementations</a>。</p>
<p><a href="https://gist.github.com/1638963#file_inflate.py">Python的解码</a>的实现也很直白：</p>
<pre><code>import zlib
import base64

str = ""
with open("data.txt") as data:
    for line in data:
        print line
        str += line

def decode_base64_and_inflate(str):
    decoded_data = base64.b64decode( str )
    return zlib.decompress( decoded_data , -zlib.MAX_WBITS)

print decode_base64_and_inflate(str)</code></pre>
<h4>PHP解码实现</h4>
<p>PHP一定要使用gzinflate才能解压纯Deflate流，gzuncompress是用来解压HTTP采用“deflate”方式压缩的数据的！</p>
<pre><code>$data = file_get_contents("data.txt");

echo $data;
echo gzinflate(base64_decode($data));

// this command will throw an exception: data error
// echo gzuncompress(base64_decode($data));
</code></pre>
<h4>JAVA实现</h4>
<p><a href="https://gist.github.com/1638963#file_inflate.java">JAVA实现</a>好累啊，这么罗嗦。还需要一个额外的一个JAR进行Base64操作。这里用的是Apache的<a href="http://commons.apache.org/codec/download_codec.cgi">Common Codec</a>。</p>
<pre><code>//http://stackoverflow.com/questions/3932117/handling-http-contentencoding-deflate

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import java.util.zip.ZipException;

import org.apache.commons.codec.binary.Base64InputStream;

public class Inflate {

    public static void inflate(File compressed, OutputStream out) throws IOException {
        InputStream in = new InflaterInputStream(new Base64InputStream(new FileInputStream(compressed)), new Inflater(true));
        shovelInToOut(in, out);
        in.close();
        out.close();
    }

    /**
     * Shovels all data from an input stream to an output stream.
     */
    private static void shovelInToOut(InputStream in, OutputStream out) throws IOException {
//    The following code should be working but it produces strange suffix like "[B@13fcf0ce" now and then
//        byte[] buffer = new byte[1000];
//        int len;
//        while((len = in.read(buffer)) > 0) {
//            out.write(buffer, 0, len);
//            System.out.println(buffer);
//        }

        String line;
        InputStreamReader isr = new InputStreamReader(in);
        BufferedReader br = new BufferedReader(isr);
        while((line = br.readLine()) != null) {
            out.write(line.getBytes());
        }
    }

    /**
     * Main method to test it all.
     */
    public static void main(String[] args) throws IOException, DataFormatException {
        File compressed = new File("data.txt");
        try {
            inflate(compressed, System.out);
        } catch(ZipException e) {
            System.out.println(e.getMessage());
            throw e;
        }
    }

}</code></pre>
<h3>总结</h3>
<p>编码问题总是一个挥之不去的阴影！</p>
]]></content:encoded>
			<wfw:commentRss>http://pagetalks.com/2012/01/19/wrangling-with-deflate-base64-and-gzip.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Immigrate  WordPress &#8211; A Real Case</title>
		<link>http://pagetalks.com/2012/01/14/immigrate-wordpress-a-real-case.html</link>
		<comments>http://pagetalks.com/2012/01/14/immigrate-wordpress-a-real-case.html#comments</comments>
		<pubDate>Sat, 14 Jan 2012 12:39:12 +0000</pubDate>
		<dc:creator>Robin</dc:creator>
				<category><![CDATA[Site Development]]></category>
		<category><![CDATA[Technique]]></category>
		<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[server]]></category>

		<guid isPermaLink="false">http://pagetalks.com/?p=539</guid>
		<description><![CDATA[上个星期，我终于决定把elfvision.com上的博客移到robinqu.me这个新域名上。由于使用wordpress已经很多年了，前前后后也做过不少wordpress的维护工作了，自我感觉良好，不料这次遇到不少麻烦，遂整... ]]></description>
			<content:encoded><![CDATA[<p>上个星期，我终于决定把elfvision.com上的博客移到robinqu.me这个新域名上。由于使用wordpress已经很多年了，前前后后也做过不少wordpress的维护工作了，自我感觉良好，不料这次遇到不少麻烦，遂整理成文。</p>
<p>分析一下我这里的案例，其实是要做以下这些事情（原站点简称A，新站点简称B）：</p>
<ol>
<li>制作A在B下的镜像</li>
<li>修改B下面的镜像Wordpress中域名设置</li>
<li>对A站相关地址进行转向到B站域名</li>
<li>清理A站的旧文件</li>
<li>在A站和B站上同时发出公告，安抚、告知用户</li>
</ol>
<h3>制作站点镜像</h3>
<p>开头很重要，如果你的站点无时无刻有访问量并产生数据，你面临两种选择：1、临时关闭站点，挂出维护通知 2、站点切换后再灌入差量数据。所幸，Wordpress站点往往基本没有实时数据，我的做法是没有关闭原站，而是直接复制数据的。</p>
<p>假设你可以登陆你的服务器，那么直接远程SSH就可以完成对文件的复制，即将wordpress站点的根目录直接复制到新位置。如果不能，那么就通过FTP慢慢拖吧⋯⋯</p>
<p>至于数据库部分，如果安装了phpMyAdmin，可以登陆到管理后台，直接选中数据库，然后在Operation选项卡中有Copy database的功能。</p>
<p>否则就得登陆mysql客户端，执行mysqldump了：</p>
<pre><code>mysqldump [db1] -u root -ppassword --add-drop-table | mysql [db2] -u root -ppassword</code></pre>
<p><span id="more-539"></span><br />
<h3>切换域名</h3>
<p>到这个时候，如果的B站点域名指向和主机配置都正确，访问B站应该被转向了A站，因为B站内部的wordpress设置的域名还是A站的。</p>
<p>切换域名分两方面：</p>
<ul>
<li>WordPress配置内部的域名设置</li>
<li>文章内容里面的链接内容</li>
</ul>
<p>对于前者，有两种办法，一种是直接登陆MYSQL，用SQL修改wp-options表的两条纪录，即siteurl和home的option_value。</p>
<pre><code>UPDATE  `wp`.`wp_options` SET  `option_value` =  'new_site_url' WHERE  `wp_options`.`option_name` ='home';
UPDATE  `wp`.`wp_options` SET  `option_value` =  'new_wordpress_url' WHERE  `wp_options`.`option_name` ='siteurl';
</code></pre>
<p>或者修改B站下面的wp_config.php，加入如下两句：</p>
<pre><code>define('WP_SITEURL', 'new_wordpress_url');
define('WP_HOME', 'new_site_url');</code></pre>
<h3>对A站的地址进行转向</h3>
<p>不少注重SEO的同学应该会单行A域名的PR值突然下降，那么我们可以设置nginx或者Apache的主机配置文件对以往链接进行304转向，将伤害降到尽可能小。</p>
<pre><code>server {
    listen 80;
    server_name www.siteB.com;

    index index.php index.html;
    root /var/www/siteB;

    location / {
        error_page 404 = /index.php?q=$uri;
		<strong>rewrite ^/(\d+)/(\d+)/(.*)$ http://siteB$request_uri permanent;</strong>
    }

}</code></pre>
<p>注意替换rewrite规则中的域名。详细文档：<a href="http://wiki.nginx.org/HttpRewriteModule#rewrite">http://wiki.nginx.org/HttpRewriteModule#rewrite</a>。</p>
<p>rewrite后面接受的第一个参数是url中path部分的正则匹配，这个正则应该按照之前wordpress的permanent链接的模式来写，最后一个参数permanent表示是304永久重定向。</p>
<p>注意，如果你是将Wordpress程序在同一个域名中迁移，例如从http://siteA.com/blog/迁移到http://siteA.com/，那么你可以尝试nginx的try_files规则：<a href="http://wiki.nginx.org/HttpCoreModule#try_files">http://wiki.nginx.org/HttpCoreModule#try_files</a>。</p>
<p>有一篇文章专门降到了利用这个指令来进行同域名不同虚拟目录的迁移：<a href="http://michaelshadle.com/2009/03/19/finally-using-nginxs-try-files-directive">http://michaelshadle.com/2009/03/19/finally-using-nginxs-try-files-directive</a>。</p>
<p>对于文章内部的链接数据，则要再次登陆MYSQL控制台或phpMyAdmin进行操作了。</p>
<p><code>
<pre>UPDATE wp_posts SET guid = replace(guid, 'http://www.siteA.com','http://www.siteB.com');
UPDATE wp_posts SET post_content = replace(post_content, 'http://www.siteA.com', 'http://www.siteB.com');
</pre>
<p></code></p>
<h3>清理旧文件</h3>
<p>登陆FTP或者SSH执行文件删除吧，不过个人建议不要删除，把所有文件都备份到另一个目录，带迁移成功后的一两个月之后再考虑是否删除。这样可以避免突发事件时的尴尬。</p>
<h3>通知用户</h3>
<p>好吧， 在两边都贴上大大的告示吧，以免用户感到困惑⋯⋯</p>
<h3>Next…</h3>
<p>我更新了另外一篇文章来阐述node里面的一些新加入crypto相关的API：<a href="http://pagetalks.com/2012/01/18/more-about-crypto-module-in-nodejs.html">http://pagetalks.com/2012/01/18/more-about-crypto-module-in-nodejs.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://pagetalks.com/2012/01/14/immigrate-wordpress-a-real-case.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Toys For Web Designers</title>
		<link>http://pagetalks.com/2010/10/30/new-toys-for-web-designers.html</link>
		<comments>http://pagetalks.com/2010/10/30/new-toys-for-web-designers.html#comments</comments>
		<pubDate>Sat, 30 Oct 2010 11:52:12 +0000</pubDate>
		<dc:creator>Robin</dc:creator>
				<category><![CDATA[HTML5]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[User Experience]]></category>
		<category><![CDATA[canvas]]></category>
		<category><![CDATA[js]]></category>

		<guid isPermaLink="false">http://pagetalks.com/?p=488</guid>
		<description><![CDATA[有时候在想，前端的核心技术完全由浏览器厂商做主，开发人员做事情总是收到各种限制真是不爽。就算到了HTMLx(x>5)，也被局限于浏览器的框框。虽然现在WebOS的概念很棒，可惜PalmPre出师未捷... ]]></description>
			<content:encoded><![CDATA[<p>有时候在想，前端的核心技术完全由浏览器厂商做主，开发人员做事情总是收到各种限制真是不爽。就算到了HTMLx(x>5)，也被局限于浏览器的框框。虽然现在WebOS的概念很棒，可惜PalmPre出师未捷身先死。老态龙钟的HP也干不出什么能和Google、Apple叫板的事情。总之，前端工程师们最多到手机上做做WebApp或者Air应用找找乐子。</p>
<p>好吧，抱怨完了之后，我们说说现在还有“玩头”的canvas。想必大家都已经看过N多canvas的例子，不管是canvas做的动画还是游戏，都显得十分理想。按下F12，你却发现这些例子的代码是十分的庞大的，证明要操控canvas做一些“有实用性”的事情，是很有难度的。</p>
<p>毕竟，Canvas的API只提供了画点、画线、画圆、画正方形之类的基本接口，简陋的让人难以接受。这个时候的Canvas跟Flash是完全没有可比性的，Flash的Tween、Sprite之类的类已经封装的非常完美，其暴露给开发者的API已经高于Canvas的那些API太多太多。</p>
<p>但另一方面，Canvas也给我们了“制作”Flash的机会。毕竟Flash的底层无非也就是画点、画线的方法。</p>
<p>在这里，我想介绍一下几个比较好的针对Canvas的脚本库。在实际工程中，是绝对救星。<br />
<span id="more-488"></span><br />
<h3><a href="http://code.google.com/p/cakejs/">Cake.js</a></h3>
<p>Cake.js是一个非常有魅力的库。首先，它解决了几个让你十分头疼的问题：</p>
<ul>
<li>Canvas内部没有对象的概念，没法针对某个图形或形状进行监听等操作</li>
<li>浏览器之间的复杂兼容性</li>
<li>Canvas缺乏动画操作API</li>
<li>Canvas和SVG不能互转</li>
</ul>
<p>Cake.js很好了解决了以上所有问题。它不仅提供了Circle、Rectangle之类的基础对象，而且这些对象能够如同DOM对象一样进行监听等操作。其提供了较为高效的动画函数，如同Flash里的TweenLite。<br />
更有趣的是，Cake.js提供了一个SVGParser，支持从SVG绘制Canvas！</p>
<p>如果你要用canvas制作例如游戏之类的高度交互的应用，那么你要么用cake.js，要么自己实现一份cake.js。</p>
<p>大家可以到这里去看看cake.js的一些演示：http://glimr.rubyforge.org/cake/canvas.html</p>
<h3><a href="http://processingjs.org/">Processing.js</a></h3>
<p>Processing是一个很有名的数据可视化语言，之前的浏览器解决方案一直是利用java applet技术，可惜applet尴尬的局面至今没有能够缓解，所以java applet并不是一个很好像大众分发的技术方案。</p>
<p>但是某人（jQuery的作者之一）实现一个JS版的Processing.js。准确的说应该是一个Processing语言的JS解析器，然后利用canvas展示。</p>
<p>传承了Processing的所有优点。如果你已有Processing的脚本，你是可以直接无痛迁移到Canvas上的。</p>
<p>对于比较了解Processing的朋友，这个库你是绝对需要的。</p>
<h3><a href="http://deanm.github.com/pre3d/">Pre3D</a></h3>
<p>有的同学可能已经迫不及待用Canvas做3D了。可是Canvas的3D Context的标准都没有，WebGL也还是少数浏览器的特权。退而求其次，就是用2D来模拟3D了。这里面的大部分原理就是坐标的矩阵变幻了，对于Canvas来说，这些操作全部用JS来实现，效率肯定比WebGL之类的C所写的原生3D API低好几个数量级的。但是这是目前唯一可行的方案。</p>
<p>所以这个库的名字叫做“Pre3D”，意味Canvas的3D时代还为来临，是3D的前期。</p>
<p>若是准备做3D图形的展示，这个库可以让你事半功倍；倘若是要做游戏，这个库也是爱莫能助的。</p>
<p>限于技术限制，Pre3D没法追踪你创建的虚拟对象，你无法与它们进行交互。你能有的仅仅是对Camera对象进行rotate、translate之类的操作。</p>
<p>但是这些对于制作出类似<a href="http://alteredqualia.com/canvasmol/">CanvasMol</a>应用是错错有余的。</p>
<h3>依旧蛋疼</h3>
<p>即使你克服了一切利用Canvas来做游戏，你却发现你的游戏在有些浏览器下跑的很慢，在有些浏览器下完全无法使用。</p>
<p>想退回利用DOM进行游戏对象的操作？现在已被正式，canvas对于多个游戏对象的操作也许好于直接操作DOM对象(via <a href="http://blog.frontendforce.com/2010/03/games-development-in-javascript-canvas-vs-dom-benchmark/">link</a>)。</p>
<p>好吧，对于刚刚定稿的HTML5我们要耐心，耐心，再耐心。</p>
]]></content:encoded>
			<wfw:commentRss>http://pagetalks.com/2010/10/30/new-toys-for-web-designers.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Eye Tracking and Web Usability: A Good Fit?</title>
		<link>http://pagetalks.com/2010/04/04/eye-tracking-and-web-usability-a-good-fit.html</link>
		<comments>http://pagetalks.com/2010/04/04/eye-tracking-and-web-usability-a-good-fit.html#comments</comments>
		<pubDate>Sun, 04 Apr 2010 13:43:44 +0000</pubDate>
		<dc:creator>Robin</dc:creator>
				<category><![CDATA[Digest]]></category>
		<category><![CDATA[User Experience]]></category>
		<category><![CDATA[eye tracking]]></category>
		<category><![CDATA[ux]]></category>

		<guid isPermaLink="false">http://pagetalks.com/?p=386</guid>
		<description><![CDATA[Since its inception, eye tracking has been employed by cognitive scientists to study reading, learning, attention, and neurology; by marketers to examine the effectiveness of ad and package designs; and by human factors engineers to guide automotive and ... ]]></description>
			<content:encoded><![CDATA[<div class="text-en" lang="en">
Since its inception, eye tracking has been employed by cognitive scientists to study reading, learning, attention, and neurology; by marketers to examine the effectiveness of ad and package designs; and by human factors engineers to guide automotive and airplane cockpit design. These and other disciplines have had great success leveraging eye tracking as a behavioral research method and to inform the design of communications and interactions. Recently, as eye tracking technology has become more affordable and accessible, academics, research suppliers, and eye tracking equipment makers have been experimenting with applying eye tracking to behavioral research in new domains.
</div>
<div class="text-cn" lang="zh">
眼球跟踪技术在可用性研究方面是个万金油。在近几年，几乎运用到了大多数公司的UX研究里面。这个直观的实验方法能给实验者关于用户注意力分布的直接统计数据。但是其中更深层次的关联，也许并不是仅仅越吸引眼球，就越重要或者越“有趣”吧？
</div>
<p><a href="http://uxmag.com/technology/eye-tracking-and-web-usability-a-good-fit" class="external digest-continue more-link">Read More</a></p>
]]></content:encoded>
			<wfw:commentRss>http://pagetalks.com/2010/04/04/eye-tracking-and-web-usability-a-good-fit.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Browser Size Tester</title>
		<link>http://pagetalks.com/2010/03/31/browser-size-tester.html</link>
		<comments>http://pagetalks.com/2010/03/31/browser-size-tester.html#comments</comments>
		<pubDate>Wed, 31 Mar 2010 08:59:30 +0000</pubDate>
		<dc:creator>Robin</dc:creator>
				<category><![CDATA[User Experience]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[size]]></category>
		<category><![CDATA[ux]]></category>

		<guid isPermaLink="false">http://pagetalks.com/?p=383</guid>
		<description><![CDATA[Are you enjoying designing on your 24&#8242; inch LCD Monitor? Well, most designers, I believe, do. More often than not, they forget to test on a monitor that their clients may use. Grab a test tool for browser size. Meanwhile, by analyzing the browser s... ]]></description>
			<content:encoded><![CDATA[<div class="text-en" lang="en">
Are you enjoying designing on your 24&#8242; inch LCD Monitor? Well, most designers, I believe, do. More often than not, they forget to test on a monitor that their clients may use.<br />
Grab a test tool for browser size. Meanwhile, by analyzing the browser size and focus distribution graph, you can better plan your layout.
</div>
<div class="text-cn" lang="zh">
用24寸的显示器来做设计应该很爽吧？相信大多数设计师都是这样。但往往，我们会忘记在客户最常使用的显示器尺寸下进行测试。同时，通过分析浏览器显示器尺寸以及用户的注意力分布图，我们可以更好的安排页面布局。以下提供了两个浏览器尺寸测试工具。
</div>
<p><span id="more-383"></span><br />
<a href="http://pagetalks.com/wp-content/uploads/2010/03/browser-test.png"><img src="http://pagetalks.com/wp-content/uploads/2010/03/browser-test.png" alt="" title="Browser Test" width="580" height="381" class="aligncenter size-full wp-image-384" /></a></p>
<ul>
<li>http://whereisthefold.com/</li>
<li>http://browsersize.googlelabs.com/</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://pagetalks.com/2010/03/31/browser-size-tester.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WAVE – Web Accessibility Evaluation Tool</title>
		<link>http://pagetalks.com/2010/03/28/wave-%e2%80%93-web-accessibility-evaluation-tool.html</link>
		<comments>http://pagetalks.com/2010/03/28/wave-%e2%80%93-web-accessibility-evaluation-tool.html#comments</comments>
		<pubDate>Sun, 28 Mar 2010 13:45:22 +0000</pubDate>
		<dc:creator>Robin</dc:creator>
				<category><![CDATA[User Experience]]></category>
		<category><![CDATA[accessibility]]></category>
		<category><![CDATA[ria]]></category>

		<guid isPermaLink="false">http://pagetalks.com/?p=374</guid>
		<description><![CDATA[WAVE is a free web accessibility evaluation tool. It is used to aid humans in the web accessibility evaluation process. Rather than providing a complex technical report, WAVE shows the original web page with embedded icons and indicators that reveal the ... ]]></description>
			<content:encoded><![CDATA[<div class="text-en" lang="en">
WAVE is a free web accessibility evaluation tool. It is used to aid humans in the web accessibility evaluation process. Rather than providing a complex technical report, WAVE shows the original web page with embedded icons and indicators that reveal the accessibility of that page.</p>
<p>Just enter the URL of a webpage you want to test and that is all. So if you care about web accessibility, you have to check it out:<br />
URL: http://wave.webaim.org/
</p></div>
<div class="text-ch" lang="zh">
WAVE是一个简单的网络应用，它的目的就是帮你检测网页上的可用性漏洞，当然都是一些基础的检测，但是这个测试仅仅需要你输入一下网址，多么方便啊。检测之后，会给出一份简单的报告，只不过没有指明具体是哪个出了问题。如果能给出一些改进方法那就更好了⋯⋯汗，我变的越来越懒了。<br />
地址：http://wave.webaim.org
</div>
<p><span id="more-374"></span><br />
<a href="http://pagetalks.com/wp-content/uploads/2010/03/wave-report.png" class="lightbox"><img src="http://pagetalks.com/wp-content/uploads/2010/03/wave-report-300x191.png" alt="" title="wave - report" width="300" height="191" class="aligncenter size-medium wp-image-376" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://pagetalks.com/2010/03/28/wave-%e2%80%93-web-accessibility-evaluation-tool.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Best Free WordPress Themes of 2009</title>
		<link>http://pagetalks.com/2010/03/26/the-best-free-wordpress-themes-of-2009.html</link>
		<comments>http://pagetalks.com/2010/03/26/the-best-free-wordpress-themes-of-2009.html#comments</comments>
		<pubDate>Fri, 26 Mar 2010 13:07:18 +0000</pubDate>
		<dc:creator>Robin</dc:creator>
				<category><![CDATA[Digest]]></category>
		<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[theme]]></category>

		<guid isPermaLink="false">http://pagetalks.com/?p=370</guid>
		<description><![CDATA[In this article, we’re presenting our picks for the best free WordPress themes of 2009. There were plenty of free themes created in 2009, but here are the ones that we feel had a little something extra that made them stand out from the crowd. If you th... ]]></description>
			<content:encoded><![CDATA[<div class="text-en" lang="en">
In this article, we’re presenting our picks for the best free WordPress themes of 2009. There were plenty of free themes created in 2009, but here are the ones that we feel had a little something extra that made them stand out from the crowd. If you think we missed or left one out, let us know about them in the comments.
</div>
<div class="text-cn" lang="zh">
老外的Wordpress主题，有什么好说的呢，不乏大家熟悉的，例如Composito、Irresistible。用的时候要注意他们对中文字体支持并不是很好。拿过来就修改一下CSS吧。
</div>
<p><a href="http://webdesignledger.com/freebies/the-best-free-wordpress-themes-of-2009" class="external digest-continue more-link">Read More</a></p>
]]></content:encoded>
			<wfw:commentRss>http://pagetalks.com/2010/03/26/the-best-free-wordpress-themes-of-2009.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>13 Useful Code Snippets for WordPress Development</title>
		<link>http://pagetalks.com/2010/03/26/13-useful-code-snippets-for-wordpress-development.html</link>
		<comments>http://pagetalks.com/2010/03/26/13-useful-code-snippets-for-wordpress-development.html#comments</comments>
		<pubDate>Fri, 26 Mar 2010 12:57:39 +0000</pubDate>
		<dc:creator>Robin</dc:creator>
				<category><![CDATA[Digest]]></category>
		<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[snippet]]></category>

		<guid isPermaLink="false">http://pagetalks.com/?p=368</guid>
		<description><![CDATA[WordPress has grown to be commonly defined as the core solution for your blogging needs. It is the most recognized and sought after Content Management System by writers and designers. Consequently, over the past few years there has been a voluble increas... ]]></description>
			<content:encoded><![CDATA[<div class="text-en" lang="en">
WordPress has grown to be commonly defined as the core solution for your blogging needs. It is the most recognized and sought after Content Management System by writers and designers. Consequently, over the past few years there has been a voluble increase in WordPress blogs, this has caused the “need” for useful tips, tricks, and hacks, all made to allow the customizing of your WordPress powered site. Here are 13 code snippets or hacks that will help you extend the capabilities of your WordPress site.
</div>
<div class="text-cn" lang="zh">
老外的文章总是“XX条关于XX的建议”，把发散的事物进行归纳，然后线性的罗列，这就是他们的思维。也是解释他们为何如此严谨的一个位置。<br />
Wordpress人人用，你记录过你写模板时的常用代码么？在我印象中，我总是翻看自己下载的那些Cheetsheets⋯⋯<br />
不过最近用上了一个叫<a href="http://www.apple.com/downloads/macosx/development_tools/snippet.html">Snippet</a>的小软件，极大程度上的提高了代码收集、重用的能力啊。这不是广告⋯⋯
</div>
<p><a href="http://webdesignledger.com/tips/13-useful-code-snippets-for-wordpress-development" class="external digest-continue more-link">Read More</a></p>
]]></content:encoded>
			<wfw:commentRss>http://pagetalks.com/2010/03/26/13-useful-code-snippets-for-wordpress-development.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quick Tips For Creating a Mobile Optimized Site</title>
		<link>http://pagetalks.com/2010/03/26/quick-tips-for-creating-a-mobile-optimized-site.html</link>
		<comments>http://pagetalks.com/2010/03/26/quick-tips-for-creating-a-mobile-optimized-site.html#comments</comments>
		<pubDate>Fri, 26 Mar 2010 12:43:46 +0000</pubDate>
		<dc:creator>Robin</dc:creator>
				<category><![CDATA[Digest]]></category>
		<category><![CDATA[User Experience]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[optimzed]]></category>

		<guid isPermaLink="false">http://pagetalks.com/?p=365</guid>
		<description><![CDATA[Last year mobile web usage increased 148% worldwide. In the near future as smarthpones become more and more ubiquitous this number will continue to shoot up. As a developer, the time has arrived for you to seriously consider whether you should begin acco... ]]></description>
			<content:encoded><![CDATA[<div class="text-en" lang="en">
Last year mobile web usage increased 148% worldwide. In the near future as smarthpones become more and more ubiquitous this number will continue to shoot up. As a developer, the time has arrived for you to seriously consider whether you should begin accommodating your mobile audience.</p>
</div>
<div class="text-cn" lang="zh">
构建面向移动终端友好的站点。国内这项业务已经成了新的站点开发服务。我们面对的仍然是一些老问题：浏览器兼容性、浏览器兼容性以及浏览器兼容性⋯⋯<br />
玩笑⋯⋯其实除了浏览器兼容性，还有设备兼容性（！？），例如显示屏尺寸、色彩等等。这篇文章简单的给出了一些基础性的建议。先翻阅一下咯。
</div>
<p><a href="http://designshack.co.uk/articles/css/quick-tips-for-creating-a-mobile-optimized-site" class="external digest-continue more-link">Read More</a></p>
]]></content:encoded>
			<wfw:commentRss>http://pagetalks.com/2010/03/26/quick-tips-for-creating-a-mobile-optimized-site.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>10 Simple and Light Weight CMS Solutions</title>
		<link>http://pagetalks.com/2010/03/23/10-simple-and-light-weight-cms-solutions.html</link>
		<comments>http://pagetalks.com/2010/03/23/10-simple-and-light-weight-cms-solutions.html#comments</comments>
		<pubDate>Tue, 23 Mar 2010 13:40:58 +0000</pubDate>
		<dc:creator>Robin</dc:creator>
				<category><![CDATA[Digest]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[cms]]></category>
		<category><![CDATA[light weight]]></category>

		<guid isPermaLink="false">http://pagetalks.com/?p=363</guid>
		<description><![CDATA[Choosing the right content management system can be an overwhelming task for a web designer or developer. There are so many available, all with different features, it can be difficult to decide which is the best solution for a particular web project. For... ]]></description>
			<content:encoded><![CDATA[<div class="text-en" lang="en">
Choosing the right content management system can be an overwhelming task for a web designer or developer. There are so many available, all with different features, it can be difficult to decide which is the best solution for a particular web project. For complex websites, a fully featured CMS is probably the best way to go. However, for simple sites, lots of bells and whistles can be overkill and actually be a bit confusing for the person maintaining the website.</p>
<p>In this article, I’ve rounded up 10 simple and light weight cms solutions. All of these systems were built with simplicity and ease-of-use in mind.
</p></div>
<div class="text-cn" lang="zh">
Wordpress已经是PHP领域的CMS王者，其余的Movable Type、ExpressionEngine、Drupal之类也是十分强悍。但是根据8：2理论，他们80％的功能我们是用不着的！我们有足够的理由换用一个更加轻量级的程序。文章便做了这样一个介绍。
</div>
<p><a href="http://webdesignledger.com/tools/10-simple-and-light-weight-cms-solutions" class="external digest-continue more-link">Read More</a></p>
]]></content:encoded>
			<wfw:commentRss>http://pagetalks.com/2010/03/23/10-simple-and-light-weight-cms-solutions.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->
