使用sass與compass合併雪碧圖(二)

上一篇文章介紹了怎樣使用compass合併雪碧圖,生成的icons.css文件中單位是px,PC端能夠直接在html文件中使用,但在移動端,咱們須要根據不一樣分辨率的屏幕,來縮放圖片大小,顯然使用px單位確定是不行的。因此須要作一下單位轉換的工做。css

移動端使用rem做爲單位是最合適不過了。並非使用了rem就能夠,還須要作一些準備工做。咱們都知道rem是基於html標籤的font-size的,因此須要使用js動態的計算htmlfont-size。這裏我使用淘寶的lib-flexiblehtml

在上一篇文章中,有講過雪碧地圖(Sprite maps),以下面:git

$icons: sprite-map("icons/*.png", $spacing: 8px, $layout: smart);

.icon {
    width: image-width(sprite-file($icons, card-icon));
    height: image-height(sprite-file($icons, card-icon));
    background-image: sprite-url($icons);
}

生成css:github

.icon {
    width: 77px;
    height: 64px;
    background-image: url('/images/icons-s37f950be3b.png');
}

如今,須要把px轉換成rem。咱們不可能在icons.css中轉換,應該在icons.scss文件中轉換。函數

icons.scss聲明一個轉換函數px2rem,:flex

@function px2rem ($px) {
    @return $px / 64px * 1rem;
}

這裏的64是由於視覺稿是640px的,若是是750px的就是75。能夠看一下lib-flexible的說明。url

加上轉換函數的icons.scss文件是這樣的:spa

$icons: sprite-map("icons/*.png", $spacing: 8px, $layout: smart);

@function px2rem ($px) {
    @return $px / 64px * 1rem;
}

.icon {
    width: px2rem(image-width(sprite-file($icons, card-icon)));
    height: px2rem(image-height(sprite-file($icons, card-icon)));
    background-image: sprite-url($icons);;
}

生成的css以下:命令行

.icon {
    width: 1.20313rem;
    height: 1rem;
    background-image: url('/images/icons-s37f950be3b.png');
}

好了,第一步轉換工做就完成了。咱們都知道,使用雪碧圖,確定要使用background-position屬性,它的單位也是px,也須要轉換,因此須要在icons.scss加上:code

$icons: sprite-map("icons/*.png", $spacing: 8px, $layout: smart);

@function px2rem ($px) {
    @return $px / 64px * 1rem;
}

.icon {
    width: px2rem(image-width(sprite-file($icons, card-icon)));
    height: px2rem(image-height(sprite-file($icons, card-icon)));
    background-image: sprite-url($icons);
    background-position: px2rem(sprite-position($icons, car-icon));
}

可是,編譯的時候出錯了,錯誤以下:

意思就是:background-position的值爲-250px 0,並不能簡單的使用px2rem函數,那該怎麼辦?咱們先來判斷一下傳遞給函數的參數的類型:

@function px2rem ($px) {
    @warn type-of($px);
    @return $px / 64px * 1rem;
}

再次編譯(能夠使用compass watch進行監聽文件的修改),命令行提示以下圖:

從圖中能夠知道:$width$height的類型是number,而$pos類型是list。知道了什麼類型就能夠對症下藥了,修改函數以下:

@function px2rem ($px) {
    @if (type-of($px) == "number") {
        @return $px / 64px * 1rem;
    }

    @if (type-of($px) == "list") {
        @return nth($px, 1) / 64px *1rem nth($px, 2) / 64px * 1rem;
    }
}

nth方法能夠取出list中的每一項進行運算,輸出css以下:

.icon {
    width: 1.20313rem;
    height: 1rem;
    background-image: url('/images/icons-s37f950be3b.png');
    background-position: -1.46875rem -1.40625rem;
}

這邊又會有個問題:background-position的值有多是0 00 100px或者100px 0,而0是沒有單位的,這樣轉換的時候會報錯,繼續對px2rem函數進行改造,以下:

@function px2rem ($px) {
    @if (type-of($px) == "number") {
        @return $px / 64px * 1rem;
    }

    @if (type-of($px) == "list") {
        @if (nth($px, 1) == 0 and nth($px, 2) != 0) {
            @return 0 nth($px, 2) / 64px * 1rem;
        } @else if (nth($px, 1) == 0 and nth($px, 2) == 0) {
            @return 0 0;
        } @else if (nth($px, 1) != 0 and nth($px, 2) == 0) {
            @return nth($px, 1) / 64px * 1rem 0;
        } @else {
            @return nth($px, 1) / 64px *1rem nth($px, 2) / 64px * 1rem;
        }
    }
}

上面對各類爲0的狀況進行了判斷,避免了錯誤。

下面還須要對background-size屬性進行轉換。在PC端若是圖片不要縮放的話,其實不須要該屬性,但在移動端通常是須要的。在移動端,可能不少人不知道該怎麼用background-size屬性,究竟是設置整個雪碧圖的大小,仍是設置單個sprite的的大小呢?實際上是設置整個雪碧圖的大小。

好像compass沒有內置的方法得到雪碧圖的大小,不要緊,咱們能夠等到雪碧圖生成的時候,再去查看雪碧圖的大小。能夠先用兩個變量保存雪碧圖的寬高,初始化爲0

$bigWidth: 0;
$bigHeight: 0;

等雪碧圖生成後,查看圖片大小,再修改,如:

$bigWidth: 242px;
$bigHeight: 270px;

這時icons.scss文件內容以下:

$icons: sprite-map("icons/*.png", $spacing: 8px, $layout: smart);

$bigWidth: 242px;
$bigHeight: 270px;

@function px2rem ($px) {
    @if (type-of($px) == "number") {
        @return $px / 64px * 1rem;
    }
    
    @if (type-of($px) == "list") {
        @if (nth($px, 1) == 0 and nth($px, 2) != 0) {
            @return 0 nth($px, 2) / 64px * 1rem;
        } @else if (nth($px, 1) == 0 and nth($px, 2) == 0)  {
            @return 0 0;
        } @else if (nth($px, 1) != 0 and nth($px, 2) == 0) {
            @return nth($px, 1) / 64px * 1rem 0;
        } @else {
            @return nth($px, 1) / 64px *1rem nth($px, 2) / 64px * 1rem;
        }
    }
}

.icon {
    width: px2rem(image-width(sprite-file($icons, card-icon)));
    height: px2rem(image-height(sprite-file($icons, card-icon)));
    background-image: sprite-url($icons);
    background-position: px2rem(sprite-position($icons, card-icon));
    background-size: px2rem(($bigWidth, $bigHeight));
    background-repeat: no-repeat;
}

生成css以下:

.icon {
    width: 1.20313rem;
    height: 1rem;
    background-image: url('/images/icons-s37f950be3b.png');
    background-position: -1.46875rem -1.40625rem;
    background-size: 3.78125rem 4.21875rem;
    background-repeat: no-repeat;
}

到這裏,應該能夠說是很完美了,但還有改進的空間。咱們須要自定義不少類,如:

.icon1 {
    width: px2rem(image-width(sprite-file($icons, card-icon)));
    height: px2rem(image-height(sprite-file($icons, card-icon)));
    background-image: sprite-url($icons);
    background-position: px2rem(sprite-position($icons, card-icon));
    background-size: px2rem(($bigWidth, $bigHeight));
    background-repeat: no-repeat;
}

.icon2 {
    width: px2rem(image-width(sprite-file($icons, watch-icon)));
    height: px2rem(image-height(sprite-file($icons, watch-icon)));
    background-image: sprite-url($icons);
    background-position: px2rem(sprite-position($icons, watch-icon));
    background-size: px2rem(($bigWidth, $bigHeight));
    background-repeat: no-repeat;
}

......

上面的每一個類中的屬性都是同樣的,爲何不使用一個mixin,把相同的屬性都放進這個mixin中,而後在每一個類中引入就能夠了。下面來定義一個mixin

@mixin sprite-info ($icons, $name) {
    width: px2rem(image-width(sprite-file($icons, $name)));
    height: px2rem(image-height(sprite-file($icons, $name)));
    background-image: sprite-url($icons);
    background-position: px2rem(sprite-position($icons, $name));
    background-size: px2rem(($bigWidth, $bigHeight));
    background-repeat: no-repeat;
}

使用這個mixin

.card {
    @include sprite-info($icons, card-icon);    
}

.watch {
    @include sprite-info($icons, watch-icon);   
}

生成css以下:

.card {
    width: 1.20313rem;
    height: 1rem;
    background-image: url('/images/icons-s37f950be3b.png');
    background-position: -1.46875rem -1.40625rem;
    background-size: 3.78125rem 4.21875rem;
    background-repeat: no-repeat;
}

.watch {
    width: 1.3125rem;
    height: 1.40625rem;
    background-image: url('/images/icons-s37f950be3b.png');
    background-position: 0 0;
    background-size: 3.78125rem 4.21875rem;
    background-repeat: no-repeat;
}

如今能夠說是很是完美了。下面貼出icons.scss文件中最終的代碼:

$icons: sprite-map("icons/*.png", $spacing: 8px, $layout: smart);

$bigWidth: 242px;
$bigHeight: 270px;

@function px2rem ($px) {
    @if (type-of($px) == "number") {
        @return $px / 64px * 1rem;
    }

    @if (type-of($px) == "list") {
        @if (nth($px, 1) == 0 and nth($px, 2) != 0) {
            @return 0 nth($px, 2) / 64px * 1rem;
        } @else if (nth($px, 1) == 0 and nth($px, 2) == 0)  {
            @return 0 0;
        } @else if (nth($px, 1) != 0 and nth($px, 2) == 0) {
            @return nth($px, 1) / 64px * 1rem 0;
        } @else {
            @return nth($px, 1) / 64px *1rem nth($px, 2) / 64px * 1rem;
        }
    }
}

@mixin sprite-info ($icons, $name) {
    width: px2rem(image-width(sprite-file($icons, $name)));
    height: px2rem(image-height(sprite-file($icons, $name)));
    background-image: sprite-url($icons);
    background-position: px2rem(sprite-position($icons, $name));
    background-size: px2rem(($bigWidth, $bigHeight));
    background-repeat: no-repeat;
}

.card {
    @include sprite-info($icons, card-icon);
}

.watch {
    @include sprite-info($icons, watch-icon);
}

生成的icons.css代碼以下:

.card {
    width: 1.20313rem;
    height: 1rem;
    background-image: url('/images/icons-s37f950be3b.png');
    background-position: -1.46875rem -1.40625rem;
    background-size: 3.78125rem 4.21875rem;
    background-repeat: no-repeat;
}

.watch {
    width: 1.3125rem;
    height: 1.40625rem;
    background-image: url('/images/icons-s37f950be3b.png');
    background-position: 0 0;
    background-size: 3.78125rem 4.21875rem;
    background-repeat: no-repeat;
}
相關文章
相關標籤/搜索