是否可以修复HTML5 canvas
元素的宽度和高度?
通常的方法如下:
<canvas id="canvas" width="300" height="300"></canvas>
canvas
DOM元素具有.height
和.width
属性,对应于height="…"
和width="…"
属性。在JavaScript代码中将它们设置为数值以调整画布大小。例如:
var canvas = document.getElementsByTagName('canvas')[0];
canvas.width = 800;
canvas.height = 600;
请注意,这会清除画布,但您应该使用ctx.clearRect( 0, 0, ctx.canvas.width, ctx.canvas.height);
来处理那些不能完全清除画布的浏览器。您需要重新绘制尺寸更改后想要显示的任何内容。
另请注意,高度和宽度是用于绘制的逻辑画布尺寸,并且与style.height
和style.width
CSS属性不同。如果未设置CSS属性,则画布的固有大小将用作其显示大小;如果您设置了CSS属性,并且它们与画布尺寸不同,则您的内容将在浏览器中缩放。例如:
// Make a canvas that has a blurry pixelated zoom-in
// with each canvas pixel drawn showing as roughly 2x2 on screen
canvas.width = 400;
canvas.height = 300;
canvas.style.width = '800px';
canvas.style.height = '600px';
请参阅放大4倍的画布的this live example。
var c = document.getElementsByTagName('canvas')[0];
var ctx = c.getContext('2d');
ctx.lineWidth = 1;
ctx.strokeStyle = '#f00';
ctx.fillStyle = '#eff';
ctx.fillRect( 10.5, 10.5, 20, 20 );
ctx.strokeRect( 10.5, 10.5, 20, 20 );
ctx.fillRect( 40, 10.5, 20, 20 );
ctx.strokeRect( 40, 10.5, 20, 20 );
ctx.fillRect( 70, 10, 20, 20 );
ctx.strokeRect( 70, 10, 20, 20 );
ctx.strokeStyle = '#fff';
ctx.strokeRect( 10.5, 10.5, 20, 20 );
ctx.strokeRect( 40, 10.5, 20, 20 );
ctx.strokeRect( 70, 10, 20, 20 );
body { background:#eee; margin:1em; text-align:center }
canvas { background:#fff; border:1px solid #ccc; width:400px; height:160px }
<canvas width="100" height="40"></canvas>
<p>Showing that re-drawing the same antialiased lines does not obliterate old antialiased lines.</p>
画布有2种尺寸,画布中像素的尺寸(它是backingstore或drawingBuffer)和显示尺寸。使用画布属性设置像素数。在HTML中
<canvas width="400" height="300"></canvas>
或者在JavaScript中
someCanvasElement.width = 400;
someCanvasElement.height = 300;
与此分开的是画布的CSS样式宽度和高度
在CSS中
canvas { /* or some other selector */
width: 500px;
height: 400px;
}
或者在JavaScript中
canvas.style.width = "500px";
canvas.style.height = "400px";
制作1x1像素画布的最佳方法是始终使用CSS来选择大小,然后编写一小部分JavaScript以使像素数与该大小相匹配。
function resizeCanvasToDisplaySize(canvas) {
// look up the size the canvas is being displayed
const width = canvas.clientWidth;
const height = canvas.clientHeight;
// If it's resolution does not match change it
if (canvas.width !== width || canvas.height !== height) {
canvas.width = width;
canvas.height = height;
return true;
}
return false;
}
为什么这是最好的方式?因为它适用于大多数情况而无需更改任何代码。
const ctx = document.querySelector("#c").getContext("2d");
function render(time) {
time *= 0.001;
resizeCanvasToDisplaySize(ctx.canvas);
ctx.fillStyle = "#DDE";
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.save();
const spacing = 64;
const size = 48;
const across = ctx.canvas.width / spacing + 1;
const down = ctx.canvas.height / spacing + 1;
const s = Math.sin(time);
const c = Math.cos(time);
for (let y = 0; y < down; ++y) {
for (let x = 0; x < across; ++x) {
ctx.setTransform(c, -s, s, c, x * spacing, y * spacing);
ctx.strokeRect(-size / 2, -size / 2, size, size);
}
}
ctx.restore();
requestAnimationFrame(render);
}
requestAnimationFrame(render);
function resizeCanvasToDisplaySize(canvas) {
// look up the size the canvas is being displayed
const width = canvas.clientWidth;
const height = canvas.clientHeight;
// If it's resolution does not match change it
if (canvas.width !== width || canvas.height !== height) {
canvas.width = width;
canvas.height = height;
return true;
}
return false;
}
body { margin: 0; }
canvas { display: block; width: 100vw; height: 100vh; }
<canvas id="c"></canvas>
const ctx = document.querySelector("#c").getContext("2d");
function render(time) {
time *= 0.001;
resizeCanvasToDisplaySize(ctx.canvas);
ctx.fillStyle = "#DDE";
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.save();
const spacing = 64;
const size = 48;
const across = ctx.canvas.width / spacing + 1;
const down = ctx.canvas.height / spacing + 1;
const s = Math.sin(time);
const c = Math.cos(time);
for (let y = 0; y <= down; ++y) {
for (let x = 0; x <= across; ++x) {
ctx.setTransform(c, -s, s, c, x * spacing, y * spacing);
ctx.strokeRect(-size / 2, -size / 2, size, size);
}
}
ctx.restore();
requestAnimationFrame(render);
}
requestAnimationFrame(render);
function resizeCanvasToDisplaySize(canvas) {
// look up the size the canvas is being displayed
const width = canvas.clientWidth;
const height = canvas.clientHeight;
// If it's resolution does not match change it
if (canvas.width !== width || canvas.height !== height) {
canvas.width = width;
canvas.height = height;
return true;
}
return false;
}
span {
width: 250px;
height: 100px;
float: left;
padding: 1em 1em 1em 0;
display: inline-block;
}
canvas {
width: 100%;
height: 100%;
}
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent cursus venenatis metus. Mauris ac nibh at odio scelerisque scelerisque. Donec ut enim <span class="diagram"><canvas id="c"></canvas></span>
vel urna gravida imperdiet id ac odio. Aenean congue hendrerit eros id facilisis. In vitae leo ullamcorper, aliquet leo a, vehicula magna. Proin sollicitudin vestibulum aliquet. Sed et varius justo.
<br/><br/>
Quisque tempor metus in porttitor placerat. Nulla vehicula sem nec ipsum commodo, at tincidunt orci porttitor. Duis porttitor egestas dui eu viverra. Sed et ipsum eget odio pharetra semper. Integer tempor orci quam, eget aliquet velit consectetur sit amet. Maecenas maximus placerat arcu in varius. Morbi semper, quam a ullamcorper interdum, augue nisl sagittis urna, sed pharetra lectus ex nec elit. Nullam viverra lacinia tellus, bibendum maximus nisl dictum id. Phasellus mauris quam, rutrum ut congue non, hendrerit sollicitudin urna.
</p>
const ctx = document.querySelector("#c").getContext("2d");
function render(time) {
time *= 0.001;
resizeCanvasToDisplaySize(ctx.canvas);
ctx.fillStyle = "#DDE";
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.save();
const spacing = 64;
const size = 48;
const across = ctx.canvas.width / spacing + 1;
const down = ctx.canvas.height / spacing + 1;
const s = Math.sin(time);
const c = Math.cos(time);
for (let y = 0; y < down; ++y) {
for (let x = 0; x < across; ++x) {
ctx.setTransform(c, -s, s, c, x * spacing, y * spacing);
ctx.strokeRect(-size / 2, -size / 2, size, size);
}
}
ctx.restore();
requestAnimationFrame(render);
}
requestAnimationFrame(render);
function resizeCanvasToDisplaySize(canvas) {
// look up the size the canvas is being displayed
const width = canvas.clientWidth;
const height = canvas.clientHeight;
// If it's resolution does not match change it
if (canvas.width !== width || canvas.height !== height) {
canvas.width = width;
canvas.height = height;
return true;
}
return false;
}
// ----- the code above related to the canvas does not change ----
// ---- the code below is related to the slider ----
const $ = document.querySelector.bind(document);
const left = $(".left");
const slider = $(".slider");
let dragging;
let lastX;
let startWidth;
slider.addEventListener('mousedown', e => {
lastX = e.pageX;
dragging = true;
});
window.addEventListener('mouseup', e => {
dragging = false;
});
window.addEventListener('mousemove', e => {
if (dragging) {
const deltaX = e.pageX - lastX;
left.style.width = left.clientWidth + deltaX + "px";
lastX = e.pageX;
}
});
body {
margin: 0;
}
.frame {
display: flex;
align-items: space-between;
height: 100vh;
}
.left {
width: 70%;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
canvas {
width: 100%;
height: 100%;
}
pre {
padding: 1em;
}
.slider {
width: 10px;
background: #000;
}
.right {
flex 1 1 auto;
}
<div class="frame">
<div class="left">
<canvas id="c"></canvas>
</div>
<div class="slider">
</div>
<div class="right">
<pre>
* controls
* go
* here
<- drag this
</pre>
</div>
</div>
const ctx = document.querySelector("#c").getContext("2d");
function render(time) {
time *= 0.001;
resizeCanvasToDisplaySize(ctx.canvas);
ctx.fillStyle = "#DDE";
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.save();
const spacing = 64;
const size = 48;
const across = ctx.canvas.width / spacing + 1;
const down = ctx.canvas.height / spacing + 1;
const s = Math.sin(time);
const c = Math.cos(time);
for (let y = 0; y < down; ++y) {
for (let x = 0; x < across; ++x) {
ctx.setTransform(c, -s, s, c, x * spacing, y * spacing);
ctx.strokeRect(-size / 2, -size / 2, size, size);
}
}
ctx.restore();
requestAnimationFrame(render);
}
requestAnimationFrame(render);
function resizeCanvasToDisplaySize(canvas) {
// look up the size the canvas is being displayed
const width = canvas.clientWidth;
const height = canvas.clientHeight;
// If it's resolution does not match change it
if (canvas.width !== width || canvas.height !== height) {
canvas.width = width;
canvas.height = height;
return true;
}
return false;
}
body { margin: 0; }
canvas {
display: block;
width: 100vw;
height: 100vh;
position: fixed;
}
#content {
position: absolute;
margin: 0 1em;
font-size: xx-large;
font-family: sans-serif;
font-weight: bold;
text-shadow: 2px 2px 0 #FFF,
-2px -2px 0 #FFF,
-2px 2px 0 #FFF,
2px -2px 0 #FFF;
}
<canvas id="c"></canvas>
<div id="content">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent cursus venenatis metus. Mauris ac nibh at odio scelerisque scelerisque. Donec ut enim vel urna gravida imperdiet id ac odio. Aenean congue hendrerit eros id facilisis. In vitae leo ullamcorper, aliquet leo a, vehicula magna. Proin sollicitudin vestibulum aliquet. Sed et varius justo.
</p>
<p>
Quisque tempor metus in porttitor placerat. Nulla vehicula sem nec ipsum commodo, at tincidunt orci porttitor. Duis porttitor egestas dui eu viverra. Sed et ipsum eget odio pharetra semper. Integer tempor orci quam, eget aliquet velit consectetur sit amet. Maecenas maximus placerat arcu in varius. Morbi semper, quam a ullamcorper interdum, augue nisl sagittis urna, sed pharetra lectus ex nec elit. Nullam viverra lacinia tellus, bibendum maximus nisl dictum id. Phasellus mauris quam, rutrum ut congue non, hendrerit sollicitudin urna.
</p>
</div>
因为我没有设置属性,所以每个样本中唯一改变的是CSS(就画布而言)
笔记:
非常感谢你!最后我用这段代码解决了模糊像素问题:
<canvas id="graph" width=326 height=240 style='width:326px;height:240px'></canvas>
添加“半像素”可以解开线条。
最好的方法:
<canvas id="myChart" style="height: 400px; width: 100px;"></canvas>