中秋!还记得西游记里的嫦娥吗?我用10000张图片拼成了儿时女神!

小李广
• 阅读 2442

前言

大家好,我是林三心,中秋即将来临,预祝大家中秋快乐!!!我在想,关于中秋,我能写点什么分享给大家呢?这一天,我在看《西游记》,突然想到了我儿时的女神,是谁呢?就是天蓬元帅苦苦追求的嫦娥仙子,那可是我儿时的女神啊。嫦娥奔月的故事我相信大家都听过

前段时间,我看了荣顶大佬的这篇我用 10000 张图片合成我们美好的瞬间,发现原来图片的主色调是那样计算的,学到了很多。于是我站在荣顶巨人的肩膀上,用王者荣耀里嫦娥这一角色的不同图片,加上王者荣耀里后羿这一角色的不同图片(后羿是嫦娥老公),组成了我儿时女神——西游记嫦娥的图像。

开搞!!!

前置准备

由于需要用到canvas,以及一些图片上传按钮,所以咱们先把HTML的代码写好,fabric是一个非常实用的canvas库,他提供了很多api,方便我们更方便地在canvas上画出可操作性的图像。fabric的代码在这里fabric库代码,创建一个文件,复制过来就行

    <!-- 引入fabric这个库 -->
    <script src="./fabric.js"></script>
    <!-- 用来选主图 -->
    <input type="file" id="mainInput" />
    <!-- 用来选组成图片 多选 -->
    <input type="file" id="composeInput" multiple />
    <!-- 生成效果 -->
    <button id="finishBtn">生成组合图</button>
    <!-- 一块800 * 800 的canvas画布 -->
    <canvas id="canvas" width="800" height="800"></div>
const mainInput = document.getElementById('mainInput') // 获取上传主图按钮的DOM
const composeInput = document.getElementById('composeInput') // 获取多传组合图片按钮的DOM
const finishBtn = document.getElementById('finishBtn') // 获取生成最终结果按钮的DOM
const exportBtn = document.getElementById('exportBtn') // 获取倒出图片按钮的DOM
const canvas = new fabric.Canvas('canvas') // 实例一个fabric的canvas对象,传入的是canvas的id
const ctx = canvas.getContext('2d') // 绘制2d图像

画出嫦娥姐姐

咱们需要先在页面上画出嫦娥姐姐的原始图像,图像如下

中秋!还记得西游记里的嫦娥吗?我用10000张图片拼成了儿时女神!

那咱们要怎么把一张图像画到HTML页面中呢?答案是canvas,那咱们就先把这个图像绘制到页面上去吧!

咱们都知道,图片直接上传到浏览器,是不可能直接就给你绘制出来的,比如原生的canvas需要把你这张图片转为base64格式才能绘制到页面,而fabric提供了一个fabric.Image.fromURL(url, img => {}),需要传入一个图片的blob地址,才能生成一张可绘制到页面的图片。那咱们怎么把咱们上传的图片转成blob地址呢?其实JavaScript已经给我们提供了这么一个方法window.URL.createObjectURL,用它就能实现啦。

// 监听上传主图按钮的上传变化
mainInput.onchange = function (e) {
    // 只有一个图片,所以是e.target.files[0]
    const url = window.URL.createObjectURL(e.target.files[0])
    // 将生成的blob地址传入
    drawMainImage(url)
}

function drawMainImage(url) {
    // 接收传进来的url
    fabric.Image.fromURL(url, img => {
        console.log(img)
        // 转换成功后的回调
        // fabric.Image.fromURL会将此url转换成一张图片

        // 需要缩放图片,height > width 就按照 width的缩放比例,反之用height的缩放比例
        // 反过来是为了能充满整张图
        const scale = img.height > img.width ? canvas.width / img.width : canvas.height / img.height

        // 设置这张图像绘制的参数
        img.set({
            left: canvas.width / 2, // 距离canvas画板左边一半宽度
            originX: 'center', // 水平方向居中
            top: 0, // 距离顶部距离为0
            scaleX: scale, // 图像水平缩放比例
            scaleY: scale, // 图像竖直缩放比例
            selectable: false // 不可操作,默认是true
        })

        // 把此图像绘制到canvas画板中
        canvas.add(img)
        
        // 图片绘制完成的回调函数
        img.on('added', e => {
            console.log('图片加载完成了啊')
            setTimeout(() => {
                // 绘制完成后,获取此图像中10000个格子的色彩信息,后面会实现
                getMainRGBA()
            }, 200) // 这里用延时器,是因为图像绘制有延迟
                    // 而这里需要保证图像真的完全绘制完,再去获取色彩信息
        })
    })
}

10000个格子

中秋!还记得西游记里的嫦娥吗?我用10000张图片拼成了儿时女神!
咱们都知道,咱们的canvas画布是 800 * 800 的,咱们想要分成 10000 个格子,那么每个格子就是 8 * 8 。实现之前,咱们现在认识一个canvas获取色彩信息的api——ctx.getImageData(x, y, width, height),他接收4个参数

  • x:获取范围的x坐标
  • y:获取范围的y坐标
  • width:获取范围的宽度
  • height:获取范围的高度
    他会返回一个对象,对象里有一个属性data,这个data就是此范围的色彩信息,比如
const { data } = ctx.getImageData(40, 40, 8, 8)

中秋!还记得西游记里的嫦娥吗?我用10000张图片拼成了儿时女神!

那么data就是x为40,y为40,宽度高度都是8,这一个范围内的色彩信息,这个色彩信息是一个数组,比如这个范围是8 * 8,那么这个数组就有 8 * 8 * 4 = 256 个元素,因为 8 * 8 就有64个像素,而每一个像素的rgba(r, g, b, a)是4个值,所以这个数组就有 8 * 8 * 4 = 256 个元素,所以下面咱们要4个4个收集,因为每4个元素就是一个像素的rgba,而一个8 * 8的格子,就会有64个像素,也就是64个rgba数组

let mainColors = [] // 用来收集1000个格子的主色调rgba,后面会实现

function getMainRGBA() {
    const rgbas = [] // 用来收集10000个格子的色彩信息
    for (let y = 0; y < canvas.height; y += 8) {
        for (let x = 0; x < canvas.width; x += 8) {
            // 获取每一块格子的色彩data
            const { data } = ctx.getImageData(x, y, 8, 8)
            rgbas[y / 8 * 100 + x / 8] = []
            for (let i = 0; i < data.length; i += 4) {
                // 4个4个收集,因为每4个就组成一个像素的rgba
                rgbas[y / 8 * 100 + x / 8].push([
                    data[i],
                    data[i + 1],
                    data[i + 2],
                    data[i + 3]
                ])
            }
        }
    }
    // 算出10000个格子,每个格子的主色调,后面实现
    mainColors = getMainColorStyle(rgbas)
}

每个格子主色调

上面咱们已经获取到了10000个格子,他们每个格子都拥有64个像素,也就是64个rgba数组,那每个格子拥有64个rgba,咱们怎么才能得到这个格子的主色调呢?很简单嘛,rgba(r, g, b, a)有4个值,咱们算出这4个值各自的平均值,然后组成一个新的rgba,这个rgba就是每个格子的主色调啦!!!

function getMainColorStyle(rgbas) {
    const mainColors = []
    for (let colors of rgbas) {
        let r = 0, g = 0, b = 0, a = 0
        for (let color of colors) {
            // 累加
            r += color[0]
            g += color[1]
            b += color[2]
            a += color[3]
        }
        mainColors.push([
            Math.round(r / colors.length), // 取平均值
            Math.round(g / colors.length), // 取平均值
            Math.round(b / colors.length), // 取平均值
            Math.round(a / colors.length) // 取平均值
        ])
    }
    return mainColors
}

上传组合图片

主图片的功能都实现了,现在就剩组合图片了,咱们可以多传组合图片。但是我们要算出每一张组合图片的主色调,因为后面咱们要主色调来对比那10000个格子的主色调,决定哪个格子放哪张组合图片

这里有一个问题要强调一下,想要获取图片的颜色信息,就得把图片画到canvas画板上才能获取,但是咱们又不想在这里把图片画到页面上的canvas里,咋办呢?咱们可以创建临时的canvas画板,画完,获取完颜色信息,咱们就把它销毁

let composeColors = [] // 收集组合图片主色调

// 监听多选按钮的上传
composeInput.onchange = async function (e) {
    const promises = [] // promises数组
    for (file of e.target.files) {
        // 将每张图片生成blob地址
        const url = window.URL.createObjectURL(file)
        // 传入blob地址
        promises.push(getComposeColorStyle(url, file.name))
    }
    const res = await Promise.all(promises) // 顺序执行所有promise
    composeColors = res // 将结果赋值给composeColors
}

function getComposeColorStyle(url, name) {
    return new Promise(resolve => {
        // 创建一个 20 * 20的canvas画板
        // 理论上这里宽高可以自己定,但是越大,色彩会越精准
        const composeCanvas = document.createElement('canvas')
        const composeCtx = composeCanvas.getContext('2d')
        composeCanvas.width = 20
        composeCanvas.height = 20

        // 创建img对象
        const img = new Image()
        img.src = url
        img.onload = function () {
            const scale = composeCanvas.height / composeCanvas.height
            img.height *= scale
            img.width *= scale

            // 将img画到临时canvas画板
            composeCtx.drawImage(img, 0, 0, composeCanvas.width, composeCanvas.height)
            // 获取颜色信息data
            const { data } = composeCtx.getImageData(0, 0, composeCanvas.width, composeCanvas.height)

            // 累加  r,g,b,a
            let r = 0, g = 0, b = 0, a = 0
            for (let i = 0; i < data.length; i += 4) {
                r += data[i]
                g += data[i + 1]
                b += data[i + 2]
                a += data[i + 3]
            }
            resolve({
                // 主色调
                rgba: [
                    Math.round(r / (data.length / 4)), // 取平均值
                    Math.round(g / (data.length / 4)), // 取平均值
                    Math.round(b / (data.length / 4)), // 取平均值
                    Math.round(a / (data.length / 4)) // 取平均值
                ],
                url,
                name
            })
        }
    })
}

对比主色调并绘制

  • canvas画板中的嫦娥姐姐有10000个格子,每个格子都有自己的主色调
  • 上传的每张组合图片也有自己的主色调

那咱们要怎么实现最终效果呢?很简单嘛!!!遍历10000个格子,拿着每个格子的主色调,去跟每张组合图片的主色调一一对比,最接近色调的图片,就拿来绘制到这个 8 * 8 的格子里。

// 监听完成按钮
finishBtn.onclick = finishCompose

function finishCompose() {
    const urls = [] // 收集最终绘制的10000张图片

    for (let main of mainColors) { // 遍历10000个格子主色调

        let closestIndex = 0 // 最接近主色调的图片的index
        let minimumDiff = Infinity // 相差值

        for (let i = 0; i < composeColors.length; i++) {
            const { rgba } = composeColors[i]
            // 格子主色调rgba四个值,减去图片主色调rgba四个值,的平方
            const diff = (rgba[0] - main[0]) ** 2 + (rgba[1] - main[1]) ** 2
                + (rgba[2] - main[2]) ** 2 + (rgba[3] - main[3]) ** 2

            // 然后开跟比较
            if (Math.sqrt(diff) < minimumDiff) {
                minimumDiff = Math.sqrt(diff)
                closestIndex = i
            }
        }

        // 把最小色差的图片url添加进数组urls
        urls.push(composeColors[closestIndex].url)
    }


    // 将urls中10000张图片,分别绘制在对应的10000个格子中
    for (let i = 0; i < urls.length; i++) {
        fabric.Image.fromURL(urls[i], img => {
            const scale = img.height > img.width ? 8 / img.width : 8 / img.height;
            img.set({
                left: i % 100 * 8,
                top: Math.floor(i / 100) * 8,
                originX: "center",
                scaleX: scale,
                scaleY: scale,
            });
            canvas.add(img)
        })
    }
}

导出图片

// 监听导出按钮
exportBtn.onclick = exportCanvas

//导出图片
function exportCanvas() {
    const dataURL = canvas.toDataURL({
        width: canvas.width,
        height: canvas.height,
        left: 0,
        top: 0,
        format: "png",
    });
    const link = document.createElement("a");
    link.download = "嫦娥姐姐.png";
    link.href = dataURL;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
}

最终效果

中秋!还记得西游记里的嫦娥吗?我用10000张图片拼成了儿时女神!

彩蛋

如果你觉得此文对你有一丁点帮助,点个赞,鼓励一下林三心哈哈。或者可以加入我的摸鱼群
想进学习群,摸鱼群,请点击这里[摸鱼](
https://juejin.cn/pin/6969565...)

哈哈我用王者荣耀猪八戒的图片,组成了我自己

中秋!还记得西游记里的嫦娥吗?我用10000张图片拼成了儿时女神!

完整代码

中秋!还记得西游记里的嫦娥吗?我用10000张图片拼成了儿时女神!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入flare这个库 -->
    <script src="./flare.js"></script>
</head>
<body>
    <!-- 用来选主图 -->
    <input type="file" id="mainInput" />
    <!-- 用来选组成图片 多选 -->
    <input type="file" id="composeInput" multiple />
    <!-- 生成效果 -->
    <button id="finishBtn">生成组合图</button>
    <!-- 导出图片 -->
    <button id="exportBtn">导出图片</button>
    <!-- 一块800 * 800 的canvas画布 -->
    <canvas id="canvas" width="800" height="800"></div>
</body>
<script src="./index2.js"></script>
</html>
const mainInput = document.getElementById('mainInput') // 获取上传主图按钮的DOM
const composeInput = document.getElementById('composeInput') // 获取多传组合图片按钮的DOM
const finishBtn = document.getElementById('finishBtn') // 获取生成最终结果按钮的DOM
const exportBtn = document.getElementById('exportBtn') // 获取倒出图片按钮的DOM
const canvas = new fabric.Canvas('canvas') // 实例一个flare的canvas对象,传入的是canvas的id
const ctx = canvas.getContext('2d') // 绘制2d图像

let mainColors = []
let composeColors = []

// 监听上传主图按钮的上传变化
mainInput.onchange = function (e) {
    // 只有一个图片,所以是e.target.files[0]
    const url = window.URL.createObjectURL(e.target.files[0])
    // 将生成的blob地址传入
    drawMainImage(url)
}

composeInput.onchange = async function (e) {
    const promises = [] // promises数组
    for (file of e.target.files) {
        // 将每张图片生成blob地址
        const url = window.URL.createObjectURL(file)
        // 传入blob地址
        promises.push(getComposeColorStyle(url, file.name))
    }
    const res = await Promise.all(promises) // 顺序执行所有promise
    composeColors = res // 将结果赋值给composeColors
}

// 监听完成按钮
finishBtn.onclick = finishCompose

// 监听导出按钮
exportBtn.onclick = exportCanvas

function drawMainImage(url) {
    // 接收传进来的url
    fabric.Image.fromURL(url, img => {
        console.log(img)
        // 转换成功后的回调
        // fabric.Image.fromURL会将此url转换成一张图片

        // 需要缩放图片,height > width 就按照 width的缩放比例,反之用height的缩放比例
        // 反过来是为了能充满整张图
        const scale = img.height > img.width ? canvas.width / img.width : canvas.height / img.height

        // 设置这张图像绘制的参数
        img.set({
            left: canvas.width / 2, // 距离canvas画板左边一半宽度
            originX: 'center', // 水平方向居中
            top: 0, // 距离顶部距离为0
            scaleX: scale, // 图像水平缩放比例
            scaleY: scale, // 图像竖直缩放比例
            selectable: false // 不可操作,默认是true
        })

        // 图片绘制完成的回调函数
        img.on('added', e => {
            console.log('图片加载完成了啊')
            setTimeout(() => {
                // 绘制完成后,获取此图像中10000个格子的色彩信息
                getMainRGBA()
            }, 200) // 这里用延时器,是因为图像绘制有延迟
            // 而这里需要保证图像真的完全绘制完,再去获取色彩信息
        })

        // 把此图像绘制到canvas画板中
        canvas.add(img)
    })
}


function getMainRGBA() {
    const rgbas = [] // 用来收集10000个格子的色彩信息
    for (let y = 0; y < canvas.height; y += 8) {
        for (let x = 0; x < canvas.width; x += 8) {
            // 获取每一块格子的色彩data
            const { data } = ctx.getImageData(x, y, 8, 8)
            rgbas[y / 8 * 100 + x / 8] = []
            for (let i = 0; i < data.length; i += 4) {
                // 4个4个收集,因为每4个就组成一个像素的rgba
                rgbas[y / 8 * 100 + x / 8].push([
                    data[i],
                    data[i + 1],
                    data[i + 2],
                    data[i + 3]
                ])
            }
        }
    }
    // 算出10000个格子,每个格子的主色调
    mainColors = getMainColorStyle(rgbas)
}

function getMainColorStyle(rgbas) {
    const mainColors = [] // 用来收集1000个格子的主色调rgba
    for (let colors of rgbas) {
        let r = 0, g = 0, b = 0, a = 0
        for (let color of colors) {
            // 累加
            r += color[0]
            g += color[1]
            b += color[2]
            a += color[3]
        }
        mainColors.push([
            Math.round(r / colors.length), // 取平均值
            Math.round(g / colors.length), // 取平均值
            Math.round(b / colors.length), // 取平均值
            Math.round(a / colors.length) // 取平均值
        ])
    }
    return mainColors
}

function getComposeColorStyle(url, name) {
    return new Promise(resolve => {
        // 创建一个 20 * 20的canvas画板
        // 理论上这里宽高可以自己定,但是越大,色彩会越精准
        const composeCanvas = document.createElement('canvas')
        const composeCtx = composeCanvas.getContext('2d')
        composeCanvas.width = 20
        composeCanvas.height = 20

        // 创建img对象
        const img = new Image()
        img.src = url
        img.onload = function () {
            const scale = composeCanvas.height / composeCanvas.height
            img.height *= scale
            img.width *= scale

            // 将img画到临时canvas画板
            composeCtx.drawImage(img, 0, 0, composeCanvas.width, composeCanvas.height)
            // 获取颜色信息data
            const { data } = composeCtx.getImageData(0, 0, composeCanvas.width, composeCanvas.height)

            // 累加  r,g,b,a
            let r = 0, g = 0, b = 0, a = 0
            for (let i = 0; i < data.length; i += 4) {
                r += data[i]
                g += data[i + 1]
                b += data[i + 2]
                a += data[i + 3]
            }
            resolve({
                // 主色调
                rgba: [
                    Math.round(r / (data.length / 4)), // 取平均值
                    Math.round(g / (data.length / 4)), // 取平均值
                    Math.round(b / (data.length / 4)), // 取平均值
                    Math.round(a / (data.length / 4)) // 取平均值
                ],
                url,
                name
            })
        }
    })
}

function finishCompose() {
    const urls = [] // 收集最终绘制的10000张图片

    for (let main of mainColors) { // 遍历10000个格子主色调

        let closestIndex = 0 // 最接近主色调的图片的index
        let minimumDiff = Infinity // 相差值

        for (let i = 0; i < composeColors.length; i++) {
            const { rgba } = composeColors[i]
            // 格子主色调rgba四个值,减去图片主色调rgba四个值,的平方
            const diff = (rgba[0] - main[0]) ** 2 + (rgba[1] - main[1]) ** 2
                + (rgba[2] - main[2]) ** 2 + (rgba[3] - main[3]) ** 2

            // 然后开跟比较
            if (Math.sqrt(diff) < minimumDiff) {
                minimumDiff = Math.sqrt(diff)
                closestIndex = i
            }
        }

        // 把最小色差的图片url添加进数组urls
        urls.push(composeColors[closestIndex].url)
    }


    // 将urls中10000张图片,分别绘制在对应的10000个格子中
    for (let i = 0; i < urls.length; i++) {
        fabric.Image.fromURL(urls[i], img => {
            const scale = img.height > img.width ? 8 / img.width : 8 / img.height;
            img.set({
                left: i % 100 * 8,
                top: Math.floor(i / 100) * 8,
                originX: "center",
                scaleX: scale,
                scaleY: scale,
            });
            canvas.add(img)
        })
    }
}


//导出图片
function exportCanvas() {
    const dataURL = canvas.toDataURL({
        width: canvas.width,
        height: canvas.height,
        left: 0,
        top: 0,
        format: "png",
    });
    const link = document.createElement("a");
    link.download = "嫦娥姐姐.png";
    link.href = dataURL;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
}

参考文章

结语

我是林三心,一个热心的前端菜鸟程序员。如果你上进,喜欢前端,想学习前端,那咱们可以交朋友,一起摸鱼哈哈,摸鱼群,加我请备注【思否】

中秋!还记得西游记里的嫦娥吗?我用10000张图片拼成了儿时女神!

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
李志宽 李志宽
4年前
扒了手机监控木马后台!
0x00楔子近日,小明有了一桩烦心事,扰的他寝食难安。原来是女神的某安卓手机出了怪病,短信收不到,发出去别人也收不到,更可气的是女神用来准备网购的钱都被神秘刷走。当女神满心焦躁翻遍通讯录时,蓦然发现了小明的备注:千斤顶17号电脑、刷机。于是在女神可怜巴巴大眼睛的注视下,小明把胸脯拍的山响,承诺一天搞定。于是,小明拿到了梦寐以求的女神手机。可没想到,后面发生
Wesley13 Wesley13
4年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
4年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
4年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Stella981 Stella981
4年前
Hibernate纯sql查询结果和该sql在数据库直接查询结果不一致
问题:今天在做一个查询的时候发现一个问题,我先在数据库实现了我需要的sql,然后我在代码中代码:selectdistinctd.id,d.name,COALESCE(c.count_num,0),COALESCE(c.count_fix,0),COALESCE(c
00后如何组织双十一大促看这一篇就够了! | 京东云技术团队
引言大家好,我是王蒙恩,一名“整顿职场”的00后。作为一名去年刚刚加入京东的校招生,我有幸成为本次CDP平台的11.11备战负责人。虽然早在实习的时候就经历过大促,但是真正组织整个部门的备战还是很难忘的。于是提起笔,给自己做一个大促总结,记录下11.11大
Python进阶者 Python进阶者
2年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
小李广
小李广
Lv1
人生到处知何似,应似飞鸿踏雪痕。泥上偶然留指爪,鸿飞哪复计西东。
文章
6
粉丝
0
获赞
0