一次idea到demo的低成本实验:div+box-shadow绘制任意图片

缘起

疫情在家,闲的没事,便重新翻开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值是必选,其他都是可选。

box-shadow

我们先写一个简单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()

效果预览:

线上体验地址

浏览器计算需要时间,耐心等待即可

哆啦A梦

总结

这是一次低成本的实验,我将帖子发到v2ex后,有老哥说可以拿来做反爬验证码,思考了一下,确实可以。除了做反爬外,我个人认为可以拿来绘制一些小图标。

上面只介绍了Python版本的实现,JavaScript版本实现:
https://github.com/pmxiaokaige/Python-Practice

© 版权声明
THE END
请我喝怡宝
点赞0
分享
评论 共4条
    • 人间不值得
    • 伍子蛇0

      核心是图片识别的库,前端可以用box-shadow,可以试试用canvas会更香,渲染速度也是飞越

      6月前回复
      • 人间不值得
        人间不值得1

        canvas绘制出来的是图片,而我这个还是HTML,可以拿来做反爬。

    • 人间不值得
    • 伍子蛇0

      嗯嗯,想法很好,优秀的PM?

      6月前回复