canvas绘制图片与文字-多样式点击切换

通过按钮携带不同参数,点击时生成不同的canvas内容,功能包含清楚canvas、下载图片,效果如下:
在这里插入图片描述
HTML代码

<h1>选择模板生成Canvas</h1>
<div class="button-group">
	<button class="generate-btn style1" data-bgcolor="#ecf0f1" data-textcolor="#2c3e50" data-imgtheme="nature">自然风格</button>
	<button class="generate-btn style2" data-bgcolor="#f5e6ff" data-textcolor="#4b0082" data-imgtheme="art">艺术风格</button>
	<button class="generate-btn style3" data-bgcolor="#fff2e6" data-textcolor="#cc6600" data-imgtheme="food">美食风格</button>
	<button class="generate-btn style4" data-bgcolor="#e6f7ff" data-textcolor="#0066cc" data-imgtheme="tech">科技风格</button>
</div>
<div class="button-group">
	<button id="downloadBtn">下载图片</button>
	<button id="clearBtn">清除Canvas</button>
</div>
<div id="canvasContainer">
	<!-- Canvas将在这里动态创建 -->
</div>
<div id="loadingText" class="loading">正在生成图片,请稍候...</div>

JS代码

document.addEventListener('DOMContentLoaded', function() {
	const generateBtns = document.querySelectorAll('.generate-btn');
	const downloadBtn = document.getElementById('downloadBtn');
	const clearBtn = document.getElementById('clearBtn');
	const canvasContainer = document.getElementById('canvasContainer');
	const loadingText = document.getElementById('loadingText');
	let canvas = null;
	let ctx = null;
	// 图片主题配置
	const imageThemes = {
		nature: [{
				text: "森林风光",
				color: "#27ae60"
			},
			{
				text: "山水美景",
				color: "#2980b9"
			},
			{
				text: "自然生态",
				color: "#16a085"
			}
		],
		art: [{
				text: "艺术创作",
				color: "#8e44ad"
			},
			{
				text: "绘画作品",
				color: "#9b59b6"
			},
			{
				text: "创意设计",
				color: "#e74c3c"
			}
		],
		food: [{
				text: "美食佳肴",
				color: "#e67e22"
			},
			{
				text: "甜品饮料",
				color: "#d35400"
			},
			{
				text: "食材原料",
				color: "#c0392b"
			}
		],
		tech: [{
				text: "科技创新",
				color: "#3498db"
			},
			{
				text: "数字未来",
				color: "#2c3e50"
			},
			{
				text: "智能生活",
				color: "#1abc9c"
			}
		]
	};

	// 为所有生成按钮添加点击事件
	generateBtns.forEach(btn => {
		btn.addEventListener('click', function() {
			const bgColor = this.dataset.bgcolor;
			const textColor = this.dataset.textcolor;
			const imgTheme = this.dataset.imgtheme;

			generateCanvas(bgColor, textColor, imgTheme);
		});
	});

	// 生成Canvas函数
	function generateCanvas(bgColor, textColor, imgTheme) {
		// 如果Canvas已存在,先清除
		if (canvas) {
			canvasContainer.removeChild(canvas);
		}

		// 显示加载提示
		loadingText.style.display = 'block';
		disableButtons();

		// 创建新的Canvas
		canvas = document.createElement('canvas');
		canvas.width = 750;
		canvas.height = 750;
		canvas.style.border = '1px solid #ccc';
		canvas.style.backgroundColor = 'white';
		canvasContainer.appendChild(canvas);

		ctx = canvas.getContext('2d');

		// 设置背景色
		ctx.fillStyle = bgColor;
		ctx.fillRect(0, 0, canvas.width, canvas.height);

		// 绘制文字 - 使用参数化样式
		const title = getThemeTitle(imgTheme);
		ctx.font = 'bold 50px "Microsoft YaHei", sans-serif';
		ctx.fillStyle = textColor;
		ctx.fillText(title, 50, 80);

		// 绘制主题相关文字
		const themeTexts = imageThemes[imgTheme];
		let yPos = 160;

		themeTexts.forEach((item, index) => {
			ctx.font = `${40 + index * 5}px Arial`;
			ctx.fillStyle = item.color;
			ctx.fillText(item.text, 50, yPos);
			yPos += 70;
		});

		// 绘制图片(图片地址,x坐标,y坐标)
		const images = [{
				url: `图片地址替换为同域名下图片地址,避免跨域无法绘制`,
				x: 50,
				y: 350
			},
			{
				url: `图片地址替换为同域名下图片地址,避免跨域无法绘制`,
				x: 350,
				y: 350
			},
			{
				url: `图片地址替换为同域名下图片地址,避免跨域无法绘制`,
				x: 50,
				y: 550
			}
		];

		let loadedImages = 0;

		function checkAllImagesLoaded() {
			loadedImages++;
			if (loadedImages === images.length) {
				// 所有图片加载完成后绘制边框
				ctx.strokeStyle = textColor;
				ctx.lineWidth = 3;
				images.forEach(imgInfo => {
					ctx.strokeRect(imgInfo.x, imgInfo.y, 250, 180);
				});

				// 完成生成
				canvas.style.display = 'block';
				loadingText.style.display = 'none';
				enableButtons();
				downloadBtn.style.display = 'inline-block';
				clearBtn.style.display = 'inline-block';
			}
		}

		images.forEach((imgInfo) => {
			const img = new Image();
			img.crossOrigin = 'Anonymous';
			img.onload = function() {
				ctx.drawImage(img, imgInfo.x, imgInfo.y, 250, 180);
				checkAllImagesLoaded();
			};
			img.onerror = function() {
				console.error('图片加载失败:', imgInfo.url);
				ctx.fillStyle = '#95a5a6';
				ctx.fillRect(imgInfo.x, imgInfo.y, 250, 180);
				ctx.fillStyle = textColor;
				ctx.font = '20px Arial';
				ctx.fillText('图片加载失败', imgInfo.x + 20, imgInfo.y + 100);
				checkAllImagesLoaded();
			};
			img.src = imgInfo.url;
		});
	}

	// 下载按钮点击事件
	downloadBtn.addEventListener('click', function() {
		if (!canvas) return;

		canvas.toBlob(function(blob) {
			const link = document.createElement('a');
			link.download = `canvas-${new Date().getTime()}.png`;
			link.href = URL.createObjectURL(blob);

			document.body.appendChild(link);
			link.click();

			setTimeout(function() {
				document.body.removeChild(link);
				URL.revokeObjectURL(link.href);
			}, 100);
		}, 'image/png', 1);
	});

	// 清除按钮点击事件
	clearBtn.addEventListener('click', function() {
		if (canvas) {
			canvasContainer.removeChild(canvas);
			canvas = null;
			ctx = null;
			downloadBtn.style.display = 'none';
			clearBtn.style.display = 'none';
		}
	});

	// 辅助函数
	function disableButtons() {
		generateBtns.forEach(btn => {
			btn.classList.add('button-disabled');
			btn.disabled = true;
		});
		downloadBtn.classList.add('button-disabled');
		downloadBtn.disabled = true;
		clearBtn.classList.add('button-disabled');
		clearBtn.disabled = true;
	}

	function enableButtons() {
		generateBtns.forEach(btn => {
			btn.classList.remove('button-disabled');
			btn.disabled = false;
		});
		downloadBtn.classList.remove('button-disabled');
		downloadBtn.disabled = false;
		clearBtn.classList.remove('button-disabled');
		clearBtn.disabled = false;
	}

	function getThemeTitle(theme) {
		const titles = {
			nature: "自然风光主题",
			art: "艺术创作主题",
			food: "美食文化主题",
			tech: "科技创新主题"
		};
		return titles[theme] || "自定义主题";
	}

	function itemToColor(colorStr) {
		return colorStr.replace('#', '');
	}
});

完整代码
https://download.youkuaiyun.com/download/weixin_43951315/90559184

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Good Lucky

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值