本系列会持续分享本人学习到的CSS知识点、技巧和效果展示。如有错误,希望您能指出。
前段时间有一位大牛分享的几道微信的面试题,其中一道是求一个元素的background-color的题目,鉴于对这道题目的学习,我写下了这篇文章。
优先级的计算规则
!important 这个关键字的优先级最高。要优化考虑使用样式规则的优先级来解决问题而不是 !important.
下面要引入特殊值 0,0,0,0 每一位为0~255(基本上不会超过255的)
内联样式. 记做: 1,0,0,0
- 然后是ID选择器. 记做: 0,1,0,0
- 类选择器、属性选择器和伪类选择器. 记做: 0,0,1,0
- 元素选择器和伪元素选择器. 记做: 0,0,0,1
- 通用选择器(星号)、组合符合(+,>,~,” “)和否定伪类(:not())不影响优先级.
如果他们的优先级一样的话,则是后声明的样式覆盖前面声明的样式.
举个简单的栗子:
a:hover {
color: red;
}
a:link {
color: yellow;
}
根据以上的计算规则我们可以得到 a:hover的优先级为 0,0,1,1,a:link的优先级也为 0,0,1,1。所以a:link的样式覆盖了a:hover。所以我们平常写这两个的不同样式时会把hover放在link的后面。
原生JS获取元素的样式
可能很多人用惯了jquery,突然让你用原生JS获取一个div的背景颜色,高高兴兴的搜了一个element.style.backgroundColor,然后一脸懵逼,为什么没有值?
var d = document.querySelector('#d1');
d.style.backgroundColor; //为什么它有时间没有值。
因为style不能读取样式表中的样式,是不是很尴尬!接下来让我们来感受一下JS的魅力:
/**
* 将属性名转化为驼峰命名格式
*/
function camelize(str) {
return str.replace(/-(\w)/g, function (matchStr, p1) {
return p1.toUpperCase();
})
}
function getStyle(element, name) {
if (!element || !name) {
return false;
}
//查看内敛样式是否存在 它的优先级最高 !important这里不考虑
var value = element.style[name];
if (value) {
return value;
}
if (element.currentStyle) {
//IE中
value = element.currentStyle[name];
} else {
if (window.getComputedStyle) {
//标准浏览器
value = window.getComputedStyle(element, null).getPropertyValue(name);
}
}
return value;
}
是不是感觉其实原生的JS也是那么的优美,只是浏览器的兼容性埋没它的美丽。以上是个简单的获取元素某个样式属性的方法。其中还有很多问题,比如说!important。。。
在下面微信面试题求解的方法这篇文章的评论中,有人提到了用canvas的方式。然后我查阅了文档,看到了Drawing DOM Content To Canvas这篇文章,不过通过实践,发现通过svg将html元素转化图片,再填入到canvas中的方式,外部样式表并不能起作用。这就尴尬了,可能是我对那篇文章理解的还不够深刻(如果有人遇到同样的问题,能够指点一下),最终我选择了通过html2canvas插件实现我的需求。
- 获取到目标元素的位置信息
- 去除目标元素的后代元素, 以防止造成干扰判断。
- 对整个页面进行截图,回调函数中恢复目标元素的后代节点。
- 获取目标元素的像素集合。
- 因为只能获取到一个个的像素点,我这里只想到了去掉border区域的其他的某点颜色作为背景颜色。
这里只能判断纯色背景(好像有点蠢),有更好的判断方法,请留言指点。
直接上代码:
const canvas = document.createElement('canvas'),
context = canvas.getContext('2d'),
div = document.querySelector('.demo1');
const rect = div.getBoundingClientRect(), //获取元素的位置信息
x = rect.left,
y = rect.top,
w = rect.width,
h = rect.height;
canvas.width = document.body.clientWidth;
canvas.height = document.body.clientHeight;
function getColor() {
//去掉目标元素的后代元素
let childnodes = removeChilds(div);
//对页面进行截屏
html2canvas(document.body, {canvas: canvas}).then((canvas) => {
//获取目标元素的像素集合
const imageData = context.getImageData(x,y,w,h);
//恢复目标元素的后代元素
addChilds(div, childnodes);
childnodes = null;
/**
* 去掉border的影响
*/
const border = parseInt(getStyle(div,"border-width"));
const index = (border * w + border) * 4;
const r = imageData.data[index],
g = imageData.data[index + 1],
b = imageData.data[index + 2],
a = imageData.data[index + 3];
console.log("rgba(" + r + "," + g + "," + b + "," + a + ")");
});
}
//剥离后代元素
function removeChilds(element) {
let eleArray = Array.from(element.childNodes);
eleArray.forEach((item) => {
element.removeChild(item);
})
return eleArray;
}
//加上后代元素
function addChilds(element, nodes) {
nodes.forEach((item) => {
element.appendChild(item);
})
}
到这里,这个题目也告一段落了。哈哈,感觉您用心的看完,给你点个赞。如果文章有误,望君评论指点。
参考文章:
* MDN
* 王美建的文章
* 微信面试题求解的方法
* Drawing DOM Content To Canvas