您好,尊贵的会员先生,有什么能帮到您的吗?
哦,似乎有什么不对,让我看看,您没有自己的头像框?
您可是最尊贵的会员,居然没有自己的头像框,这太不可思议了。
掘金怎么能让您受到这种屈辱,我发誓,我会用42码的大靴子狠狠地踢他屁股,并且让他吃下隔壁玛丽苏太太做的苹果派,这是他应得的惩罚。--- 沃兹基 ● 硕德
言归正传,以上纯属玩笑,但是作为尊贵的掘金会员,没有自己的头像框来彰显自己的尊贵,确实让我很郁闷。
好在身为程序猿,尤其是前端高级CV工程师,没有便自己创造。
效果
说明
- 因为是要更改第三方页面的内容,结合本人目前的技术栈,选用浏览器插件比较合适;
- 插件操作页面主要有四个部分,分别是选头像框区域、选择需要处理的头像、执行结果区域、按钮操作区域;
- 基本操作就是选中头像框,再选中需要处理的头像(页面上的全部头像、导航栏的头像,或者指定用户名称的头像),点击添加即可;
- 该插件内置了四款头像框可用,如果需要,可以在项目中
popup/avatarBorderList.js文件中添加; - 添加边框基本原理是为头像图片添加一个
span元素,将头像图片放于span中,所以自定义的头像框中的字段说明如下:
{
"name": "头像框名称",
"value": {
"element": "span样式",
"before": "span::before样式",
"after": "span::after样式",
"other": "其他样式,如动画。。。。"
}
}
项目地址
基本实现
获取头像
既然是为头像添加边框,那么自然就需要获取到头像的DOM元素,本插件中,获取头像的方法有三种:
- 获取页面已有的全部头像,不包括未加载、未渲染的头像:
document.querySelectorAll('.avatar')
- 只获取导航栏的头像,这个也是比较简单:
document.querySelectorAll('.main-nav .avatar')
- 指定用户名称的头像:这种比较麻烦,一般头像
img元素的alt属性上会带有用户名称:
但是,有时又会没有,显示undefine:
所以按照用户名称查找时,除了查找图片元素之外,还得查找含有用户名称的元素,两方面同时搜索:
// 获取指定用户名称的头像框
const allAvatarElement = document.querySelectorAll('.avatar')
const userName = avatarCondition[2].value
const list = []
// 按照用户名称对 img 元素进行过滤
for (let i = 0, len = allAvatarElement.length; i < len; i++) {
const item = allAvatarElement[i]
item.alt.includes(userName) && list.push(item)
}
// 部分 img.alt 属性获取不到用户名称,只能按照用户名称查找方式
const userNameList = document.querySelectorAll('.username') // 获取页面上的全部用户名称
for (let i = 0, len = userNameList.length; i < len; i++) {
const item = userNameList[i]
if (item.innerText.includes(userName)) {
// 如果用户名称拥有指定字段,查找相应的 img 元素
const target = item.parentNode.parentNode.parentNode.querySelector('.avatar')
target && list.push(target)
}
}
添加头像框
添加头像框时,需要先把定义好的样式注入到页面中,这样头像框的类.my-avatar-border才能获取到样式:
// 获取选中的样式
const css = avatarBorderList.find(item => item.name === currentAvatarBorder)
// 将选中的样式拼接成最终样式
currentCssValue = css && css.value ?
`.${myAvatarBorderClassName}{${css.value.element};box-sizing: border-box;}
.${myAvatarBorderClassName}::after{${css.value.after}}
.${myAvatarBorderClassName}::before{${css.value.before}}
${css.value.other}` : ''
// 注入样式
chrome.scripting.insertCSS({ target: { tabId: tab.id }, css: currentCssValue })
处理好样式之后,就是给指定头像添加边框元素。将头像img元素取出,包裹上一层span元素,其类名为my-avatar-border:
// 创建包裹 img 的 span
const avatarBorder = document.createElement('span')
// 给 span 添加类名
avatarBorder.classList.add('my-avatar-border')
// 遍历选中的 img, 逐个添加 span
for (let i = 0, len = avatarElementList.length; i < len; i++) {
const targetAvatarElement = avatarElementList[i]
// 克隆创建的 span
const cloneElement = avatarBorder.cloneNode(true)
// 将 span 设定为于 img 同样的宽高
cloneElement.style = `display:inline-block;width: ${targetAvatarElement.clientWidth}px;height: ${targetAvatarElement.clientHeight}px;`
// 将 img 放入 span中,再将 span 放入 img.parentNode中
const parentNode = targetAvatarElement.parentNode
cloneElement.appendChild(targetAvatarElement)
parentNode.appendChild(cloneElement)
}
移除头像框
首先需要移除之前注入页面的样式:
// 删除注入的样式表
chrome.scripting.removeCSS({ target: { tabId: tab.id }, css: currentCssValue })
然后将所有 span.my-avatar-border删除:
// 获取 span 元素
const avatarBorderElementList = document.querySelectorAll(`.${myAvatarBorderClassName}`)
for (let i = 0, len = avatarBorderElementList.length; i < len; i++) {
// 将 span 删除,将 img 放回原处
const target = avatarBorderElementList[i]
const parentNode = target.parentNode
const img = target.childNodes[0]
parentNode.removeChild(target)
parentNode.append(img)
}
自定义头像框
本插件只有预设四种头像框,如果需要更多的头像框效果,可以在项目中popup/avatarBorderList.js文件中设置,文件内容如下:
export default [
{
"name": "头像框名称",
"value": {
"element": "span样式",
"before": "span::before样式",
"after": "span::after样式",
"other": "其他样式,如动画。。。。"
}
},
...
]
其中other可以用来定义一些其他样式,比如动画或者其他元素样式,如:
"other": `
@keyframes rotateBorder {
0% {
transform: rotateZ(0);
}
100% {
transform: rotateZ(720deg);
}
}
.my-avatar-border img {
z-index: 1;
}
`
预设的边框展示
我正在参加「创意开发 投稿大赛」详情请看:掘金创意开发大赛来了!