html案例:编写一个用于发布CSDN文章时,生成有关缩略图

CSDN博客文章缩略图生成器

起因:

  • 之前注意到CSDN可以随机选取文章缩略图,但后来这个功能似乎取消了。于是我想调整一下缩略图的配色方案。

html制作界面
界面分上下两块区域,上面是参数配置,下面是效果预览图。

  • 参数配置:

    • 文本内容自定义:输入关键词生成图片中间的文本内容(建议简短);
    • 背景色调整:提供预设颜色选项和通过颜色选择器选择颜色;
    • 图片尺寸:默认宽480像素,高270像素
  • 功能说明:

    • 由选择颜色或随机生成颜色生成图片,如果不满意还可以预设颜色,之后可以把图片保存下来,通过重置参数就可以达到随机生成的效果;

生成效果

  • 生成的效果图

代码部分

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>CSDN博客文章缩略图生成器</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
        }
        .container {
            text-align: center;
            background: white;
            padding: 20px;
            border-radius: 10px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
            user-select: none;
            -webkit-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
        }
        .form-group {
            margin-bottom: 10px;
        }
        .form-group label {
            display: inline-block;
            width: 100px;
            text-align: right;
            margin-right: 10px;
        }
        .form-group input[type="text"],
        .form-group input[type="number"]{
            padding: 5px;
            width: 200px;
            margin-left: 10px;
        }
        .form-group input[type="color"] {
            padding: 0;
            width: 210px;
            margin-left: 12px;
            border: none;
            cursor: pointer;
        }
        .form-group select {
            padding: 5px;
            width: 213px;
            margin-left: 10px;
            border-radius: 4px;
            border: 1px solid #ccc;
        }
        .form-group select:disabled {
            background-color: #eee;
            cursor: not-allowed;
        }
        .form-group select:hover {
            border-color: #888;
        }
        .controls {
            display: flex;
            justify-content: center;
            margin-top: 20px;
            align-items: center;
            flex-wrap: nowrap;
            margin-top: 20px;
            gap: 20px;
        }
        .controls button {
            margin-top: 10px;
            padding: 8px 16px;
            cursor: pointer;
        }
        #preview {
            margin-top: 20px;
            border-radius: 10px;
            overflow: hidden;
        }
        canvas {
            width: 100%;
            height: auto;
            margin-top: 20px;
            border-radius: 10px;
        }
    </style>
</head>
<body>
<div class="container">
    <h2>CSDN博客文章缩略图生成器</h2>
    
    <!-- 配置选项 -->
    <div class="form-group">
        <label for="text">文本内容:</label>
        <input type="text" id="text" placeholder="请输入文本内容" value="#示例文本"/>
    </div>
    <div class="form-group">
        <label for="presetColors">颜色预设:</label>
        <select id="presetColors" onchange="applyPresetColor()">
            <option value="" selected>请选择</option>
            <option value="#FE5F20">Java专栏色</option>
            <option value="#5E61CB">学车专栏色</option>
            <option value="#3A80A8">数据库专栏色</option>
            <option value="#34B3BC">其他专栏色</option>
            <option value="#90839B">(其他)Linux文章色</option>
            <option value="#34B3BC">(其他)软件文章色</option>
        </select>
    </div>
    <div class="form-group">
      <label for="bgColor">背景颜色:</label>
      <input type="color" id="bgColor" value="#ffffff">
    </div>
    <div class="form-group">
        <label for="width">宽度:</label>
        <input type="number" id="width" value="480"/>
    </div>
    <div class="form-group">
        <label for="height">高度:</label>
        <input type="number" id="height" value="270"/>
    </div>
    <div class="controls">
        <button onclick="generateImage()">生成图片</button>
        <button onclick="downloadImage()">保存图片</button>
        <button onclick="resetColor()">重置参数</button>
    </div>

    <!-- 预览区域 -->
    <div id="preview">
        <canvas id="myCanvas"></canvas>
    </div>
</div>

<script>
    const canvas = document.getElementById("myCanvas");
    const ctx = canvas.getContext("2d");


    // 颜色值校验
    function isValidHexColor(color) {
        const regex = /^#([0-9A-Fa-f]{6})$/;
        return regex.test(color);
    }
        
    // 颜色随机
    function getRandomColor() {
        return '#' + Math.floor(Math.random()*16777215).toString(16);
    }
    
    // 重置颜色参数
    function resetColor() {
        document.getElementById("presetColors").value = ""; // 清空下拉框选择
        document.getElementById("bgColor").value = "#ffffff"; // 重置颜色选择器为默认白色
        userSelectedColor = false; // 允许 generateImage 使用随机色
        generateImage(); // 重新生成图片
    }

    // 生成渐变色
    function generateGradient(startColor, endColor, width, height) {
        let gradient = ctx.createLinearGradient(0, 0, width, height);
        //gradient.addColorStop(0, startColor);
        gradient.addColorStop(0.5, adjustBrightness(startColor, -0.1));
        gradient.addColorStop(1, endColor);
        return gradient;
    }

    
    // 图形生成
    let userSelectedColor = false;
    function generateImage() {
        const text = document.getElementById("text").value || "#示例文本内容";
        const bgColorInput = document.getElementById("bgColor").value;
        const width = parseInt(document.getElementById("width").value) || 480;
        const height = parseInt(document.getElementById("height").value) || 270;

        // 设置画布尺寸
        canvas.width = width;
        canvas.height = height;

        // 清除画布
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        // 判断是否用户选择了颜色
        let bgColor;
        if (userSelectedColor || bgColorInput !== "#ffffff") {
            bgColor = isValidHexColor(bgColorInput) ? bgColorInput : getRandomColor();
        } else {
            bgColor = getRandomColor();
        }


        // 创建渐变背景
        ctx.fillStyle = generateGradient(bgColor, adjustBrightness(bgColor, -0.2), width, height);
        ctx.fillRect(0, 0, width, height);

        // 绘制多个斜坡形状
        ctx.beginPath();
        ctx.moveTo(1, height); // A点,左下角
        ctx.lineTo(width * 0.9, height); // B点,右下角
        ctx.lineTo(0, height * 0.196); // C点,右上角
        ctx.closePath();
        ctx.fillStyle = 'rgba(255, 255, 255, 0.1)';
        ctx.fill();
        
        ctx.beginPath();
        ctx.moveTo(1, height); // A点,左下角
        ctx.lineTo(width * 0.45, height); // B点,右下角
        ctx.lineTo(0, -230); // C点,左上角
        ctx.closePath();
        ctx.fillStyle = 'rgba(255, 255, 255, 0.1)';
        ctx.fill();
        
        // 绘制多个半球形状
        ctx.beginPath();
        ctx.arc(width * 0.95, height * 0.1, Math.min(width, height) * 0.2, 0, Math.PI * 2, false);
        ctx.closePath();
        ctx.fillStyle = 'rgba(255, 255, 255, 0.1)';
        ctx.fill();
	
        ctx.beginPath();
        ctx.arc(width * 0.1, height * 0.75, Math.min(width, height) * 0.2, 0, Math.PI * 2, false);
        ctx.closePath();
        ctx.fillStyle = 'rgba(255, 255, 255, 0.1)';
        ctx.fill();

        // 设置字体样式
        //ctx.font = `bold ${Math.min(width / text.length, 60)}px Arial`; // 根据画布宽度调整字体大小
        ctx.font = "bold 60px Arial"
        ctx.textAlign = "center";
        ctx.fillStyle = "#ffffff";

        // 计算文字位置以确保居中显示
        const metrics = ctx.measureText(text);
        const x = canvas.width / 2;
        const y = (canvas.height / 2) + (metrics.actualBoundingBoxAscent / 2);

        // 绘制文本
        ctx.fillText(text, x, y);
    }

    
    // 调整图片亮度
    function adjustBrightness(hex, correctionFactor) {
        if (!/^#([0-9A-Fa-f]{6})$/.test(hex)) {
            console.warn("Invalid color format:", hex);
            return "#000000"; // fallback
        }

        hex = hex.replace(/^#/, '');
        let r = parseInt(hex.substr(0, 2), 16),
            g = parseInt(hex.substr(2, 2), 16),
            b = parseInt(hex.substr(4, 2), 16);

        // 调整亮度,使用线性方式更直观
        r = Math.max(0, Math.min(255, Math.round(r + 255 * correctionFactor)));
        g = Math.max(0, Math.min(255, Math.round(g + 255 * correctionFactor)));
        b = Math.max(0, Math.min(255, Math.round(b + 255 * correctionFactor)));

        // 确保返回为 6 位颜色
        const toHex = (c) => c.toString(16).padStart(2, '0');
        return "#" + toHex(r) + toHex(g) + toHex(b);
    }
    
    // 下载图片
    function downloadImage() {
        const link = document.createElement('a');
        link.download = 'generated-image.png';
        link.href = canvas.toDataURL('image/png');
        link.click();
    }
        
    // 预设颜色应用
    function applyPresetColor() {
        const colorPicker = document.getElementById('bgColor');
        if (colorPicker) { // 检查是否成功获取到元素
            const presetColor = document.getElementById('presetColors').value;
            colorPicker.value = presetColor;
            generateImage(); // 更新图片预览
        } else {
            console.error("未能找到ID为'bgColor'的元素");
        }
    }

	// 添加事件监听器来检测颜色选择
	document.getElementById('bgColor').addEventListener('input', () => {
	    userSelectedColor = true;
        generateImage(); 
	});
    // 页面加载时默认生成一张图片
    window.onload = () => generateImage();
</script>
</body>
</html>
相关推荐
GISer_Jing5 分钟前
LLM对话框项目总结II
前端·javascript·node.js
恰薯条的屑海鸥6 分钟前
前端进阶之路-从传统前端到VUE-JS(第五期-路由应用)
前端·javascript·vue.js·学习·前端框架
子林super8 分钟前
TIDB常用命令手册
前端
好青崧9 分钟前
单页面和多页面的区别和优缺点
前端·vue
wangpq11 分钟前
Echart饼图自动轮播效果封装
javascript·vue.js
TimelessHaze14 分钟前
深入理解 JavaScript Event Loop:从原理到实战全解析
前端·javascript·react.js
爱学习的茄子14 分钟前
【踩坑实录】React Router从入门到精通:我的前端路由血泪史
前端·javascript·面试
小徐_233314 分钟前
uni-app 弹窗总被父元素“绑架”?3招破局,H5/小程序/APP一招通杀!
前端·微信小程序·uni-app
G等你下课14 分钟前
为什么你需要 useLayoutEffect?深入理解同步副作用
前端·react.js
拾光拾趣录15 分钟前
JavaScript压缩原理与手写实现
前端·javascript·前端工程化