canvas 随机生成 彩色柱状图

这篇博客介绍如何利用JavaScript的canvas API,结合CSS,动态地生成具有随机颜色的柱状图,适用于前端数据可视化展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

柱状图、颜色,随机生成

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <title>Title</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        body {
            background-color: rgba(149, 175, 192, 0.3);
        }

        .canvas {
            display: block;
            margin: 30px auto;
            border: 1px solid #cccccc;
            background-color: rgba(199, 236, 238, 0.5);
        }
    </style>
</head>

<body>
    <canvas class="canvas" width="700" height="700"></canvas>

    <script>
        let canvas = document.querySelector('canvas');
        let ctx = canvas.getContext('2d');

        ctx.beginPath();
        ctx.moveTo(45, 60);
        ctx.lineTo(50, 50);
        ctx.lineTo(55, 60);
        ctx.lineTo(50, 50);
        ctx.lineTo(50, 450);
        ctx.lineTo(450, 450);
        ctx.lineTo(440, 445);
        ctx.lineTo(450, 450);
        ctx.lineTo(440, 455);
        ctx.strokeStyle = 'black';
        ctx.strokeWidth = 5;
        ctx.stroke();
        ctx.closePath();

        for (let i = 0; i < 9; i++) {
            let r = Math.random() * 256;
            let g = Math.random() * 256;
            let b = Math.random() * 256;
            ctx.fillStyle = 'rgb(' + r + ',' + g + ',' + b + ')';
            let x = 70, y = 450, w = 20, h = -Math.random() * 400;
            ctx.fillRect(x + 40 * i, y, w, h);
        }
    </script>
</body>
</html>
// 超精细半色调生成方法 async generateUltraHalftoneImage(imagePath) { const printWidth = 430; const printHeight = 430; // 创建离屏Canvas const offscreenCanvas = wx.createOffscreenCanvas({ type: '2d', width: printWidth, height: printHeight }); const ctx = offscreenCanvas.getContext('2d'); // 填充白色背景 ctx.fillStyle = '#FFFFFF'; ctx.fillRect(0, 0, printWidth, printHeight); // 加载图片 const img = offscreenCanvas.createImage(); await new Promise((resolve, reject) => { img.onload = resolve; img.onerror = reject; img.src = imagePath; }); // 计算缩放比例 const scale = Math.min( printWidth / img.width, printHeight / img.height ); // 计算绘制位置 const drawWidth = img.width * scale; const drawHeight = img.height * scale; const x = (printWidth - drawWidth) / 2; const y = (printHeight - drawHeight) / 2; // 使用最高质量绘制 ctx.imageSmoothingEnabled = true; ctx.imageSmoothingQuality = 'high'; ctx.drawImage(img, x, y, drawWidth, drawHeight); // 获取图像数据 const imageData = ctx.getImageData(0, 0, printWidth, printHeight); const data = imageData.data; // 专业级灰度处理 this.professionalGrayscale(data); // 应用超精细半色调效果 this.applyUltraFineHalftone(data, printWidth, printHeight); // 将半色调数据绘制到Canvas ctx.putImageData(imageData, 0, 0); // 生成临时文件路径 return await new Promise((resolve, reject) => { wx.canvasToTempFilePath({ canvas: offscreenCanvas, fileType: 'png', quality: 1, success: (res) => resolve(res.tempFilePath), fail: reject }); }); }, // 专业级灰度处理 professionalGrayscale(data) { // 使用更精确的灰度公式 for (let i = 0; i < data.length; i += 4) { const r = data[i]; const g = data[i + 1]; const b = data[i + 2]; // 使用CIE Lab转换公式的简化版本 const gray = 0.2126 * r + 0.7152 * g + 0.0722 * b; // 应用S曲线增强(保留更多中间调) const enhanced = this.sCurveEnhancement(gray); data[i] = data[i + 1] = data[i + 2] = enhanced; } }, // S曲线增强(优化中间调) sCurveEnhancement(value) { const normalized = value / 255; // 专业S曲线公式(更平缓的过渡) let curved; if (normalized < 0.25) { curved = 2.5 * Math.pow(normalized, 2); } else if (normalized < 0.75) { curved = 1.5 * normalized - 0.125; } else { curved = 1 - 2.5 * Math.pow(1 - normalized, 2); } return Math.max(0, Math.min(255, curved * 255)); }, // 超精细半色调算法 applyUltraFineHalftone(data, width, height) { // 创建临时数组存储灰度值 const grayData = new Float32Array(width * height); // 提取灰度数据 for (let i = 0, j = 0; i < data.length; i += 4, j++) { grayData[j] = data[i]; } // 使用专业级误差扩散算法 for (let y = 0; y < height; y++) { for (let x = 0; x < width; x++) { const idx = y * width + x; let oldVal = grayData[idx]; // 使用动态阈值(更精细的控制) const threshold = this.calculateUltraThreshold(grayData, x, y, width, height); // 应用抖动技术减少颗粒感 const jitter = this.calculateJitter(x, y, width, height); const effectiveThreshold = threshold * (1 + jitter); const newVal = oldVal < effectiveThreshold ? 0 : 255; // 设置最终像素值 const dataIdx = idx * 4; data[dataIdx] = data[dataIdx + 1] = data[dataIdx + 2] = newVal; // 计算误差 const error = oldVal - newVal; // 专业级误差扩散(Jarvis-Judice-Ninke算法) if (x + 1 < width) { grayData[idx + 1] += error * 7 / 48; } if (x + 2 < width) { grayData[idx + 2] += error * 5 / 48; } if (y + 1 < height) { if (x - 2 >= 0) { grayData[idx + width - 2] += error * 3 / 48; } if (x - 1 >= 0) { grayData[idx + width - 1] += error * 5 / 48; } grayData[idx + width] += error * 7 / 48; if (x + 1 < width) { grayData[idx + width + 1] += error * 5 / 48; } if (x + 2 < width) { grayData[idx + width + 2] += error * 3 / 48; } } if (y + 2 < height) { if (x - 2 >= 0) { grayData[idx + width * 2 - 2] += error * 1 / 48; } if (x - 1 >= 0) { grayData[idx + width * 2 - 1] += error * 3 / 48; } grayData[idx + width * 2] += error * 5 / 48; if (x + 1 < width) { grayData[idx + width * 2 + 1] += error * 3 / 48; } if (x + 2 < width) { grayData[idx + width * 2 + 2] += error * 1 / 48; } } } } }, // 计算超精细阈值 calculateUltraThreshold(grayData, x, y, width, height) { const baseThreshold = 128; const idx = y * width + x; const currentGray = grayData[idx]; // 计算7x7邻域平均值(更大范围更平滑) let sum = 0; let count = 0; for (let dy = -3; dy <= 3; dy++) { for (let dx = -3; dx <= 3; dx++) { const nx = x + dx; const ny = y + dy; if (nx >= 0 && nx < width && ny >= 0 && ny < height) { const nIdx = ny * width + nx; sum += grayData[nIdx]; count++; } } } const localAvg = sum / count; // 计算局部对比度 const contrastFactor = Math.abs(currentGray - localAvg) / 255; // 在低对比度区域使用更平滑的阈值 if (contrastFactor < 0.1) { return baseThreshold * 0.3 + localAvg * 0.7; } else if (contrastFactor < 0.3) { return baseThreshold * 0.5 + localAvg * 0.5; } else { return baseThreshold; } }, // 计算抖动值(减少规则图案) calculateJitter(x, y, width, height) { // 使用伪随机噪声减少规则图案 const seed = (x * 15485863 + y * 2038074743) % 1000000009; const noise = (seed % 100) / 100; // 应用正弦波创建更自然的抖动模式 const freq = 0.1; const xWave = Math.sin(x * freq); const yWave = Math.sin(y * freq); // 混合噪声和波形 const jitter = (noise + xWave + yWave) / 30; // 小幅度抖动 return jitter; }, 这个代码继续优化,提升图片质感,精细化图片,回复我的代码需要完整的js代码,不要出现什么填补代码,不用担心性能问题,我得机器性能无敌强,只需要图片效果最好就行
最新发布
07-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值