如何在 HTML5 画布上绘图

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在 HTML5 画布上绘图相关的知识,希望对你有一定的参考价值。

步骤 1: 在 html 中设置画布,创建一个引用,并获取上下文对象

画布在 HTML 中通过 <canvas> 标签定义。与其他标签类似,<canvas> 的属性(如宽度和高度)作为特性输入。假设你希望创建一个宽 500 像素、高 500 像素的画布,并将其命名为“can1”,稍后在 javascript 中引用它时将用到。

在 HTML 文档中输入 <canvas> 标签。

<canvas id="can1" width="500" height="500"></canvas>

在 JavaScript 文档中,创建一个变量,在编写脚本时该变量将代替“can1”。这里,我们将该变量命名为“myCanvas”,并使用 getElementById 将其链接到“can1”。

var myCanvas = document.getElementById("can1");

画布的 CanvasRenderingContext2D 对象具有操作画布的所有命令。 这里,在上下文对象中检索“can1”。将此变量称为“myContext”。

var myContext = myCanvas.getContext("2d");

步骤 2: 绘制矩形、直线、贝塞尔曲线、圆和形状

在画布上绘制简单的线条非常容易。使用 JavaScript 的 moveTo 方法可设置线条开始位置的坐标。然后只需使用另一方法设置终点。 第二步可以使用若干方法,每种方法专用于帮助呈现一种不同的线型,无论是直线、贝塞尔曲线还是圆弧。若要将线条合并为形状,可以闭合对 beginPath 和 closePath 方法调用中的线条。在指定所需的外观之后,可以使用 fill 方法应用颜色,并使用 stroke 方法执行线条和形状的呈现。

应用一些基本风格。这里,通过使用 fillStyle 属性绘制一个黑色矩形,将画布背景设置为黑色 (#000)。然后使用 strokeStyle 属性将线条颜色设置为白色 (#fff),使用 fillRect 方法应用黑色背景,并使用 lineWidth 属性将线条的粗细设置为 3 个像素。


// Specify a black background, and white lines that are 3 pixels thick.
myContext.fillStyle   = '#000';
myContext.strokeStyle = '#fff';
myContext.fillRect(0,0,500,500);
myContext.lineWidth  = 3;myContext.fill();

在后续步骤中,将在这个 500×500 的黑色画布上继续构建。

现在,准备在画布的黑色表面绘制一个白色线条。先从直线开始。

使用 moveTo 方法设置直线的起点,使用 lineTo 方法设置终点。

这些方法采用两个数字作为参数。第一个数字表示 x 轴坐标,或者表示此坐标定义的自画布左侧算起的像素数。第二个数字是从顶部开始测量的 y 轴坐标。


// Draw a line that starts at the upper left corner of the canvas and ends at the lower right. 
myContext.moveTo(0,0);
myContext.lineTo(500,500);
myContext.stroke();

若要绘制二次贝塞尔曲线,请使用 quadraticCurveTo 方法,该方法采用两个坐标—曲线的一个控制点和一个端点。

// Draw a swooping curve that spans the width of the canvas.
myContext.moveTo(0,0);
myContext.quadraticCurveTo(0,500,500,250);
myContext.stroke();

若要绘制三次贝塞尔曲线,请使用 bezierCurveTo 方法,该方法采用三个坐标—曲线的两个控制点和一个端点。

// Draw a V-shaped Bezier curve that spans the entire canvas.
myContext.moveTo(0,0);
myContext.bezierCurveTo(500, 820, 0, 500, 500, 0);
myContext.stroke();

若要创建一个圆,请使用 arc 方法:在设置用于绘制圆形轮廓的原点时,请确保将 moveTo 方法设置在沿线条路径的位置上,否则圆上将有一条通向 moveTo坐标的“尾巴”。

// Draw a circle that spans the width of the canvas.
myContext.moveTo(500,250);
myContext.arc(250,250,250,0,Math.PI*2,true);
myContext.stroke();

通过闭合对 beginPath 和 closePath 调用中的多个线条,可以从上述线条的任意组合中绘制一个 2D 形状。然后,整个形状可以使用 fill 接收一种颜色。前面设置的笔划样式将创建白色线条,在与应用于主体的红色 (#f00) 合并时,该形状将继承双色调外观。

//  Draw a red diamond that spans the entire canvas.
myContext.fillStyle = '#f00';
myContext.beginPath();
myContext.moveTo(250,0);
myContext.lineTo(0,250);
myContext.lineTo(250,500);
myContext.lineTo(500,250);
myContext.closePath();
myContext.fill();


步骤 3: 显示位图图像

位图图像(如 .jpg、.png 和 .gif 文件)可以放置在画布上,甚至可以在代码中缩放和裁剪,不会触及原始文件。若要添加位图图像,请指定该图像的 URI,然后使用 drawImage 方法在画布上指定其位置。使用可选参数可将图像缩放到指定的大小,甚至仅显示图像的一个片段,这对于实现滚动背景或使用子画面表动态显示子画面等操作非常有用。

若要在屏幕上绘制位图图像而不进行任何修改,请指定要用于左上角的 x 坐标和 y 坐标。

// Draw an image at the upper left corner of the canvas (0, 0).
var myImg = new Image();
myImg.src = 'myImageFile.png';
myContext.drawImage(myImg, 0, 0)

若要缩放图像,可在末尾添加两个数字,分别代表宽度和高度。如果有帮助,不妨将后两个数字视为“右部”和“底部”,而不是“宽度”和“高度”。

// Scale the image to span the entire 500 x 500 canvas.
var myImg = new Image();
myImg.src = 'myImageFile.png';
myContext.drawImage(myImg, 0, 0, 500, 500)

若要仅使用图像的一个切片,则需要定义两个矩形区域,对 drawImage 的调用提高到 9 个参数(第一个参数是 JavaScript 图像对象)。要传入的前四个数字表示图像的切片。后四个数字表示要显示该切片的画布区域。

// Take a 20 x 20 slice from the upper left of the image and scale it to span the entire 500 x 500 canvas.
var myImg = new Image();
myImg.src = 'myImageFile.png';
myContext.drawImage(myImg, 0, 0, 20, 20, 0, 0, 500, 500);


步骤 4: 渐变

任何人只要熟悉在图形设计程序中定义渐变的常见方式,都会喜欢使用 JavaScript 代码定义渐变的简单性。在设计程序中是选择颜色,渐变中的颜色位置使用水平滑块设置。JavaScript 中的唯一区别是使用从 0 到 1 范围内的小数值代替滑块。

在设计程序中,线性渐变使用线条在图像上定位,线条的开始和结束位置确定方向和缩放级别。在 JavaScript 中,该线条使用两对 x、y 轴坐标绘制。然后将 4 个数字传递到 createLinearGradient 方法以创建 CanvasGradient 对象。在定义渐变对象的属性之后,就会得到所需的渐变,CanvasGradient 作为 fillStyle 传递到 fillRect 方法进行呈现。

// Render a white, red and black gradient diagonally across the canvas.
var myGradient = myContext.createLinearGradient(0,0, 500,500); // gradient starts at upper left and ends at lower right
myGradient.addColorStop(0,"#fff");   // white at the beginning of the gradient
myGradient.addColorStop(0.5,"#f00");// red in the middle of the gradient
myGradient.addColorStop(1,"#000");  // black at the end of the gradient
myContext.fillStyle = myGradient;   // ensure the next call to fillRect will use the specified gradient
myContext.fillRect(0,0,500,500);   // rectangle that contains the gradient spans the entire canvas

径向渐变的定义方式稍有不同。为渐变的起点和终点绘制两对 x、y 轴坐标—,这与线性渐变中一样—,但每个坐标对都有第三个与其关联的 z 轴坐标,用于定义半径。可以想像为围绕一个坐标绘制一个圆,该坐标位于中心 (250, 250),绘制的圆的大小以像素为单位定义。这样定义两个圆之后,一个圆较小,一个圆跨整个画布,有 6 个数字传递到 createRadialGradient。在呈现时,径向渐变在两个圆之间的空间中绘制,颜色等级与圆的半径的大小成正比。

// Render a white, red and black radial gradient spanning the canvas.
var myGradient = myContext.createRadialGradient(250,250,0, 250,250,500); // gradient is centered and spans the entire canvas 
myGradient.addColorStop(0,"#fff");   // white at the beginning of the gradient
myGradient.addColorStop(0.5,"#f00");  // red in the middle of the gradient
myGradient.addColorStop(1,"#000");   // black at the end of the gradient
myContext.fillStyle = myGradient;    // ensure the next call to fillRect will use the specified gradient
myContext.fillRect(0,0,500,500);    // rectangle that contains the gradient spans the entire canvas

步骤 5: 动画

可以使用多种方法绘制动画。

对于画布内的元素,JavaScript 提供了 setInterval 方法,该方法计划一个重复调用的函数,每经过定义的时间间隔便调用一次该函数。在该函数中,需要重绘画布来反映对其上呈现的对象的更改。下面是一个示例,其中一个函数初始化该动画,将呈现频率计划为大约每秒 60 帧(每 13.33 毫秒一帧),并且重复调用该函数将重绘画布。在本例中,径向渐变从一个小点逐渐增大,直到填充整个画布。

// Generate an animation of a growing gradient.
// These variables must exist globally so both functions can access them.
var myCanvas; 
var myContext;
var outerBoundary = 0, innerBoundary = 0;
// Start the animation.
window.onload = initialize;
function initialize() 
    myCanvas = document.getElementById("can1");
    myContext = myCanvas.getContext("2d");
    setInterval("redrawCanvas()",13);    // redraw @ approximately 60 frames per second
                                        
                                         
// Run the animation.                   
function redrawCanvas()               
    if (outerBoundary < 500)             
        outerBoundary++;             // grow the size of the gradient
     else                              
        innerBoundary++;             // grow the size of the inner white circle if red is maxed
                                        
    var myGradient = myContext.createRadialGradient(250,250,innerBoundary, 250,250,outerBoundary);
    myGradient.addColorStop(0,"#fff");   // white at the beginning of the gradient
    myGradient.addColorStop(0.5,"#f00"); // red in the middle of the gradient
    myGradient.addColorStop(1,"#000");   // black at the end of the gradient
    myContext.fillStyle = myGradient;    // ensure the next call to fillRect will use the specified gradient
    myContext.fillRect(0,0,500,500);     // rectangle that contains the gradient spans the entire canvas

CSS3 转换和动画可用于转换画布本身和画布外部的对象。

此外,新的 WinJS 库有许多高度优化的动画,创建这些动画是为了模拟原有 Windows 动画的行为。 WinJS 动画有助于为你的应用 UI 提供一个高度集成的外观。有关详细信息,请参阅WinJS.UI.Animation 命名空间。


步骤 6: 更多 HTML5 画布提示

可以使用一系列属性(shadowColor、shadowBlur、shadowOffsetX 和 shadowOffsetY)应用阴影。

可以使用 createPattern 方法作为一种模式重复画布中的元素。

可以使用 save 方法保存画布状态,然后执行更改,再使用 restore 方法还原以前的状态。该方法很好用,函数甚至不需要采用参数。

可以使用 globalCompositeOperation 属性定义两个画布元素重叠时会发生什么情况。 使用此属性始终可以定义在源或新元素级别发生的情况。可以执行的操作有颜色混合、遮蔽和更改重叠优先级等。

注意  globalCompositeOperation 主题使用源表示新元素,使用目标表示以前存在的元素。

可以使用 strokeText 方法将文本添加到画布。

参考技术A

1. 在 HTML 文档中输入 <canvas> 标签。

<canvas id="can1" width="500" height="500"></canvas>

2. 在 JavaScript 文档中,创建一个变量,在编写脚本时该变量将代替“can1”。这里,我们将该变量命名为“myCanvas”,并使用 getElementById 将其链接到“can1”。

var myCanvas = document.getElementById("can1");

3. 画布的 CanvasRenderingContext2D 对象具有操作画布的所有命令。 这里,我们在上下文对象中检索“can1”。我们将此变量称为“myContext”。

var myContext = myCanvas.getContext("2d");

// Specify a black background, and white lines that are 3 pixels thick.
myContext.fillStyle   = '#000';
myContext.strokeStyle = '#fff';
myContext.fillRect(0,0,500,500);
myContext.lineWidth  = 3;
myContext.fill();

//这里,我们通过使用 fillStyle 属性绘制一个黑色矩形,将画布背景设置为黑色 (#000)。然后使用 strokeStyle 属性将线条颜色设置为白色 (#fff),使用 fillRect 方法应用黑色背景,并使用lineWidth 属性将线条的粗细设置为 3 个像素。

具体的可查看:https://msdn.microsoft.com/zh-cn/library/windows/apps/hh452750.aspx

本回答被提问者和网友采纳
参考技术B 首先你要知道canvas 这个标签。 你可以 搜索w3cschool 知道canvas这个标签去看下。看案列它是怎么实现的。其实很简单,具体简单参考https://msdn.microsoft.com/zh-cn/subscriptions/hh452750.aspx 参考技术C 内容很长,附上MDN的Canvas教程:
https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial

HTML5 画布在缩小 Chrome 中的绘图时显示为别名

【中文标题】HTML5 画布在缩小 Chrome 中的绘图时显示为别名【英文标题】:HTML5 canvas is showing as aliased on downscaling a drawing in Chrome 【发布时间】:2021-02-28 18:16:30 【问题描述】:

要求: 所以我使用 html5 画布在 iPad(2732 * 2048) 上执行绘图并存储绘制的像素以便我可以重复使用它们。

现在我需要在网站上显示与缩小版本 (615 * 460) 相同的绘图,方法是按像素重绘。

实施

我正在使用 fabric.js 来渲染画布。

要缩小:

    将画布的高度和宽度乘以调整大小比例,以便将绘图缩放到原始大小。 强制将容器的高度和宽度固定为显示绘图所需的尺寸。 使用 CSS 将容器填充到其尺寸的 100%。

问题 在 Chrome 中渲染时,绘图会出现别名,但它在非视网膜显示器上的 Safari 中正确渲染。

也用纯画布测试过,行为相同。

在 Chrome 85 上绘图

在 Safari 14 上绘图

伪代码:(仅显示所需的设置和样式以避免复杂化)

// resizeRatio = 4.45 (2732 / 615);

   canvas = new fabric.Canvas('someId');
   canvas.enableRetinaScaling = false;
   canvas.freeDrawingBrush.color = '#000000';
   
   canvas.setWidth(460 * resizeRatio);
   canvas.setHeight(615 * resizeRatio);
   
   container = document.getElementbyId('container');

   container.style.width = (this.width) + 'px';
   container.style.height = (this.height) + 'px';
   
   brush = new fabric.PencilBrush(canvas);

   brush.width = 2.5;

  // Loop over each of the coordinates using mouse events on the brush to render the 
  // canvas.

HTML

<div id=container style=" width: 100% !important;height: 100% !important;">
   <canvas style=" width: 100% !important; height: 100% !important;" id="canvas"></canvas>. 
</div>

谢谢

【问题讨论】:

您是否尝试将画笔宽度设置为四舍五入的数字(例如 2 或 3)? 您好,感谢您的回复。我试过了,没有任何区别。 【参考方案1】:

您无需调整canvas.widthcanvas.height 的大小,因为它们与canvas.style.heightcanvas.style.width 不同。为了保持清晰,您不应降低画布的分辨率。

示例用例是我使用 4k 显示器,我可以使用 window.devicePixelRatio 知道设备与像素的比率为 2。然后我在画布上重新绘制我想画的东西,在这里我将大小乘以这个比率。 canvas.width += canvas.width * deviceToPixelRatio,这使得图像清晰且易于放大。

【讨论】:

以上是关于如何在 HTML5 画布上绘图的主要内容,如果未能解决你的问题,请参考以下文章

可拖动图像上的画布绘图

如何优化画布上的动画? HTML 5

如何撤消 HTML5 Canvas 绘图应用程序的橡皮擦操作

用于游戏的 HTML 5 在画布上高效绘图

如何在移动设备的画布上绘图?

Javascript 如何在移动设备上画布绘图工作