什么是点九图
Android平台里有一种特殊的图片形式,文件扩展名 xxx.9.png,为了方便记忆,所以称其为点九图,英文是 Nine Patch。
应用场景
当我们需要为一段文字添加图片背景,而我们并不知道这段文字的长度和宽度,该如何解决?
一个图片在不同的分辨率下,边角会失真,如何解决?
思考💡:我们怎么做到对图片进行部分拉伸,如果可以实现部分拉伸,那就可以解决上述的场景
对比图
在日常开发中,我们很多时候都会处理这样的场景,就是ui提供了背景图片,但是背景图片可能宽度不够,我们就肆意的拉伸来满足需求,但是实践发现,拉伸的图片会模糊,这个时候我们就需要用点九图处理
看一下对比图
上面的是肆意拉伸的结果,下面是用点九图拉伸的结果,点九图的制作主要跟下面几个属性有关,依次学习一下
border-image
border-image 属性可以通过一些简单的规则,将一副图像划分为 9 个单独的部分,浏览器会自动使用相应的部分来替换边框的默认样式。
border-image是border-image-source || border-image-slice|| border-image-width|| border-image-outset || border-image-repeat 属性的简写
其中,border-image-width 通常省略,取border-width的值,border-image-outset也很少用。所以实际应用中最常用的写法就是:border-image: source slice round;
我们常见的格式可能就是 border-image: url('./image/link-on.png') 20 14 20 14 fill stretch stretch;
border-image-source:定义边框图像的路径;
border-image-slice:定义边框图像从什么位置开始分割;
border-image-width:定义边框图像的厚度(宽度);
border-image-outset:定义边框图像的外延尺寸(边框图像区域超出边框的量);
border-image-repeat:定义边框图像的平铺方式
url
url就不解释了
border-image-slice
主要解释一下border-image-slice,这个代表把我们的图片怎么切割,切割的值是1~4个,不用写单位的,默认值就是px,对应css的常见规则 上 右 下 左,我们把图片切割四刀,就会形成一个九空格了,切割出来的四个角是不变的,那拉伸的时候,只有图中的5 8 9 6 7 这5个部分会被拉伸,那我们接着学一下拉伸border-image-repeat
border-image-repeat
border-image-repeat 属性用来设置如何填充使用 border-image-slice 属性分割的图像边框,例如平铺、拉伸等等,该属性的语法格式如下
border-image-repeat:stretch | repeat | round
1.stretch(拉伸)默认值
border-image:url() 27 stretch(水平和垂直方向都是拉伸)
就像上面所说的那样,边角的不会发生变化,水平的部分就是水平拉伸,垂直部分就是垂直拉伸,很明显
2.round(平铺)
border-image:url() 27 round(水平和垂直都是平铺)
和上图进行对比会发现,这就是重复,而且重复的还是除了边角之外的部分,这个重复得很整齐,也就是说这个并没有多出一部分不能完好的放置,而是每一个都很完整,这就是平铺和重复的区别了,再往下看就知道了。
3.repeat(重复)
border-image:url() 27 repeat(水平和垂直都是重复)
小总结
1.border-image的常用参数有三个,分别是图片链接,裁剪位置,重复方式
2.裁剪位置是按照上右下左顺时针的方式进行裁剪,即离上面多少,离右边多少,离下面多少,离左边多少
3.在进行变化的时候,边角是不发生变化的
4.第三个参数分为水平和垂直的变化,当只有一个参数时,表示水平和垂直的变化相同,round和repeat重复方式的区别在于round会将要重复的内容进行等比例的缩放来实现不重叠的效果,而repeat就是单纯的重复,可能会产生重叠的效果(注意:这里说的是可能会,因为如果裁剪的大小刚好的话就不会发生重叠的效果,此时round和repeat的效果相同)
border-width和border-image-width的区别
思考💡:border-image-width 和 border-width 各自的作用是什么?通过两个例子来看
上图中,border-width 是30px,border-image-width 是15px,所以边框图片被缩小成15px的尺寸填充到border里面。
再看上图,border-width 还是30px,border-image-width 是60px,所以边框图片被放大到60px的尺寸填充到border里面,甚至超出了border区域,延伸到盒子的background当中。
所以,border-image图片填充的区域大小,取决于 border-image-width ,跟素材图尺寸无关,跟border-width也无关。只是在不设置border-image-width的时候,它的值默认等于border-width
最后,border-width要在border-image之前设置,否则在chrome可能显示不正确。
案例
案例1
把我们前面提到的对比图,展示一下,原图是这样的
那我再拉伸的时候,自然是想保持四个角不变 ,这里介绍一个好用的点九图网站
通过这个网站的解析,我们很容易得到我们的切割值,下面看一下核心代码
.jiu-bg {
width: 273px;
border-width: 20px;
border-style: solid;
border-image: url('./image/link-on.png') 20 14 20 14 fill stretch;
}
案例2
想要的效果是这样的
原图是这样的
通过网站获取切割值,因为我们无论怎么拉伸,都不希望四个不规则顶角边框变化,所以
核心代码
.jiu-bg {
width: 1024px;
min-height: 300px;
border: 58px solid transparent;
border-image: url('./image/test.png') 58 58 fill stretch;
}
体会一下fill,如果没有fill会是什么样的 border-image: url('./image/test.png') 58 58 stretch;
案例3
需求图是这样的,手机端的气泡图的原理就是点九图实现的
原图是这样的
核心代码
<html>
<head>
<title>border-image</title>
</head>
<style>
body{
background: black;
}
.con{
height: 220px;
padding: 0px 50px;
width: fit-content;
color: white;
border-width: 1px;
border-style: solid;
border-image: url('./image/test2.webp') 0 170 0 170 fill / 1px 170px stretch;
}
.ctn{
position: relative;
top: 96px;
}
</style>
<body>
<img id="img" src="image.png" />
<div class="con">
<span class="ctn">我是内容我是内容我是内容我是内容我是内容我是内容</span>
</div>
</body>
</html>
主要解释一下border-image: url("image.png") 0 170 0 170 fill / 1px 170px stretch
因为不在乎高度,只管左右的拉伸,所以上下切割0,左右各选了170像素,这个部分是不会因为width增加而改变的。 fill字段就是让两个| | 中间的部分填充背景
后面的1px 170px
指的是border-image-width ,字面意思是边框图片宽度,上下是1px,左右是170px