阿里云主机折上折
  • 微信号
Current Site:Index > `<canvas>` - graphics drawing canvas

`<canvas>` - graphics drawing canvas

Author:Chuan Chen 阅读数:48123人阅读 分类: HTML

<canvas> is a powerful tag introduced in HTML5 for dynamically drawing graphics, animations, or interactive content on web pages. It provides a complete drawing API through JavaScript, supporting pixel-level operations, making it suitable for scenarios like game development and data visualization.

Basic Usage of <canvas>

The <canvas> tag itself is just a container; content must be drawn using JavaScript. Its basic syntax is as follows:

<canvas id="myCanvas" width="500" height="300"></canvas>

The width and height attributes define the dimensions of the canvas. If not set, the default width is 300px and the default height is 150px. It is recommended to always explicitly set these attributes to avoid distortion caused by CSS scaling.

Obtaining the Drawing Context

To draw on <canvas>, you first need to obtain the rendering context. The 2D drawing context is the most commonly used:

const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');

getContext('2d') returns a CanvasRenderingContext2D object, which provides all the 2D drawing methods.

Drawing Basic Shapes

Rectangles

Canvas provides three methods for drawing rectangles:

// Fill a rectangle
ctx.fillStyle = 'blue';
ctx.fillRect(50, 50, 100, 75);

// Stroke a rectangle
ctx.strokeStyle = 'red';
ctx.lineWidth = 3;
ctx.strokeRect(200, 50, 100, 75);

// Clear a rectangular area
ctx.clearRect(80, 80, 40, 20);

Path Drawing

Complex shapes are created using paths:

// Draw a triangle
ctx.beginPath();
ctx.moveTo(100, 100);  // Starting point
ctx.lineTo(150, 50);
ctx.lineTo(200, 100);
ctx.closePath();  // Automatically close the path
ctx.stroke();

// Draw a circle
ctx.beginPath();
ctx.arc(300, 200, 50, 0, Math.PI * 2);  // x, y, radius, start angle, end angle
ctx.fillStyle = 'green';
ctx.fill();

Styles and Colors

Canvas offers rich styling options:

// Linear gradient
const gradient = ctx.createLinearGradient(0, 0, 200, 0);
gradient.addColorStop(0, 'red');
gradient.addColorStop(1, 'yellow');
ctx.fillStyle = gradient;
ctx.fillRect(50, 150, 200, 100);

// Shadow effects
ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
ctx.shadowBlur = 10;
ctx.shadowOffsetX = 5;
ctx.shadowOffsetY = 5;
ctx.fillRect(300, 150, 100, 100);

Text Drawing

Canvas can draw text with various styling options:

ctx.font = '30px Arial';
ctx.fillStyle = 'purple';
ctx.textAlign = 'center';
ctx.fillText('Hello Canvas', canvas.width/2, 50);

// Stroked text
ctx.font = 'bold 40px sans-serif';
ctx.strokeStyle = 'black';
ctx.lineWidth = 2;
ctx.strokeText('Stroke Text', 150, 120);

Image Operations

Canvas can draw, scale, and crop images:

const img = new Image();
img.src = 'example.jpg';
img.onload = function() {
  // Draw the original image
  ctx.drawImage(img, 10, 10);
  
  // Draw scaled image
  ctx.drawImage(img, 150, 10, 100, 80);
  
  // Crop and draw part of the image
  ctx.drawImage(img, 50, 50, 100, 100, 300, 10, 100, 100);
};

Animation Implementation

Smooth animations can be achieved using requestAnimationFrame:

let x = 0;
function animate() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.fillRect(x, 100, 50, 50);
  x += 2;
  if (x > canvas.width) x = 0;
  requestAnimationFrame(animate);
}
animate();

Advanced Techniques

Saving and Restoring State

Canvas states (styles, transformations, etc.) can be managed using a stack:

ctx.fillStyle = 'red';
ctx.save();  // Save the current state

ctx.fillStyle = 'blue';
ctx.fillRect(50, 50, 100, 100);

ctx.restore();  // Restore the previously saved state
ctx.fillRect(200, 50, 100, 100);  // Will use red fill

Transformation Operations

Canvas supports transformations like translation, rotation, and scaling:

ctx.fillStyle = 'orange';
ctx.translate(150, 150);  // Move the origin
ctx.rotate(Math.PI / 4);  // Rotate 45 degrees
ctx.fillRect(-50, -50, 100, 100);  // Draw centered at the new origin

Pixel Manipulation

You can directly manipulate pixel data:

const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;

// Invert colors
for (let i = 0; i < data.length; i += 4) {
  data[i] = 255 - data[i];      // R
  data[i+1] = 255 - data[i+1];  // G
  data[i+2] = 255 - data[i+2];  // B
}

ctx.putImageData(imageData, 0, 0);

Performance Optimization

For complex Canvas applications, performance optimization is crucial:

  1. Layered Rendering: Use multiple overlapping <canvas> elements to separate static and dynamic content.
  2. Avoid Floating-Point Coordinates: Use integer coordinates to prevent blurring from sub-pixel rendering.
  3. Batch Operations: Minimize state changes (e.g., style changes).
  4. Offscreen Canvas: Pre-render complex graphics to a hidden canvas.
// Offscreen Canvas example
const offscreenCanvas = document.createElement('canvas');
const offscreenCtx = offscreenCanvas.getContext('2d');
// Pre-render complex graphics on the offscreen canvas
offscreenCtx.fillRect(0, 0, 100, 100);
// Draw the pre-rendered content on the main canvas
ctx.drawImage(offscreenCanvas, 0, 0);

Implementing Interactivity

Canvas itself has no built-in interactivity, but it can be achieved through event listeners:

canvas.addEventListener('click', function(event) {
  const rect = canvas.getBoundingClientRect();
  const x = event.clientX - rect.left;
  const y = event.clientY - rect.top;
  
  if (ctx.isPointInPath(x, y)) {
    alert('Clicked on the shape!');
  }
});

WebGL Integration

<canvas> also supports 3D graphics rendering via WebGL:

const gl = canvas.getContext('webgl');
if (gl) {
  // WebGL code
  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  gl.clear(gl.COLOR_BUFFER_BIT);
}

Practical Application Examples

Drawing Charts

// Simple bar chart
const data = [30, 60, 90, 40, 70];
const barWidth = 50;
const spacing = 20;

ctx.fillStyle = 'steelblue';
data.forEach((value, index) => {
  const x = index * (barWidth + spacing);
  const height = value * 2;
  ctx.fillRect(x, canvas.height - height, barWidth, height);
});

Drawing Board Application

let isDrawing = false;

canvas.addEventListener('mousedown', startDrawing);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', stopDrawing);
canvas.addEventListener('mouseout', stopDrawing);

function startDrawing(e) {
  isDrawing = true;
  draw(e);
}

function draw(e) {
  if (!isDrawing) return;
  
  ctx.lineWidth = 5;
  ctx.lineCap = 'round';
  ctx.strokeStyle = '#000';
  
  ctx.lineTo(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop);
  ctx.stroke();
  ctx.beginPath();
  ctx.moveTo(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop);
}

function stopDrawing() {
  isDrawing = false;
  ctx.beginPath();
}

Compatibility and Limitations

Although modern browsers support <canvas>, note the following:

  1. Older versions of IE (8 and below) do not support it.
  2. Canvas content is not part of the DOM and cannot be accessed via CSS selectors.
  3. Performance issues may arise when drawing a large number of objects.
  4. Blurring may occur on high-DPI devices and requires special handling:
// Handling high-DPI devices
const dpr = window.devicePixelRatio || 1;
canvas.style.width = canvas.width + 'px';
canvas.style.height = canvas.height + 'px';
canvas.width = canvas.width * dpr;
canvas.height = canvas.height * dpr;
ctx.scale(dpr, dpr);

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

上一篇:<svg>-SVG矢量图形

下一篇:<map>-图像映射

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.