果壳网招聘前端工程师

评论数:4评论

果壳网 guokr.com 是一个新兴的泛科技主题网站。我们面向城市科技青年,提供负责任、有智趣、贴近生活的内容。
我们在寻找掌握“正确”的技术与理念的前端开发工程师,负责果壳网站的前端架构设计与网站产品开发。

我们希望你能大致符合如下描述:
1. 透彻掌握HTML、CSS,对网页标准有成熟的理解 ;
2. 精通JS语法特性和运行机制,乐于探索高级web应用的最佳实践 ;
3. 充分理解前端开发对界面体验、交互设计、可访问性和网站性能的重要性 。

工作中我们需要你能:
1. 负责果壳网网页前端开发、前端架构设计与技术性能优化;
2. 与后端开发工程师配合完成产品开发项目,与设计师配合实现产品的界面交互功能。

拥有以下任意特点会让你离这份工作更进一步:
1. 对code有一份执着的心态,并有自己喜欢的浏览器bug;
2. 一些著名的JS库,对你来说不只是开发工具,更是你学习架构、风格的良师益友;
3. 持续关注业界最新发展,对HTML5、NodeJS等前沿技术与其设计理念有深刻思考;
4. 熟悉或精通前端之外的一或多项技术;
5. 喜欢写博客,分享和记录你的思考或实践;
6. 有自己的开源项目,并不断学习实践新技术。

这些都不是必需的,但如果你全部符合,我们很希望你能给我们一次面试的机会(哈哈)。
对了,我们使用Python、Django、JQuery,如果你熟悉它们或能快速学习,会让你尽早开始与我们一起工作。

模块化CSS

评论数:4评论

原来写过一篇:更好的组织CSS,里面有一些我当初对于CSS写法的想法。现在这篇文章有些旧了。当初的想法虽然依旧可用,但是有了些改变。于是决定再写一篇。

CSS是完全没有逻辑的语言,可以说它不适合于团队开发。但是我们可以通过一个好的写法避免团队之间的命名冲突、相互依赖等等问题。

注:为了尽量避免js和css之间的开发关联,js的钩子基本采用id,且使用驼峰命名,不得已才会用class。CSS全部使用class作为选择符(不用id),且不适用驼峰命名方式,下面会详细解释class的命名方式。 Continue reading

网页行内排版二三事

评论数:0评论

《CSS权威指南》是一本好书,不下看了三遍了,每次翻阅依然能有收获。本文只是简单介绍一下网页中的行内样式排版的一些要点。先抛出一些关键字:

  1. 内容框
  2. 行内框
  3. 行框
  4. 基线
  5. 行内非替换元素
  6. 行内替换元素
排名不分先后,先记下这些关键字,之后会逐渐解释它们的含义。

非IE浏览器的灰阶化

评论数:2评论

最近网上疯传:“XXX死了”。所以难免过几天又要网站变黑白了。IE下面做到这点很容易,

使用滤镜就可以做到:
javascript代码:

elem.style.filter = 'progid:DXImageTransform.Microsoft.BasicImage(grayscale=1)';

CSS代码:

elem {
    filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);
    /* Element must "hasLayout"! */
    zoom: 1;
}

但是其他浏览器就比较困难了。这需要对图片和其他元素分别处理。对于其他元素比较简单,只要获取他们的color、backgroundColor、borderBottomColor,borderTopColor,borderLeftColor,borderRightColor属性值并且转换成灰阶化之后的值即可。注意这里说的是灰阶化不是去色,两者稍有不同:

// 去色 Desaturate:
function RGBtoDesat(r,g,b) {
    var average = (r + g + b) / 3;
    return {
        r: average,
        g: average,
        b: average
    };
}

// 灰阶化 Grayscale:
function RGBtoGrayscale(r,g,b) {
    var mono = parseInt( (0.2125 * r) + (0.7154 * g) + (0.0721 * b), 10 );
    return {
        r: mono,
        g: mono,
        b: mono
    };
}

所以只要遍历所有的元素,并修改他们的颜色相关属性,原颜色保留方便恢复。
但是图片元素能否被转换依赖于两件事情:

  • 浏览器是否支持canvas,以及它的getImageData方法;
  • 并且图片是同源的(不跨域)

接下来就需要依次遍历图片所有像素点的颜色值,将其灰阶化。这一过程非常的耗内存,即使是飞速的js引擎遇到了大图片也会消耗不少cpu。
这一切的工作都已经有人做好了:http://james.padolsey.com/demos/grayscale/

grayScal API
grayscale函数支持的参数不仅仅是dom,还可以是jquery对象:

var el = document.getElementById( 'myEl' );
grayscale( el );

// Alternatively, pass a DOM collection
// (all elements will get "grayscaled")
grayscale( document.getElementsByTagName('div') );

// Even works with jQuery collections:
grayscale( $('div') );

重置颜色:

grayscale.reset( el );
// reset() also accepts DOM/jQuery collections
grayscale.reset( $('div') );

prepare函数是用于处理大图片或多张小图片时候的情况,它使用了分时计算的方法防止页面UI卡死。注意图片越大需要的计算时间越多,一个300×300大小的PNG图片在prepare模式下就需要大概3秒时间。所以如果你的图片比较大那么这个方法的生效时间会相当的慢。优点是浏览器不会卡死!
The ‘prepare’ function, as discussed earlier, should be called when there’s a large image to process or even if there are several smaller images. Be aware that larger images will take quite a while to process (just a 300×300 PNG takes about 3 seconds in ‘prepare’ mode).

grayscale.prepare( document.getElementById('myEl') );
// Also accepts DOM/jQuery collections
grayscale.prepare( $('.gall_img') );

另外值得注意一点的是ie下面的灰阶化滤镜会对元素或子元素的其他滤镜产生影响。如果你使用了例如渐变这样的ie滤镜就会被影响:

elem {
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f9fcf7', endColorstr='#e6f4de');
}

所以如果你使用了其他滤镜,那么需要修改下样式。

动画主循环

评论数:4评论

今天看了下cocos2d-javascript的源代码,说实话代码好乱,可能是和它特殊的打包方式有关。以至于一般的前端代码的读法有些不管用。花了一段时间才发现它的主要动画循环的js:Direct.js

结果发现cocos2d-javascript里面动画循环代码如下:

   /**
     * The main loop is triggered again. Call this function only if
     * cocos.Directory#stopAnimation was called earlier.
     */
    startAnimation: function () {
        var animationInterval = 1.0 / this.get('maxFrameRate');
        this._animationTimer = setInterval(util.callback(this, 'drawScene'), animationInterval * 1000);
    },

它使用了setInterval这个定时器执行动画循环。因为javascript是单线程的,所以如果js的执行时间过长会导致页面卡死,如果是用setInterval,并且间隔时间小于每次计算的时间(js执行时间)那么会导致浏览器没有空隙去渲染ui,也就是界面卡死的情况。

用setInterval的优点是间隔时间是确定的,方便计算位置等参数。

不过这个优点可以忽略不计,毕竟用setTimeout可以防止卡死情况的出现。

当然setTimeout也是由缺陷的。当用户最小化窗口,或者进入另外一个tab的时候,setTimeout和setInterval还是会照样运行!这样会白白消耗内存和cpu。

虽然有些浏览器有优化,比如firefox 5的新特性:后台不活动标签页的 setTimeout 和 setInterval 限定为 1000ms。但是依旧还是在运行!所以我们希望由浏览器来决定什么时候去运行动画,这样即可以减少多余消耗,也可以让动画更刘畅。于是出现 了:requestAnimFrame。它是接受一个回调函数来执行绘制代码。但是由于各个浏览器的支持不一样,所以需要一些优雅降级。

// see http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// shim layer with setTimeout fallback

(function(){

    // chrome shipped without the time arg in m10
    var timeundefined = false;
    if (window.webkitRequestAnimationFrame){
        webkitRequestAnimationFrame(function(time){
            timeundefined = (time == undefined);
        });
    }

    window.requestAnimFrame = (function(){
      return window.requestAnimationFrame ||
              (!timeundefined && window.webkitRequestAnimationFrame) ||
              window.mozRequestAnimationFrame ||
              window.oRequestAnimationFrame ||
              window.msRequestAnimationFrame ||
              function(callback, element){
                return window.setTimeout(function(){
                    callback(+new Date);
                }, 1000 / 60);
              };
    })();

})();

2012年3月28日修改过

不过requestAnimeFrame也有个缺点:就是没有clearTimeout这样对应的函数,所以如果是用于游戏这样的循环代码是没办法从外部打断的。必须是在循环函数内部取消循环。

标准提供了cancelAnimationFrame函数,用于外部打断(感谢mdmeo的提示)。

于是我们可以把游戏里面的主循环代码写成:

window.clearRequestTimeout = function(id) {
    window.cancelAnimationFrame ? window.cancelAnimationFrame(id) :
    window.webkitCancelAnimationFrame ? window.webkitCancelAnimationFrame(id) :
    window.webkitCancelRequestAnimationFrame ? window.webkitCancelRequestAnimationFrame(id) : /* Support for legacy API */
    window.mozCancelRequestAnimationFrame ? window.mozCancelRequestAnimationFrame(id) :
    window.oCancelRequestAnimationFrame	? window.oCancelRequestAnimationFrame(id) :
    window.msCancelRequestAnimationFrame ? window.msCancelRequestAnimationFrame(id) :
    clearTimeout(id);
};
function Animation() {
    this.animeId;
    this.startAnimation = function() {
        var self = this;
        self.lastTime = +new Date();
        self.animeId = requestAnimFrame(function( time ) {
            var delayTime = time - self.lastTime;
            // doSomething( delayTime ); // do some paint and calculate
            console.log( delayTime );
            self.startAnimation();
        });
    },
    this.stopAnimation = function() {
        clearRequestTimeout( this.animeId );
    }
}

参考:

  1. https://developer.mozilla.org/en/DOM/window.mozRequestAnimationFrame
  2. http://paulirish.com/2011/requestanimationframe-for-smart-animating/
  3. https://gist.github.com/917153
  4. http://dev.chromium.org/developers/design-documents/requestanimationframe-implementation

「译」Geolocation HTML5地理定位

评论数:0评论

参考自:http://html5doctor.com/finding-your-position-with-geolocation/

Geolocation API提供了开发者获取用户位置的功能。接下来介绍下此API的相关信息。

浏览器兼容性

目前(2011-6-22)如下浏览器支持Geolocation API:

  • Firefox 3.5+
  • Chrome 5.0+
  • Safari 5.0+
  • Opera 10.60+
  • Internet Explorer 9.0+
  • Android 2.0+
  • iPhone 3.0+
  • Opera Mobile 10.1+
  • Symbian (S60 3rd & 5th generation)
  • Blackberry OS 6
  • Maemo

数据保护

此规范会将用户的位置暴露出去,所以需要用户的授权才能够使用。当你使用Geolocation api时,浏览器会提示用户“是否授权”。

地理位置

有很多方法可以定位用户的地理位置,并且每种方法都有不同的精度。桌面浏览器一般会使用WiFi(精确到20m)或者IP定位(只能精确到城市级别,并且有可能是假地址)。移动装置一般会使用GPS(精确到10m并且只能在外部使用),WiFi或GSM/CDMA网络信号定位(精确到1000m)。

使用API

先判断是否有此功能,代码如下:

if (navigator.geolocation) {
// do fancy stuff
}

返回false则不支持此api。

getCurrentPosition 或 watchPosition

这两个方法都是立即返回的,使用的是异步回调的方式来使用api。它们有相同的参数:

  1. successCallback – 成功后的回调函数
  2. [errorCallback] – 失败后的回调函数
  3. [options] – 相关配置参数:
    • enableHighAccuracy – 确保应用会给出最佳结果。这有可能会让浏览器的反应时间变慢。如果是移动装置,还有可能因为使用GPS而消耗更多电量。接受参数类型为boolean,默认为false。
    • timeout – 接受一个数字作为参数,默认为0微秒。设置浏览器的超时时间。
    • maximumAge – 表示程序能接受的被缓存位置的最大过期时间。接受一个数字作为参数,默认为0微秒。这就意味这默认每次获取位置都必需重新获取一个新位置。

clearWatch

这个方法接受一个参数,需要清理的观察进程的id:watchID(这个参数由watchPosition方法返回)。

getCurrentPositionwatchPosition方法的主要区别是watchPosition方法会持续告诉你位置的改变,所以基本上它一直在更新用户的位置。当你在移动的时候,这个功能会非常有利于追踪用户的位置。这个函数还会返回一个watchID值被clearWatch使用来停止监控。

当用户的位置被返回,它包含了一个Position对象,它包含了如下属性:

Property Details
coords.latitude 十进制表示的纬度值
coords.longitude 十进制表示的经度值
coords.altitude 以米为单位的海拔值(reference ellipsoid)
coords.accuracy 以米为单位,告诉应用经纬度值的精确度。这个用于帮助开发者决定是否使用返回的经纬度值。
coords.altitudeAccuracy 海拔的精确度
coords.heading 装置的方向,从正北顺时针方向
coords.speed 装置的移动速度(米每秒)
timestamp 获取位置时候的时间值

这些参数中只有coords.latitude, coords.longitudecoords.accuracy是保证会有的,其他的值则可能是null。

例子

if (navigator.geolocation) {
    var timeoutVal = 10 * 1000 * 1000;
    navigator.geolocation.getCurrentPosition(
       displayPosition,
       displayError,
       { enableHighAccuracy: true, timeout: timeoutVal, maximumAge: 0 }
    );
} else {
    alert("Geolocation is not supported by this browser");
}

function displayPosition(position) {
    alert("Latitude: " + position.coords.latitude + ", Longitude: " + position.coords.longitude);
}

function displayError(error) {
    var errors = {
        1: 'Permission denied',
        2: 'Position unavailable',
        3: 'Request timeout'
    };
    alert("Error: " + errors[error.code]);
}

Demo样例

「译」Cocos2d-javascript入门教程三

评论数:0评论

我的唠叨:cocos2d-iphone是iOS平台上非常不错的2D游戏引擎,它是基于python版的cocos2d设计的,这里主要说的是它的javascript版。最近打算学习下这个游戏引擎,所以特来翻译下它的相关文档。

相关系列译文:

1. Cocos2d-javascript入门教程一

2. Cocos2d-javascript入门教程二

3. Cocos2d-javascript入门教程三 Continue reading

jQuery 1.6 prop and attr

评论数:1评论

jQuery 1.6有两个改动使得它不再完全兼容旧版本,虽然说这个改动本质上来说加快了性能,遵循了html5标准,更清晰的分离了API的职责,但是心理总有些不爽,这意味着很多网站不能轻易的升级。

先来看下是哪两个改动: Continue reading