缘起
疫情在家,闲的没事,便重新翻开 html5 和 css3 文档学习,在看到 css 的 box-shadow 时突发奇想,能不能用这个效果绘制图片。
原理
box-shadow: 15px 10px 0px 5px rgb(255,255,255);
上面是一个简单 box-shadow 特效,15px 代表 x 轴值,10px 代表 Y 轴,0px 代表模糊值,5px 代表阴影的尺寸,最后一个是颜色。x 和 y 值是必选,其他都是可选。
我们先写一个简单 demo,模糊值和阴影值都设为 0 排序,代码如下:
<style>
.container{
width:30px;
height:30px;
background:red;
box-shadow:35px 35px rgb(0,0,0);
}
</style>
<div class="container"></div>
效果如下:
然后修改 style,将其改为下面:
<style>
.container{
width:1px;
height:1px;
background:red;
border-radius: 50%;
box-shadow:35px 35px rgb(0,0,0);
}
</style>
<div class="container"></div>
效果如下:
这个时候 div 和其阴影都变成了圆点,可以更改阴影的 x,y 值移动,例如绘制一条直线的代码如下:
<style>
.container {
width: 1px;
height: 1px;
border-radius: 50%;
background: red;
box-shadow: 35px 35px rgb(0, 0, 0),
36px 35px rgb(0, 0, 0),
37px 35px rgb(0, 0, 0),
38px 35px rgb(0, 0, 0),
39px 35px rgb(0, 0, 0),
40px 35px rgb(0, 0, 0),
41px 35px rgb(0, 0, 0),
42px 35px rgb(0, 0, 0),
43px 35px rgb(0, 0, 0),
44px 35px rgb(0, 0, 0),
45px 35px rgb(0, 0, 0);
}
</style>
<div class="container"></div>
效果如下:
初中就学过点动成线,线动成面,而图片也是一个个像素点组成,所以我们只需要将这些像素点的坐标和该坐标对应的颜色值找到就可以用阴影来绘制出来。
Python 代码实现
Python里面有一个处理图片的 PIL 库,首先使用 pip 安装这个库,然后开始编写代码。
def transform(image_file):
# 转换图片的模式为 RGB
image_file = image_file.convert("RGB")
# 获得文字图片的每个像素点
img_datas = image_file.load()
prototype = ""
#size 属性表示图片的分辨率,'0'为横向大小,'1'为纵向
for h in range(0,image_file.size[1]):
for w in range(0,image_file.size[0]):
img_color_data = img_datas[w,h]
# print(img_color_data) #(255, 192, 165)
prototype += "{x}px {y}px rgb{color},".format(x=w,y=h,color=img_color_data)
return prototype[:-1]+";"
上面这段代码首先将图片转为 RGB 模式,然后用双重 for 循环逐行读取颜色值,并与 x,y 值拼接成 box-shadow 的属性。完整的代码如下:
# -*- coding: utf-8 -*-
#author : PM 小凯哥<my@xuxinkai.cn>
from PIL import Image
def transform(image_file):
# 转换图片的模式为 RGB
image_file = image_file.convert("RGB")
# 获得文字图片的每个像素点
img_datas = image_file.load()
prototype = ""
#size 属性表示图片的分辨率,'0'为横向大小,'1'为纵向
for h in range(0,image_file.size[1]):
for w in range(0,image_file.size[0]):
img_color_data = img_datas[w,h]
# print(img_color_data) #(255, 192, 165)
prototype += "{x}px {y}px rgb{color},".format(x=w,y=h,color=img_color_data)
return prototype[:-1]+";"
def get_html(new_pro):
html1 = '''
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>小凯哥博客-https://xuxinkai.cn</title>
<style>
.container{
position: relative;
width: 1px;
height: 1px;
border-radius: 50%;
background-color:white;
box-shadow:'''
html2 = '''
}
</style>
</head>
<body>
<div class="container">
</div>
</body>
</html>
'''
return html1+new_pro+html2
#修改图片地址
fp = open('./a.jpg','rb')
image_file = Image.open(fp)
#调整图片大小
image_file=image_file.resize((int(image_file.size[0]*0.5), int(image_file.size[1]*0.5)))
tmp = open('a.html','w',encoding='utf-8')
tmp.write(get_html(transform(image_file)))
tmp.close()
效果预览:
浏览器计算需要时间,耐心等待即可
总结
这是一次低成本的实验,我将帖子发到 v2ex 后,有老哥说可以拿来做反爬验证码,思考了一下,确实可以。除了做反爬外,我个人认为可以拿来绘制一些小图标。
上面只介绍了Python版本的实现,JavaScript版本实现:
github.com/pmxiaokaige…
PM 小凯哥 版权所有丨如未注明 , 均为原创丨本网站采用CC BY-NC-ND 4.0协议进行授权
转载请注明原文链接:一次idea到demo的低成本实验:div+box-shadow绘制任意图片 喜欢 (2)赏