繁体   English   中英

画布的宽度/高度如何以及为什么与我的图像混乱?

[英]How and why is canvas width/height messing with my image drawing?

我正在尝试编写一个函数,该函数接受x,y坐标和旋转,并将围绕图像中心点旋转的图像插入画布。 这段代码可以正常工作:

 let img = new Image(), canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'), step = 0, drawImage = (ctx, img, x, y, degrees, w = 150, h = 150) => { ctx.save(); ctx.translate(x+w/4, y+h/4); ctx.rotate(degrees*Math.PI/180.0); ctx.translate(-xw/4, -yh/4); ctx.drawImage(img, x, y, w, h); ctx.restore(); }, animate = () => { ctx.globalCompositeOperation = 'destination-over'; // clear canvas ctx.clearRect(0, 0, window.innerWidth, window.innerHeight); drawImage(ctx, img, 0, 0, step) step++; window.requestAnimationFrame(animate); } img.src = "http://upload.wikimedia.org/wikipedia/commons/d/d2/Svg_example_square.svg"; animate(); 
 * { margin:0; padding:0; } /* to remove the top and left whitespace */ html, body { width:100%; height:100%; } /* just to be sure these are full screen*/ canvas { display:block;} /* To remove the scrollbars */ 
 <canvas id="canvas" width="300" height="300"> 

但是当我尝试调整画布大小时

canvas.width =window.innerWidth;
canvas.height = window.innerHeight;

这会使图像变形并且还会改变旋转点,在更大的窗口上效果更加清晰。 我怎样才能拥有一个充满屏幕的画布,并像使用HTML属性设置尺寸一样对待它呢?

 let img = new Image(), canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'), step = 0, drawImage = (ctx, img, x, y, degrees, w = 300, h = 300) => { ctx.save(); ctx.translate(x+w/4, y+h/4); ctx.rotate(degrees*Math.PI/180.0); ctx.translate(-xw/4, -yh/4); ctx.drawImage(img, x, y, w, h); ctx.restore(); }, animate = () => { ctx.globalCompositeOperation = 'destination-over'; // clear canvas ctx.clearRect(0, 0, window.innerWidth, window.innerHeight); drawImage(ctx, img, 0, 0, step) step++; window.requestAnimationFrame(animate); } img.src = "http://upload.wikimedia.org/wikipedia/commons/d/d2/Svg_example_square.svg"; canvas.width =window.innerWidth; canvas.height = window.innerHeight; animate(); 
  * { margin:0; padding:0; } /* to remove the top and left whitespace */ html, body { width:100%; height:100%; } /* just to be sure these are full screen*/ canvas { display:block;} /* To remove the scrollbars */ 
 <canvas id="canvas" width="300" height="300"> 

这是Chrome的“错误”,与您要求绘制的错误svg图像有关。

您绘制的svg没有绝对的widthheight属性,也没有viewBox

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <rect width="150" height="150" fill="rgb(0, 255, 0)" stroke-width="1" stroke="rgb(0, 0, 0)"/>
</svg>

这意味着它没有内部尺寸,也没有任何内部比率。 在HTML上下文中,浏览器仍可以通过应用内联替换元素中描述的规则来设置默认大小。

通过遵循这些规则,将svg保存在相对大小的容器中的<img>计算尺寸300 x 150pxwidth => 300pxheight => 2:1 * width => 150px )。 但是,其本征大小为0 ,Firefox将通过naturalXXX属性报告该大小,而Chrome会将其设置为300150

 onload = e => { const img = document.querySelector('img'); console.log( 'computed', img.width, // 300 img.height // 150 ); console.log( 'intrinsic', img.naturalWidth, // 0 in FF, 300 in Chrome img.naturalHeight // 0 in FF, 150 in Chrome ); } 
 img { border: 1px solid blue} 
 <img src="http://upload.wikimedia.org/wikipedia/commons/d/d2/Svg_example_square.svg"> 

现在,当您在画布上绘制此图像时,没有这样的CSS规则来指示应如何计算此计算出的大小,并且UA并不同意在画布上绘制此图像时会发生什么。
Firefox将根本无法绘制它(记住,他们成立naturalXXX0 。Chrome将使用一些魔法试探法来绘制它认为它应该得出的最好的。这就是我所说的错误。
如果在drawImage中使用的HTMLImageElement没有srcset (即,其密度为1 ),则drawImage(img, x, y)产生与drawImage(img, x, y, img.naturalWidth, img.naturalHeight)相同的结果。
但是,鉴于它们用于这些图像的魔力没有内在的大小,因此不会发生这种情况。

因此,您会看到它在Chrome中变形,因为您要求将其绘制为300 x 300矩形。

 const img = new Image(), canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'), draw = async () => { const w = img.naturalWidth, h = img.naturalHeight; console.log('reported img size', w, h); ctx.fillRect(0, 0, w, h); await wait(2000); console.log('drawImage with reported size'); ctx.drawImage(img, 0, 0, w, h); await wait(2000); console.log('default drawImage'); ctx.drawImage(img, 0, 0); }; img.src = "http://upload.wikimedia.org/wikipedia/commons/d/d2/Svg_example_square.svg"; canvas.width = window.innerWidth; canvas.height = window.innerHeight; img.onload = draw; function wait(ms) { return new Promise(res => setTimeout(res, ms)); } 
 <canvas id="canvas" width="300" height="300"> 

因此,您可以尝试通过drawImage(img, x, y, w, h)来测量所需的比率,该比率与仅使用3个参数时相同,但最好的办法是使用正确的svg,并使用绝对宽度和高度设置,这将使其适用于所有浏览器:

 let img = new Image(), canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'), step = 0, drawImage = (ctx, img, x, y, degrees, w = 300, h = 300) => { ctx.save(); ctx.translate(x + w / 4, y + h / 4); ctx.rotate(degrees * Math.PI / 180.0); ctx.translate(-x - w / 4, -y - h / 4); ctx.drawImage(img, x, y, w, h); ctx.restore(); }, animate = () => { ctx.globalCompositeOperation = 'destination-over'; // clear canvas ctx.clearRect(0, 0, window.innerWidth, window.innerHeight); drawImage(ctx, img, 0, 0, step) step++; window.requestAnimationFrame(animate); } canvas.width = window.innerWidth; canvas.height = window.innerHeight; img.onload = animate; fetch("https://upload.wikimedia.org/wikipedia/commons/d/d2/Svg_example_square.svg") .then(resp => resp.text()) .then(markup => { const mime = 'image/svg+xml'; const doc = new DOMParser().parseFromString(markup, mime); doc.documentElement.setAttribute('width', 150); doc.documentElement.setAttribute('height', 150); img.src = URL.createObjectURL( new Blob( [new XMLSerializer().serializeToString(doc)], { type: mime } ) ); }) .catch(console.error); 
 * { margin:0; padding:0; } /* to remove the top and left whitespace */ html, body { width:100%; height:100%; } /* just to be sure these are full screen*/ canvas { display:block;} /* To remove the scrollbars */ 
 <canvas id="canvas" width="300" height="300"> 

尝试改变

canvas.width =window.innerWidth;
canvas.height = window.innerHeight;

canvas.style.width = "100%";
canvas.style.height = "100%";

 let img = new Image(), canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'), step = 0, drawImage = (ctx, img, x, y, degrees, w = 300, h = 300) => { ctx.save(); ctx.translate(x+w/4, y+h/4); ctx.rotate(degrees*Math.PI/180.0); ctx.translate(-xw/4, -yh/4); ctx.drawImage(img, x, y, w, h); ctx.restore(); }, animate = () => { ctx.globalCompositeOperation = 'destination-over'; // clear canvas ctx.clearRect(0, 0, window.innerWidth, window.innerHeight); drawImage(ctx, img, 0, 0, step) step++; window.requestAnimationFrame(animate); } img.src = "http://upload.wikimedia.org/wikipedia/commons/d/d2/Svg_example_square.svg"; canvas.style.width = "100%"; canvas.style.height = "100%"; animate(); 
 * { margin:0; padding:0; } /* to remove the top and left whitespace */ html, body { width:100%; height:100%; } /* just to be sure these are full screen*/ canvas { display:block;} /* To remove the scrollbars */ 
 <canvas id="canvas"> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM