在网页中实现画图和画图点击事件

在网页网站日常开发中,我们通常用会用到图片展示、图片切片技术等手段来实现网页中图片的应用。

这可能是大多数人会想到的办法,那么还有其他的方式么?

这里来介绍一种新的实现方式,它的名字叫“Canvas”。

Canvas是一个HTML5元素,用于在网页上绘制图形、动画和其他可视化内容。它提供了一个JavaScript API,可以通过编程方式在Canvas上绘制各种图形,包括线条、矩形、圆形、文本等。Canvas非常灵活,可以用于创建各种交互式图表、游戏和图像处理应用程序等。您可以使用Canvas来实现各种创意和实用的功能,如绘制动态图形、处理用户输入、创建图表和数据可视化等。

优点:通过canvas展示图片或者图片可以节省大量网络流量

缺点:入门简单,但是对画图要有深刻理解,才能画出好图形

下面我来实现两个案例:

第一个就是实现画圆、画线、点击事件、放大缩小。具体实现效果如下:

画圆:

核心函数:arc

它有6个参数:

1.x 圆的中心的 x 坐标。
2.y 圆的中心的 y 坐标。
3.r 圆的半径。
4.sAngle 起始角,以弧度计(弧的圆形的三点钟位置是 0 度)。
5.eAngle 结束角,以弧度计。
6.counterclockwise 可选。规定应该逆时针还是顺时针绘图。False = 顺时针,true = 逆时针。

从中可以看的出来,它以x,y坐标为中心,r为半径向四周360度展开画图,类似于我们使用圆规的动作。

画线:

核心函数:moveTo,lineTo

它们两个都需要两个参数,分别都是x,y坐标值

moveTo作用就是把我们的画笔移动到x,y坐标,左上角0,0为起始位置。

lineTo作用就是画线,把从当前画笔位置移动我们画线的位置,中间形成的轨迹就是一条线。

点击事件

点击事件这里主要实现是通过监听canvas的画布的点击事件,判断当前点击位置是否处于所画的位置范围内。

放大缩小

核心函数:scale

scale函数使用来调整图形的放大和缩小

它有两个参数,分别是x:横轴和y:纵轴的缩放因子。x,y两个参数默认1,如果要放大就在x,y两个参数各自加+0.1,这样就实现了放大原来图形的十分之一。

下面我们来一份综合的实现案例:

<!DOCTYPE html>
<html lang="zh">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Canvas点击</title>
</head>

<body>

  <div>
    <button id="test">放大</button>
    <button id="test2">缩小</button>
  </div>
  <canvas id="myCanvas" width="800" height="600" style="border:1px solid #000000;margin-top:10px"></canvas>


  <script>
    const canvas = document.getElementById('myCanvas');
    const test = document.getElementById('test');
    const test2 = document.getElementById('test2');
    const ctx = canvas.getContext('2d');




    // 绘制圆形
    function drawCircle(x, y, radius, color) {
      ctx.beginPath();
      ctx.arc(x, y, radius, 0, Math.PI * 2);
      ctx.fillStyle = color;//设置填充颜色
      ctx.fill();//开始填充
      ctx.stroke();
    }

    // 绘制线
    function drawLine(startX, startY, endX, endY, color) {
      ctx.beginPath();
      ctx.moveTo(startX, startY);
      ctx.lineTo(endX, endY);
      if (color) {
        color = color
      } else {
        ctx.strokeStyle = 'blue';
      }
      ctx.stroke();
    }


    // 检查点击位置是否在矩形内的函数
    function isInsideRect(x, y, rect) {
      return x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y + rect.height;
    }

    // 添加放大缩小画布的方法
    var zoom = 1;
    function zoomBox() {
      ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除画布
      ctx.save(); // 保存当前状态
      ctx.scale(zoom, zoom); // 缩放
      draw()
      ctx.restore(); // 恢复状态
    }
    
    function draw(params) {

      drawCircle(100, 100, 10, 'green');
      drawLine(110, 100, 200, 100)
      
      drawCircle(210, 100, 10, 'green');
      drawLine(210, 110, 210, 200)

      drawCircle(210, 210, 10, 'green');
      drawLine(220, 210, 300, 210)

      drawCircle(310, 210, 10, 'green');
    }

    // 添加点击事件处理程序
    canvas.addEventListener('click', function (event) {
      const x = event.clientX - canvas.offsetLeft;
      const y = event.clientY - canvas.offsetTop;
      console.info("x", x, "y", y)
      if (isInsideRect(x, y, { x: 90 * zoom, y: 90 * zoom, width: 20 * zoom, height: 20 * zoom })) {

        alert("点击了第1个圆")
      }
      if (isInsideRect(x, y, { x: 110 * zoom, y: 100 * zoom, width: 100 * zoom, height: 5 * zoom })) {

        alert("点击了第1个线")
      }
      if (isInsideRect(x, y, { x: 200 * zoom, y: 90 * zoom, width: 20 * zoom, height: 20 * zoom })) {

        alert("点击了第2个圆")
      }
      if (isInsideRect(x, y, { x: 210 * zoom, y: 110 * zoom, width: 5 * zoom, height: 90 * zoom })) {

        alert("点击了第2个线")
      }
      if (isInsideRect(x, y, { x: 200 * zoom, y: 200 * zoom, width: 20 * zoom, height: 20 * zoom })) {

        alert("点击了第3个圆")
      }
      if (isInsideRect(x, y, { x: 220 * zoom, y: 210 * zoom, width: 85 * zoom, height: 5 * zoom })) {

        alert("点击了第3个线")
      }
      if (isInsideRect(x, y, { x: 300 * zoom, y: 200 * zoom, width: 20 * zoom, height: 20 * zoom })) {

        alert("点击了第4个圆")
      }
    });

    test.addEventListener('click', function (event) {
      zoom += 0.1
      zoomBox()
    });

    test2.addEventListener('click', function (event) {
      zoom -= 0.1
      zoomBox()
    });

    draw()
  </script>
</body>

</html>

通过了解原理我们可以实现画出各种各样的图形甚至图像的实现。

画一个笑脸

<!DOCTYPE html>
<html lang="zh">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Canvas笑脸</title>
</head>

<body>
  <canvas id="smileyCanvas" width="400" height="400"></canvas>
  <script>
    var canvas = document.getElementById('smileyCanvas');
    if (canvas.getContext) {
      var ctx = canvas.getContext('2d');

      // 绘制脸部
      ctx.beginPath();
      ctx.arc(200, 200, 150, 0, Math.PI * 2, true); // 圆形脸
      ctx.fillStyle = 'yellow';
      ctx.fill();
      ctx.stroke();

      // 绘制左眼
      ctx.beginPath();
      ctx.arc(150, 150, 20, 0, Math.PI * 2, true); // 左眼
      ctx.fillStyle = 'black';
      ctx.fill();

      // 绘制右眼
      ctx.beginPath();
      ctx.arc(250, 150, 20, 0, Math.PI * 2, true); // 右眼
      ctx.fillStyle = 'black';
      ctx.fill();

      // 绘制微笑
      ctx.beginPath();
      ctx.arc(200, 220, 80, 0, Math.PI, false); // 半圆形微笑
      ctx.stroke();
    }


  </script>
</body>

</html>

超萌小黑猫

<!DOCTYPE html>
<html lang="zh">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>猫猫</title>
</head>

<body>
  <canvas id="myCanvas" width="610" height="430"></canvas>
  <script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');


    // 绘制身体
    // 左侧身体
    ctx.beginPath();
    // 手臂外侧
    // 开始点
    ctx.moveTo(275, 260);
    // 控制点230,315  结束点 255,325
    ctx.quadraticCurveTo(230, 315, 255, 325);
    ctx.lineTo(270, 320);

    // 手臂内侧
    ctx.quadraticCurveTo(260, 310, 270, 280);

    // 胳子窝
    ctx.quadraticCurveTo(272, 275, 274, 280);

    // 身体外侧
    ctx.quadraticCurveTo(263, 300, 276, 330);

    // 左腿外侧
    ctx.lineTo(274, 355);

    // 左脚
    ctx.quadraticCurveTo(258, 370, 290, 372);
    ctx.quadraticCurveTo(320, 375, 310, 348);

    // 裆部
    ctx.quadraticCurveTo(308, 338, 314, 346);

    // 右侧身体
    // 右脚
    ctx.quadraticCurveTo(320, 362, 315, 364);
    ctx.quadraticCurveTo(310, 372, 335, 373);
    ctx.quadraticCurveTo(365, 370, 350, 350);

    // 右脚尾巴连接处
    ctx.lineTo(351, 335);

    // 尾巴
    ctx.quadraticCurveTo(390, 365, 420, 300);
    ctx.quadraticCurveTo(430, 280, 400, 308);
    ctx.quadraticCurveTo(385, 350, 352, 328);

    // 身体外侧
    ctx.quadraticCurveTo(365, 315, 354, 280);
    // 胳子窝
    ctx.quadraticCurveTo(352, 275, 358, 280);
    // 手臂内侧
    ctx.quadraticCurveTo(370, 305, 358, 325);
    // 手臂外侧
    ctx.quadraticCurveTo(370, 335, 382, 318);
    ctx.quadraticCurveTo(390, 300, 342, 250);

    ctx.closePath();
    ctx.fillStyle = '#000';
    ctx.fill();




    // 脖子
    ctx.beginPath();
    ctx.ellipse(309, 253, 42, 25, 0, Math.PI * 0.9, Math.PI * 0.02, true);
    ctx.fillStyle = '#87e5f1';
    ctx.fill();


    // 耳朵
    // 绘制左耳
    ctx.beginPath();
    ctx.moveTo(235, 175);
    ctx.quadraticCurveTo(185, 75, 272, 140);
    ctx.closePath();
    ctx.fillStyle = '#000';
    ctx.fill();
    // 左耳内
    ctx.beginPath();
    ctx.moveTo(237, 160);
    ctx.quadraticCurveTo(207, 105, 255, 138);
    ctx.closePath();
    ctx.fillStyle = '#faf0bf';
    ctx.fill();

    // 绘制右耳
    ctx.beginPath();
    ctx.moveTo(338, 129);
    ctx.quadraticCurveTo(415, 80, 375, 160);
    ctx.closePath();
    ctx.fillStyle = '#000';
    ctx.fill();
    // 右耳内
    ctx.beginPath();
    ctx.moveTo(343, 134);
    ctx.quadraticCurveTo(400, 100, 370, 158);
    ctx.closePath();
    ctx.fillStyle = '#faf0bf';
    ctx.fill();



    // 胡须
    // 绘制左侧胡须
    ctx.beginPath();
    ctx.moveTo(245, 210);
    ctx.lineTo(190, 212);
    ctx.lineWidth = 5;
    ctx.lineCap = 'round';
    ctx.stroke();

    ctx.beginPath();
    ctx.moveTo(255, 235);
    ctx.lineTo(200, 255);
    ctx.lineWidth = 5;
    ctx.lineCap = 'round';
    ctx.stroke();

    // 绘制右侧胡须
    ctx.beginPath();
    ctx.moveTo(385, 210);
    ctx.lineTo(420, 212);
    ctx.lineWidth = 5;
    ctx.lineCap = 'round';
    ctx.stroke();

    ctx.beginPath();
    ctx.moveTo(375, 235);
    ctx.lineTo(405, 250);
    ctx.lineWidth = 5;
    ctx.lineCap = 'round';
    ctx.stroke();


    // 眼睛嘴巴
    // 绘制上半部分脸
    ctx.beginPath();
    ctx.arc(305, 200, 80, Math.PI * 0.9, Math.PI * 0.1);
    ctx.fillStyle = '#000';
    ctx.fill();

    // 绘制下半部分脸
    ctx.beginPath();
    ctx.ellipse(305, 200, 82, 65, 0, Math.PI * 0.9, Math.PI * 0.1, true);
    ctx.fillStyle = '#000';
    ctx.fill();

    // 绘制左眼
    ctx.beginPath();
    ctx.arc(270, 200, 20, 0, Math.PI * 2);
    ctx.fillStyle = '#fff';
    ctx.fill();

    // 绘制左眼眼珠
    ctx.beginPath();
    ctx.arc(275, 200, 7, 0, Math.PI * 2);
    ctx.fillStyle = '#000';
    ctx.fill();

    // 绘制右眼
    ctx.beginPath();
    ctx.arc(340, 200, 20, 0, Math.PI * 2);
    ctx.fillStyle = '#fff';
    ctx.fill();

    // 绘制右眼眼珠
    ctx.beginPath();
    ctx.arc(335, 200, 7, 0, Math.PI * 2);
    ctx.fillStyle = '#000';
    ctx.fill();

    // 绘制嘴巴
    ctx.beginPath();
    ctx.ellipse(307, 223, 10, 7, 0, 0, Math.PI * 2);
    ctx.fillStyle = '#ff6600';
    ctx.fill();
 

  </script>
</body>

</html>

https://juejin.cn/post/7032169398626418718

画flappy bird游戏动画

看到这个我突然觉得Canvas可以画万物了,只要敢想就没有画不出来的。^_^

https://www.cnblogs.com/wuhaozhou/p/5800788.html

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇