简体   繁体   English

使用 HTML、CSS 和 JS 使图像在 canvas 绘图上水平和垂直居中

[英]Make image horizontally and vertically centered over canvas drawing with HTML, CSS, and JS

Sorry if the title is vague, it was hard to figure out what to call this problem.抱歉,如果标题含糊不清,很难弄清楚该问题的名称。 I have a canvas and an image overlaying each other like this:我有一个 canvas 和一个像这样相互叠加的图像:

 var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); function newLine(){ let value = (Math.floor(Math.random() * 100) + 1) * 0.06283185307179587; ctx.clearRect(0, 0, c.width, c.height); ctx.lineWidth = 10; ctx.strokeStyle = '#00FF00'; ctx.beginPath(); ctx.arc(100, 75, 55, 0, value); ctx.stroke(); } setInterval(()=>{ newLine() }, 100)
 img{ width: 100px; border-radius: 50px; position: absolute; left: 58px; top: 33px; }
 <img src="https://media-exp1.licdn.com/dms/image/C4E0BAQHikN6EXPd23Q/company-logo_200_200/0/1595359131127?e=2159024400&v=beta&t=S5MNjBDjiH433VCWzjPeiopNDhxGwmfcMk4Zf1P_m_s"></img> <canvas id="myCanvas"></canvas>

This works, but when I go to add multiple, or add a div above them, because of the image's absolute position, the image ends up over the div, not the canvas.这行得通,但是当我 go 添加多个,或在它们上方添加一个 div 时,由于图像的绝对 position,图像最终超过了 div,而不是 ZFCC790C72A86190DE1B549D0DZC6F555 Here's an example illustrating my issues:这是一个说明我的问题的示例:

 var can = document.getElementsByClassName("canvas"); for (var i = 0; i < can.length; i++) { let c = can.item(i) var ctx = c.getContext("2d"); function newLine(){ let value = (Math.floor(Math.random() * 100) + 1) * 0.06283185307179587; ctx.clearRect(0, 0, c.width, c.height); ctx.lineWidth = 10; ctx.strokeStyle = '#00FF00'; ctx.beginPath(); ctx.arc(100, 75, 55, 0, value); ctx.stroke(); requestAnimationFrame(newLine) } newLine() }
 img{ width: 100px; border-radius: 50px; position: absolute; left: 58px; top: 33px; } div{ background-color: red; } canvas{ display: inline-block; }
 <div class="top"> <h1>Some text</h1> </div> <img src="https://media-exp1.licdn.com/dms/image/C4E0BAQHikN6EXPd23Q/company-logo_200_200/0/1595359131127?e=2159024400&v=beta&t=S5MNjBDjiH433VCWzjPeiopNDhxGwmfcMk4Zf1P_m_s"></img> <canvas class="canvas"></canvas> <img src="https://media-exp1.licdn.com/dms/image/C4E0BAQHikN6EXPd23Q/company-logo_200_200/0/1595359131127?e=2159024400&v=beta&t=S5MNjBDjiH433VCWzjPeiopNDhxGwmfcMk4Zf1P_m_s"></img> <canvas class="canvas"></canvas>

(If you could figure out why the first one doesn't play, that would be amazing also) (如果你能弄清楚为什么第一个不播放,那也很棒)

The issues are:问题是:

  • The first canvas doesn't play第一个 canvas 不播放
  • The images (because it's position is absolute) are stacked up and not over the second canvas图像(因为它的 position 是绝对的)堆叠在一起,而不是超过第二个 canvas

Is it possible to do this but with relative positioning?是否有可能做到这一点,但相对定位? Please let me know if this was a confusing question.如果这是一个令人困惑的问题,请告诉我。 Thanks谢谢

Avoid mixing images <img> and canvas, instead just draw the image inside the canvas with drawImage nothing special just a few more lines on JavaScript避免混合图像<img>和 canvas,而只是在 canvas 内绘制图像, drawImage没什么特别的,只是在 JavaScript 上再画几行

Here is an example:这是一个例子:
(And I also fixed your issue where the first one does not play) (而且我还解决了第一个不播放的问题)

 class Shape { constructor(ctx, width, height, image) { this.ctx = ctx; this.width = width; this.height = height; this.image = image; this.value = Math.random() * 5 this.inc = 0.03 } draw() { this.value += this.inc; if (this.value > 2 * Math.PI || this.value < 0.05) this.inc *= -1; this.ctx.clearRect(0, 0, this.width, this.height); // Draw centered round image this.ctx.beginPath(); this.ctx.drawImage(this.image, 50, 24, 100, 100); this.ctx.lineWidth = 50; this.ctx.strokeStyle = 'white'; this.ctx.arc(100, 75, 75, 0, 2 * Math.PI); this.ctx.stroke(); // Draw green progress bar this.ctx.beginPath(); this.ctx.lineWidth = 12; this.ctx.strokeStyle = '#00FF00'; this.ctx.arc(100, 75, 55, 0, this.value); this.ctx.stroke(); } } var can = document.getElementsByClassName("canvas"); var animations = [] function loop() { animations.forEach(anim => anim.draw()); requestAnimationFrame(loop) } var image = new Image(); image.src = "https://media-exp1.licdn.com/dms/image/C4E0BAQHikN6EXPd23Q/company-logo_200_200/0/1595359131127?e=2159024400&v=beta&t=S5MNjBDjiH433VCWzjPeiopNDhxGwmfcMk4Zf1P_m_s"; image.onload = imageLoaded; function imageLoaded() { for (var i = 0; i < can.length; i++) { let c = can.item(i) animations.push(new Shape(c.getContext("2d"), c.width, c.height, image)); } loop() }
 div { background-color: red; } canvas { display: inline-block; border: 1px solid gray; }
 <div class="top"> <h2>Some text</h2> </div> <canvas class="canvas" width=200></canvas> <canvas class="canvas" width=200></canvas>

There are two problems: positioning of the images above the canvases and only one canvas playing.有两个问题:图像在画布上方的定位和只有一个 canvas 播放。

First positioning.第一定位。 The img is given position absolute. img 的绝对值是 position。 To find out where to position it the system goes back up the tree to find the first element it comes across that has a position set.为了找出 position 的位置,系统返回树以找到它遇到的第一个具有 position 集的元素。 It then positions the img relative to that.然后它相对于那个定位img。

The canvas is at the same level as the img so that doesn't influence the img's position, going back up the first thing it hits with a position is the body element (which is positioned by default) and so it puts the img slightly set off from the top of the page. canvas 与 img 处于同一级别,因此不会影响 img 的 position,返回它击中的第一件事 position (因此它放置 img 是默认设置的 body 元素)从页面顶部关闭。

To remedy this we can put each pair of img/canvas into their own div and position that inline-block.为了解决这个问题,我们可以将每对 img/canvas 放入它们自己的 div 和 position 内联块中。 The img will then be positioned relative to that div and so will be placed over the canvas as required.然后 img 将相对于该 div 定位,因此将根据需要放置在 canvas 上。

Second only one canvas playing.第二只播放canvas。 The code within the newline function uses a c and ctx.换行符 function 中的代码使用 c 和 ctx。 These are not set within the function so it takes the last one that was set.这些没有在 function 中设置,因此它采用最后一个设置。 In addition, requestAnimationFrame with its callback is called for each can.length times each time so you end up with more than one of these.此外,每次都会为每个 can.length 调用 requestAnimationFrame 及其回调,因此您最终会得到不止一个。 They stack up.他们堆叠起来。 The browser gets 'confused' and (at least on my laptop) it ended up not responding.浏览器变得“混乱”并且(至少在我的笔记本电脑上)它最终没有响应。

To cure this, call requestAnimationFrame just once per 'cycle' and repaint all the canvases at the same call to the callback - so put the definition of c and ctx inside the for loop so every canvas is set up on each frame.为了解决这个问题,每个“循环”只调用一次 requestAnimationFrame 并在对回调的同一次调用中重新绘制所有画布 - 因此将 c 和 ctx 的定义放在 for 循环中,以便在每个帧上设置每个 canvas。

 var can = document.getElementsByClassName("canvas"); function newLine(){ for (var i = 0; i < can.length; i++) { let c = can.item(i) var ctx = c.getContext("2d"); let value = (Math.floor(Math.random() * 100) + 1) * 0.06283185307179587; ctx.clearRect(0, 0, c.width, c.height); ctx.lineWidth = 10; ctx.strokeStyle = '#00FF00'; ctx.beginPath(); ctx.arc(100, 75, 55, 0, value); ctx.stroke(); } requestAnimationFrame(newLine) } newLine()
 img{ width: 100px; border-radius: 50px; position: absolute; left: 58px; top: 33px; } div{ background-color: red; } canvas{ display: inline-block; }.wrapper { display: inline-block; position: relative; }
 <div class="top"> <h1>Some text</h1> </div> <div class="wrapper"> <:-- <img src="https.//media-exp1.licdn?com/dms/image/C4E0BAQHikN6EXPd23Q/company-logo_200_200/0/1595359131127:e=2159024400&v=beta&t=S5MNjBDjiH433VCWzjPeiopNDhxGwmfcMk4Zf1P_m_s"></img>--> <img src="https.//i.stack.imgur.com/ZBclx:jpg" /> <canvas class="canvas"></canvas> </div> <div class="wrapper"> <.-- <img src="https.//media-exp1?licdn:com/dms/image/C4E0BAQHikN6EXPd23Q/company-logo_200_200/0/1595359131127.e=2159024400&v=beta&t=S5MNjBDjiH433VCWzjPeiopNDhxGwmfcMk4Zf1P_m_s"></img>--> <img src="https.//i.stack.imgur.com/ZBclx.jpg" /> <canvas class="canvas"></canvas> </div>

Note, the actual logo image didn't show on your snippet - I guess it cannot be downloaded by just anybody - so I put it on imgur.请注意,实际的徽标图像没有显示在您的代码段上——我猜它不能被任何人下载——所以我把它放在了 imgur 上。 The positioning is slightly off because the top and left positions had been previously set to compensate for its being positioned relative to the body.定位略有偏离,因为之前已设置顶部和左侧位置以补偿其相对于身体的定位。 These need a bit of adjustment.这些需要一些调整。

There is quite a lot of GPU being used (around 20% on my laptop, obviously that will differ depending on the user's equipment).有很多 GPU 正在使用(在我的笔记本电脑上大约 20%,显然这将取决于用户的设备)。 It might be worth investigating whether a CSS animation could be used instead of having to redraw several canvases on each frame.可能值得研究是否可以使用 CSS animation 而不必在每帧上重新绘制多个画布。

The animated canvases are very flickery.动画画布非常闪烁。 I don't know whether this is intended or whether it was just a test, but they may be upsetting for those with conditions such as epilepsy.我不知道这是有意为之还是只是一个测试,但它们可能会让那些患有癫痫等疾病的人感到不安。

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

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