js使用canvas实现绘制月饼

 更新时间:2023年09月18日 16:06:51   作者:Defineee  
皓月当空,月圆中秋,在这个传统节日里,除了赏月、猜灯谜、赏花灯等习俗外,还有就是品尝美味的月饼,本文就来使用canvas绘制一个精美的月饼吧

皓月当空,月圆中秋,在这个传统节日里,除了赏月、猜灯谜、赏花灯等习俗外,还有就是品尝美味的月饼。关于月饼,大家一定都知道月饼上会印着一个精美的图案与纹路。

效果图

HTML

这个 HTML 片段的主要组成部分包括一个canvas画布、一个背景图片、文字以及一组按钮功能。 关于css部分过于冗长大家可以直接去码上掘金阅读。

    <div class="banner">
      <canvas id="canvas" width="500" height="500"> </canvas>
      <div class="basebg"> </div>
      <img src="./bg.png" alt="" class="bg">
      <img src="./sc1.png" alt="" class="sc1">
      <div class="text">———— 但愿人长久,千里共婵娟 ————</div>
      <div class="btn">
        <div class="model" onclick="model(1)">单笔</div>
        <div class="model" onclick="model(8)">对称</div>
        <div class="reset" onclick="reset()">清空画布</div>
      </div>
    </div>

初步绘制

我们来看一下绘制的逻辑,首先通过了事件监听器绑定了pointerdown、pointermove、pointerup。

pointerdown:当用户按下鼠标左键或触摸屏幕时,isDrawing 的变量设置为 true,表示用户开启绘制。

pointermove:当用户在Canvas上移动鼠标或手指时,首先判断isDrawing的值,确定用户是否开启绘制,如果为开启绘制,则获取鼠标或触摸事件的坐标信息(e.clientXe.clientY)并根据Canvas的相对位置(使用 getBoundingClientRect() 方法计算)将坐标信息转换为Canvas内部的坐标(以左上角为原点)。将其赋值给 point对象(point对象中的表示一条线段的起点与终点),调用draw函数绘制线条。

pointerup:用户释放鼠标左键或手指时触发将 isDrawing 变量设置为 false,表示用户停止绘制。

  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  const width = canvas.width;
  const height = canvas.height;
  let point = {};
  let lineNum = 8;
  let isDrawing = false;
  canvas.addEventListener('pointerdown', (e) => {
    isDrawing = true;
  });
  canvas.addEventListener('pointermove', (e) => {
    if (!isDrawing) return;
    const x = e.clientX - canvas.getBoundingClientRect().left
    const y = e.clientY - canvas.getBoundingClientRect().top
    point.x1 = x;
    point.y1 = y;
    draw(ctx, "#fdbb07", 5);
    point.x2 = x;
    point.y2 = y;
  });
  canvas.addEventListener('pointerup', (e) => {
    isDrawing = false;
  });

pointerevnet与touchevent

一般来讲在电脑上我们都会使用MouseEvent,但是如果想要在手机上也能进行绘制,就需要使用PointerEventTouchEvent

PointerEvent是一个通用的事件类型,用于处理多种输入设备(包括鼠标、触摸屏、触控笔等)的输入事件。TouchEvent用于处理触摸屏输入事件,如触摸、滑动等。所有在这里我们使用了PointerEvent,因为它更加具备通用性。

不过在实际开发中,pointermove事件出现绘制中断的情况,于是只能再添加一个touchmove监听器。 需要注意的是TouchEvent获取坐标的方式与PointerEvent略有不同。

e.touches[0].clientX
e.touches[0].clientY

getBoundingClientRect()

在获取坐标时,我们还做了一个操作,减去getBoundingClientRect()的top和left。

getBoundingClientRect返回值是一个 DOMRect 对象,这个对象是由该元素的 getClientRects() 方法返回的一组矩形的集合,就是该元素的 CSS 边框大小。返回的结果是包含完整元素的最小矩形,并且拥有 left, top, right, bottom, x, y, width, 和 height 这几个以像素为单位的只读属性用于描述整个边框。除了 width 和 height 以外的属性是相对于视图窗口的左上角来计算的。

这步其实可有可无,是因为在一开始还没写css时发现的一个没写* {margin: 0;padding: 0;}导致的问题。直接来看一下区别,一开始写了css还可能发现不了。

绘制函数

接下来是绘制的函数,传入了canvas对象、画笔颜色和线条宽度,再通过point中线段的起点与终点进行绘制。

  function draw(canvas, color, lineWidth) {
    canvas.strokeStyle = color;
    canvas.lineWidth = lineWidth;
    canvas.lineCap = "round";
    canvas.moveTo(point.x1, point.y1);
    canvas.lineTo(point.x2, point.y2);
    canvas.stroke();
  }

对称绘制

上一步简单了实现了绘制功能,已经可以绘制月饼的图案,不过有的月饼上都是一些对称的的图案,简单的靠一支画笔完全不可能画出对称的效果。所以还需要一个能绘制对称图案的功能。 大致的方案是通过rotate进行旋转,为了保证画笔的点位正常,需要使用translate将坐标原点移动到 Canvas 的中心位置,对point坐标都要进行偏移操作。

  function draw(canvas, color, lineWidth) {
    canvas.strokeStyle = color;
    canvas.lineWidth = lineWidth;
    canvas.lineCap = "round";
    var r = 360 / lineNum * Math.PI / 180;
    for (let i = 0; i < lineNum; i++) {
      canvas.save();
      canvas.translate(width / 2, height / 2);
      canvas.rotate(r * i);
      canvas.beginPath();
      canvas.moveTo(point.x1 - width / 2, point.y1 - height / 2);
      canvas.lineTo(point.x2 - width / 2, point.y2 - height / 2);
      canvas.stroke();
      canvas.restore();
    }
  }

结语

至此,绘制的相关功能写完了,还有一个额外的操作是,对于图案线条添加了边框,本意是想增加线条的立体感,但是写完发现一点也感觉不到。由于在绘制过程中线条交叉会导致边框覆盖之前线条的情况,于是使用了一个简单粗暴的方案,在这个canvas中下面在添加一个canvas进行同步绘制单独的边框效果。

到此这篇关于js使用canvas实现绘制月饼的文章就介绍到这了,更多相关js canvas绘制月饼内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaScript如何获取父级元素和子级元素代码示例

    JavaScript如何获取父级元素和子级元素代码示例

    最近工作中总遇到取各种父啊子啊,每次都得查,所以下面这篇文章主要给大家介绍了关于JavaScript如何获取父级元素和子级元素的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-04-04
  • uniapp使用Vant-weapp的最新方法教程

    uniapp使用Vant-weapp的最新方法教程

    Vant Weapp是有赞前端团队开源的一套小程序UI组件库,助力开发者快速搭建小程序应用,下面这篇文章主要给大家介绍了关于uniapp使用Vant-weapp的最新方法教程,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-04-04
  • 使用20行JS代码实现屏幕录制功能

    使用20行JS代码实现屏幕录制功能

    在开发中可能有遇到过屏幕录制的需求,无论是教学、演示还是游戏录制,都需要通过屏幕录制来记录和分享内容,MediaRecorder 是一种强大的技术,可以在浏览器端实现屏幕录制功能,本文将介绍如何使用JS MediaRecorder 实现屏幕录制,需要的朋友可以参考下
    2023-11-11
  • Bootstrap缩略图与警告框学习使用

    Bootstrap缩略图与警告框学习使用

    这篇文章主要为大家详细介绍了Bootstrap缩略图与警告框学习使用的相关资料,希望通过这篇文章和大家更多的去学习Bootstrap缩略图与警告框,从中得到收获
    2017-02-02
  • 普通web整合quartz跑定时任务的示例

    普通web整合quartz跑定时任务的示例

    这篇文章主要介绍了普通web整合quartz跑定时任务,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-03-03
  • js 计算图片内点个数的示例代码

    js 计算图片内点个数的示例代码

    这篇文章主要介绍了js 计算图片内点个数的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • Javascript设计模式之观察者模式的多个实现版本实例

    Javascript设计模式之观察者模式的多个实现版本实例

    这篇文章主要介绍了Javascript设计模式之观察者模式的多个实现版本实例,本文给出3种实现版本代码,同时给出了Jquery实现版本,需要的朋友可以参考下
    2015-03-03
  • javascript闭包的理解和实例

    javascript闭包的理解和实例

    所谓闭包,值得是词法表示包括不必要计算的变量的函数,也就是说,该函数可以使用函数外定义的变量。
    2010-08-08
  • JS拖拽插件实现步骤

    JS拖拽插件实现步骤

    实现JS拖拽插件主要从六个方面做介绍:一、js拖拽插件的原理,二、根据原理实现的最基本效果,三、代码抽象与优化,四、扩展:有效的拖拽元素,五、性能优化和总结,六、jquery插件化 ,需要的朋友可以参考下
    2015-08-08
  • javascript实现table单元格点击展开隐藏效果(实例代码)

    javascript实现table单元格点击展开隐藏效果(实例代码)

    这篇文章主要介绍了javascript实现table单元格点击展开隐藏效果的实例代码讲解,代码简单易懂,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-04-04

最新评论