High DPI Canvas 高分辨率Canvas(譯)

此文章為譯文古程,作者:Paul Lewis 寫于:2012-8-25
原文地址:http://www.html5rocks.com/en/tutorials/canvas/hidpi/?redirect_from_locale=zh
由于原文編寫時間已經(jīng)比較久遠(yuǎn)鳄虱,BackingStorePixelRatio屬性已經(jīng)被棄用了捉偏,所以本文做一些修改折欠。
感謝 @玄魂 的提醒叠萍。

HIDPI屏幕是一個非常棒的東西造壮,他讓一切變得清晰渡讼。這也讓我們開發(fā)者遇到了一些新的挑戰(zhàn)。在本文中耳璧,我們將研究在如何在HIDPI的屏幕上使用canvas繪制高清的圖片成箫。

設(shè)備像素比(window.devicePixelRatio)

讓我們開始吧!回到之前談到的旨枯,HIDPI的屏幕上的像素(邏輯像素)蹬昌,我們可以當(dāng)做是正常的像素(css中設(shè)置的像素),你可以正常使用它攀隔。如果你畫一個100px的東西皂贩,他也就是一個100px的東西栖榨。但是,在出現(xiàn)了一些高分辨率屏幕的手機(jī)之后明刷,一個屬性devicePixelRatio就一起出現(xiàn)了治泥。它允許我們?nèi)ゲ樵冊O(shè)備像素比。在這里我們需要拋出一個名詞邏輯像素遮精,也就是在css設(shè)置的100px時居夹,在iphone4S(devicePixelRatio為2)上,實(shí)際渲染的是200px的物理像素本冲。

這個屬性是非常有意思的准脂。但是這對于我們開發(fā)者的影響是什么呢?早些時候檬洞,我們注意到當(dāng)我們向這種高分辨率的屏幕添加img的時候狸膏,我們的圖形受到devicePixelRatio的影響變得非常模糊。
如何解決這個問題呢添怔?我發(fā)現(xiàn)如果我把img的寬和高分別與devicePixelRatio相乘湾戳,得到的大小畫進(jìn)屏幕中,在對齊進(jìn)行縮放devicePixelRatio的大小广料。Img就會以一種高清的方式呈現(xiàn)砾脑。

BackingStorePixelRatio(此屬性已被棄用,詳情查閱

那么在canvas中是怎么樣的呢艾杏?在桌面版chrmoe與safari6會有不同的表現(xiàn)韧衣。并且在這里又需要拋出一個新的名詞webkitBackingStorePixelRatio。目前只在webkit上出現(xiàn)(2012年购桑。2016年5月27測試畅铭,只有Safari有這個屬性。勃蜘。硕噩。。)缭贡,火狐與微軟可能在未來支持炉擅。
簡單的說BackingStorePixelRatio就告訴瀏覽器canvas背后的緩存區(qū)的像素比。如果我們說一張圖片的寬度為200px但是webkitBackingStorPixelRatio為2匀归。在canvas緩存區(qū)中真的數(shù)據(jù)九尾400px
坑资。

canvas-backingstore.png

#具體差異
在擁有高清屏幕的Macbook Pro上,Safari與chrome的表現(xiàn)并不相同穆端。Safari上webkitBackingStorePixelRatio的值是2,devicePoxelRatio的值也是2仿便,但是在chrome上webkitBackingStorePixelRatio的值是1体啰,devicePoxelRatio的值是2攒巍。也就是說在Safari上我們的圖形會自動以一種清晰的方式呈現(xiàn),而在chrome上他是被模糊的荒勇。

chrome與Safari的顯示差異

所以我們會發(fā)問柒莉,為什么chrome不能與Safari一樣自動適應(yīng)高清的圖形輸出呢?

實(shí)現(xiàn)

所以我們只能自己去適應(yīng)沽翔。解決的辦法也想到簡單

upsize your canvas width and height by devicePixelRatio / webkitBackingStorePixelRatio and then use CSS to scale it back down to the logical pixel size you want.

放大devicePixelRatio 倍canvas的寬高兢孝,然后用css在縮小回到你想要的理想像素。就比如仅偎,之前我們了解到高清屏幕設(shè)備的chrome中devicePixelRatio = 2跨蟹。所以將canvas的寬和高會放大 2 被,相當(dāng)于 * 2橘沥。然后使用css縮放會原來的大小窗轩。
最后我們需要考慮到,我們手動把畫布放大了2倍座咆,又通過css把他的樣式大小縮放回去原來的大小痢艺。這里會造成畫布里的圖形有縮放的問題,所以我們需要縮放回去介陶。
具體的代碼如

/**
 * Writes an image into a canvas taking into
 * account the backing store pixel ratio and
 * the device pixel ratio.
 *
 * @author Paul Lewis
 * @param {Object} opts The params for drawing an image to the canvas
 */
function drawImage(opts) {

    if(!opts.canvas) {
        throw("A canvas is required");
    }
    if(!opts.image) {
        throw("Image is required");
    }

    // get the canvas and context
    var canvas = opts.canvas,
        context = canvas.getContext('2d'),
        image = opts.image,

    // now default all the dimension info
        srcx = opts.srcx || 0,
        srcy = opts.srcy || 0,
        srcw = opts.srcw || image.naturalWidth,
        srch = opts.srch || image.naturalHeight,
        desx = opts.desx || srcx,
        desy = opts.desy || srcy,
        desw = opts.desw || srcw,
        desh = opts.desh || srch,
        auto = opts.auto,

    // finally query the various pixel ratios
        devicePixelRatio = window.devicePixelRatio || 1,
    // backingStoreRatio此屬性已被棄用
    //  backingStoreRatio = context.webkitBackingStorePixelRatio ||
                            context.mozBackingStorePixelRatio ||
                            context.msBackingStorePixelRatio ||
                            context.oBackingStorePixelRatio ||
                            context.backingStorePixelRatio || 1,

       // ratio = devicePixelRatio / backingStoreRatio;
          ratio = devicePixelRatio;

    // ensure we have a value set for auto.
    // If auto is set to false then we
    // will simply not upscale the canvas
    // and the default behaviour will be maintained
    if (typeof auto === 'undefined') {
        auto = true;
    }

    // upscale the canvas if the two ratios don't match
    // if (auto && devicePixelRatio !== backingStoreRatio) {
    if (auto && devicePixelRatio) {
        var oldWidth = canvas.width;
        var oldHeight = canvas.height;

        canvas.width = oldWidth * ratio;
        canvas.height = oldHeight * ratio;

        canvas.style.width = oldWidth + 'px';
        canvas.style.height = oldHeight + 'px';

        // now scale the context to counter
        // the fact that we've manually scaled
        // our canvas element
        context.scale(ratio, ratio);

    }

    context.drawImage(pic, srcx, srcy, srcw, srch, desx, desy, desw, desh);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末堤舒,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子哺呜,更是在濱河造成了極大的恐慌植酥,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弦牡,死亡現(xiàn)場離奇詭異友驮,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)驾锰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門卸留,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人椭豫,你說我怎么就攤上這事耻瑟。” “怎么了赏酥?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵喳整,是天一觀的道長。 經(jīng)常有香客問我裸扶,道長框都,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任呵晨,我火速辦了婚禮魏保,結(jié)果婚禮上熬尺,老公的妹妹穿的比我還像新娘。我一直安慰自己谓罗,他們只是感情好粱哼,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著檩咱,像睡著了一般揭措。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上刻蚯,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天绊含,我揣著相機(jī)與錄音,去河邊找鬼芦倒。 笑死艺挪,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的兵扬。 我是一名探鬼主播麻裳,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼器钟!你這毒婦竟也來了津坑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤傲霸,失蹤者是張志新(化名)和其女友劉穎疆瑰,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體昙啄,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡穆役,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了梳凛。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片耿币。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖韧拒,靈堂內(nèi)的尸體忽然破棺而出淹接,到底是詐尸還是另有隱情,我是刑警寧澤叛溢,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布塑悼,位于F島的核電站,受9級特大地震影響楷掉,放射性物質(zhì)發(fā)生泄漏厢蒜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望郭怪。 院中可真熱鬧支示,春花似錦刊橘、人聲如沸鄙才。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽攒庵。三九已至,卻和暖如春败晴,著一層夾襖步出監(jiān)牢的瞬間浓冒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工尖坤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留稳懒,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓慢味,卻偏偏與公主長得像场梆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子纯路,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容