使用JavaScript向HTML Canvas插入图片不显示问题求助
Canvas图片不显示问题修复方案
问题原因
你的代码存在三个核心问题:
- 没有在draw函数中应用缩放和平移变换,scale、translatePos参数完全没有被使用,缩放拖拽逻辑失效
- 图片加载是异步操作,你每次调用draw都会重新创建Image实例发起请求,图片加载完成的时机晚于draw函数执行,导致首次渲染看不到图片
- 绘制图片时没有做画布状态管理,也没有适配变换后的坐标,就算图片加载出来也不会显示在预期位置
修复后的完整代码
HTML代码
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <body onmousedown="return false;"> <div id="wrapper"> <canvas id="myCanvas" width="578" height="200"> </canvas> <div id="buttonWrapper"> <input type="button" id="plus" value="+"><input type="button" id="minus" value="-"> </div> </div> <h2 id="status"> 0, 0 </h2> </body>
CSS代码
body { margin: 0px; padding: 0px; } #wrapper { position: relative; border: 1px solid #9C9898; width: 578px; height: 200px; } #buttonWrapper { position: absolute; width: 30px; top: 2px; right: 2px; } input[type="button"] { padding: 5px; width: 30px; margin: 0px 0px 2px 0px; }
JS代码
// 提前预加载图片,避免每次重绘都重新请求 let base_image = new Image(); base_image.src = 'https://www.gstatic.com/webp/gallery3/1.sm.png'; // 图片加载完成后再触发首次绘制 let imgLoaded = false; base_image.onload = function() { imgLoaded = true; draw(scale, translatePos); } let translatePos; let scale = 1.0; const scaleMultiplier = 0.8; function draw(scale, translatePos) { // 图片未加载完成直接返回 if(!imgLoaded) return; var canvas = document.getElementById("myCanvas"); var context = canvas.getContext("2d"); // 清空画布 context.clearRect(0, 0, canvas.width, canvas.height); // 保存当前上下文状态 context.save(); // 应用平移和缩放变换 context.translate(translatePos.x, translatePos.y); context.scale(scale, scale); // 绘制图片,调整偏移量让图片居中对齐 context.drawImage(base_image, -base_image.width/2, -base_image.height/2); // 恢复上下文状态,避免后续操作叠加变换 context.restore(); } window.onload = function() { var canvas = document.getElementById("myCanvas"); translatePos = { x: canvas.width / 2, y: canvas.height / 2 }; var startDragOffset = {}; var mouseDown = false; // 缩放按钮事件 document.getElementById("plus").addEventListener("click", function() { scale /= scaleMultiplier; draw(scale, translatePos); }, false); document.getElementById("minus").addEventListener("click", function() { scale *= scaleMultiplier; draw(scale, translatePos); }, false); // 拖拽事件 canvas.addEventListener("mousedown", function(evt) { mouseDown = true; startDragOffset.x = evt.clientX - translatePos.x; startDragOffset.y = evt.clientY - translatePos.y; }); canvas.addEventListener("mouseup", function(evt) { mouseDown = false; }); canvas.addEventListener("mouseover", function(evt) { mouseDown = false; }); canvas.addEventListener("mouseout", function(evt) { mouseDown = false; }); canvas.addEventListener("mousemove", function(evt) { if (mouseDown) { translatePos.x = evt.clientX - startDragOffset.x; translatePos.y = evt.clientY - startDragOffset.y; draw(scale, translatePos); } }); }; jQuery(document).ready(function() { $("#wrapper").mousemove(function(e) { $('#status').html(e.pageX + ', ' + e.pageY); }); })
额外优化说明
- 把鼠标坐标监听的mouseover改成了mousemove,坐标会跟随鼠标移动实时更新,更符合使用习惯
- 增加了图片加载完成标识,避免图片加载完成前执行绘制逻辑报错
- 每次重绘前清空画布,避免缩放拖拽时出现重影
内容的提问来源于stack exchange,提问作者Zubair Nazer Oliyat
相关产品推荐
相关产品推荐

