zoukankan      html  css  js  c++  java
  • 使用sass与compass合并雪碧图(二)

    上一篇文章介绍了怎样使用compass合并雪碧图,生成的icons.css文件中单位是px,PC端可以直接在html文件中使用,但在移动端,我们需要根据不同分辨率的屏幕,来缩放图片大小,显然使用px单位肯定是不行的。所以需要做一下单位转换的工作。

    移动端使用rem作为单位是最合适不过了。并不是使用了rem就可以,还需要做一些准备工作。我们都知道rem是基于html标签的font-size的,所以需要使用js动态的计算htmlfont-size。这里我使用淘宝的lib-flexible

    在上一篇文章中,有讲过雪碧地图(Sprite maps),如下面:

    $icons: sprite-map("icons/*.png", $spacing: 8px, $layout: smart);
    
    .icon {
    	 image-width(sprite-file($icons, card-icon));
    	height: image-height(sprite-file($icons, card-icon));
    	background-image: sprite-url($icons);
    }
    

    生成css:

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

    现在,需要把px转换成rem。我们不可能在icons.css中转换,应该在icons.scss文件中转换。

    icons.scss声明一个转换函数px2rem,:

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

    这里的64是因为视觉稿是640px的,如果是750px的就是75。可以看一下lib-flexible的说明。

    加上转换函数的icons.scss文件是这样的:

    $icons: sprite-map("icons/*.png", $spacing: 8px, $layout: smart);
    
    @function px2rem ($px) {
    	@return $px / 64px * 1rem;
    }
    
    .icon {
    	 px2rem(image-width(sprite-file($icons, card-icon)));
    	height: px2rem(image-height(sprite-file($icons, card-icon)));
    	background-image: sprite-url($icons);;
    }
    

    生成的css如下:

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

    好了,第一步转换工作就完成了。我们都知道,使用雪碧图,肯定要使用background-position属性,它的单位也是px,也需要转换,所以需要在icons.scss加上:

    $icons: sprite-map("icons/*.png", $spacing: 8px, $layout: smart);
    
    @function px2rem ($px) {
    	@return $px / 64px * 1rem;
    }
    
    .icon {
    	 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 {
    	 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 {
    	 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 {
    	 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 {
    	 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 {
    	 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) {
    	 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 {
    	 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 {
    	 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) {
    	 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 {
    	 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 {
    	 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;
    }
  • 相关阅读:
    restframework 生成接口文档
    django simpleRoute 简化路由
    django 视图GenericView
    备份问题-原生问题
    django 中如何使用celery 和redis
    主外键定义与主从表关系
    django restframework 钩子函数:全局钩子和局部钩子
    QuerySet Django 几个必会方法
    django restframework -模型序列化高级用法终极篇
    django User.objects.get()报错 raise self.model.DoesNotExist手动处理解决办法
  • 原文地址:https://www.cnblogs.com/xljzlw/p/4771103.html
Copyright © 2011-2022 走看看