最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

js使用canvas實(shí)現(xiàn)繪制月餅

 更新時(shí)間:2023年09月18日 16:06:51   作者:Defineee  
皓月當(dāng)空,月圓中秋,在這個(gè)傳統(tǒng)節(jié)日里,除了賞月、猜燈謎、賞花燈等習(xí)俗外,還有就是品嘗美味的月餅,本文就來使用canvas繪制一個(gè)精美的月餅吧

皓月當(dāng)空,月圓中秋,在這個(gè)傳統(tǒng)節(jié)日里,除了賞月、猜燈謎、賞花燈等習(xí)俗外,還有就是品嘗美味的月餅。關(guān)于月餅,大家一定都知道月餅上會(huì)印著一個(gè)精美的圖案與紋路。

效果圖

HTML

這個(gè) HTML 片段的主要組成部分包括一個(gè)canvas畫布、一個(gè)背景圖片、文字以及一組按鈕功能。 關(guān)于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)">對(duì)稱</div>
        <div class="reset" onclick="reset()">清空畫布</div>
      </div>
    </div>

初步繪制

我們來看一下繪制的邏輯,首先通過了事件監(jiān)聽器綁定了pointerdown、pointermove、pointerup。

pointerdown:當(dāng)用戶按下鼠標(biāo)左鍵或觸摸屏幕時(shí),isDrawing 的變量設(shè)置為 true,表示用戶開啟繪制。

pointermove:當(dāng)用戶在Canvas上移動(dòng)鼠標(biāo)或手指時(shí),首先判斷isDrawing的值,確定用戶是否開啟繪制,如果為開啟繪制,則獲取鼠標(biāo)或觸摸事件的坐標(biāo)信息(e.clientXe.clientY)并根據(jù)Canvas的相對(duì)位置(使用 getBoundingClientRect() 方法計(jì)算)將坐標(biāo)信息轉(zhuǎn)換為Canvas內(nèi)部的坐標(biāo)(以左上角為原點(diǎn))。將其賦值給 point對(duì)象(point對(duì)象中的表示一條線段的起點(diǎn)與終點(diǎn)),調(diào)用draw函數(shù)繪制線條。

pointerup:用戶釋放鼠標(biāo)左鍵或手指時(shí)觸發(fā)將 isDrawing 變量設(shè)置為 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

一般來講在電腦上我們都會(huì)使用MouseEvent,但是如果想要在手機(jī)上也能進(jìn)行繪制,就需要使用PointerEventTouchEvent。

PointerEvent是一個(gè)通用的事件類型,用于處理多種輸入設(shè)備(包括鼠標(biāo)、觸摸屏、觸控筆等)的輸入事件。TouchEvent用于處理觸摸屏輸入事件,如觸摸、滑動(dòng)等。所有在這里我們使用了PointerEvent,因?yàn)樗泳邆渫ㄓ眯浴?/p>

不過在實(shí)際開發(fā)中,pointermove事件出現(xiàn)繪制中斷的情況,于是只能再添加一個(gè)touchmove監(jiān)聽器。 需要注意的是TouchEvent獲取坐標(biāo)的方式與PointerEvent略有不同。

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

getBoundingClientRect()

在獲取坐標(biāo)時(shí),我們還做了一個(gè)操作,減去getBoundingClientRect()的top和left。

getBoundingClientRect返回值是一個(gè) DOMRect 對(duì)象,這個(gè)對(duì)象是由該元素的 getClientRects() 方法返回的一組矩形的集合,就是該元素的 CSS 邊框大小。返回的結(jié)果是包含完整元素的最小矩形,并且擁有 left, top, right, bottom, x, y, width, 和 height 這幾個(gè)以像素為單位的只讀屬性用于描述整個(gè)邊框。除了 width 和 height 以外的屬性是相對(duì)于視圖窗口的左上角來計(jì)算的。

這步其實(shí)可有可無,是因?yàn)樵谝婚_始還沒寫css時(shí)發(fā)現(xiàn)的一個(gè)沒寫* {margin: 0;padding: 0;}導(dǎo)致的問題。直接來看一下區(qū)別,一開始寫了css還可能發(fā)現(xiàn)不了。

繪制函數(shù)

接下來是繪制的函數(shù),傳入了canvas對(duì)象、畫筆顏色和線條寬度,再通過point中線段的起點(diǎn)與終點(diǎn)進(jìn)行繪制。

  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();
  }

對(duì)稱繪制

上一步簡(jiǎn)單了實(shí)現(xiàn)了繪制功能,已經(jīng)可以繪制月餅的圖案,不過有的月餅上都是一些對(duì)稱的的圖案,簡(jiǎn)單的靠一支畫筆完全不可能畫出對(duì)稱的效果。所以還需要一個(gè)能繪制對(duì)稱圖案的功能。 大致的方案是通過rotate進(jìn)行旋轉(zhuǎn),為了保證畫筆的點(diǎn)位正常,需要使用translate將坐標(biāo)原點(diǎn)移動(dòng)到 Canvas 的中心位置,對(duì)point坐標(biāo)都要進(jìn)行偏移操作。

  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();
    }
  }

結(jié)語

至此,繪制的相關(guān)功能寫完了,還有一個(gè)額外的操作是,對(duì)于圖案線條添加了邊框,本意是想增加線條的立體感,但是寫完發(fā)現(xiàn)一點(diǎn)也感覺不到。由于在繪制過程中線條交叉會(huì)導(dǎo)致邊框覆蓋之前線條的情況,于是使用了一個(gè)簡(jiǎn)單粗暴的方案,在這個(gè)canvas中下面在添加一個(gè)canvas進(jìn)行同步繪制單獨(dú)的邊框效果。

到此這篇關(guān)于js使用canvas實(shí)現(xiàn)繪制月餅的文章就介紹到這了,更多相關(guān)js canvas繪制月餅內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解JSON.stringify()的5個(gè)秘密特性

    詳解JSON.stringify()的5個(gè)秘密特性

    這篇文章主要介紹了詳解JSON.stringify()的5個(gè)秘密特性,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • JS代碼實(shí)現(xiàn)table數(shù)據(jù)分頁效果

    JS代碼實(shí)現(xiàn)table數(shù)據(jù)分頁效果

    這篇文章主要介紹了JS代碼實(shí)現(xiàn)table數(shù)據(jù)分頁效果的相關(guān)資料,非常不錯(cuò),代碼簡(jiǎn)答易懂,非常實(shí)用,需要的朋友可以參考下
    2016-05-05
  • Bootstrap CSS組件之導(dǎo)航條(navbar)

    Bootstrap CSS組件之導(dǎo)航條(navbar)

    這篇文章主要為大家詳細(xì)介紹了Bootstrap CSS組件之導(dǎo)航條(navbar),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • 其實(shí)你可以少寫點(diǎn)if else與switch(推薦)

    其實(shí)你可以少寫點(diǎn)if else與switch(推薦)

    switch case與if else的區(qū)別:switch case會(huì)生成一個(gè)跳轉(zhuǎn)表來指示實(shí)際的case分支的地址,而if...else卻需要遍歷條件分支直到命中條件,下面這篇文章主要給大家介紹了關(guān)于if else與switch在使用中的一些技巧,需要的朋友可以參考下
    2019-01-01
  • 原生js圖片輪播效果實(shí)現(xiàn)代碼

    原生js圖片輪播效果實(shí)現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了基于原生js實(shí)現(xiàn)圖片輪播效果的具體代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • 溫習(xí)Javascript基礎(chǔ)語法之詞法結(jié)構(gòu)

    溫習(xí)Javascript基礎(chǔ)語法之詞法結(jié)構(gòu)

    javascript是一門簡(jiǎn)單的語言,也是一門復(fù)雜的語言。這篇文章主要介紹了溫習(xí)Javascript基礎(chǔ)語法之詞法結(jié)構(gòu)的相關(guān)資料,需要的朋友可以參考下
    2016-05-05
  • bootstrap3 dialog 更強(qiáng)大、更靈活的模態(tài)框

    bootstrap3 dialog 更強(qiáng)大、更靈活的模態(tài)框

    這篇文章主要介紹了bootstrap3 dialog 更強(qiáng)大、更靈活的模態(tài)框,本文通過效果展示實(shí)例代碼詳解,需要的朋友可以參考下
    2017-04-04
  • 原生JS下拉加載插件分享

    原生JS下拉加載插件分享

    本文主要分享了原生JS下拉加載插件的實(shí)現(xiàn)代碼。具有一定的參考價(jià)值,需要的朋友一起來看下吧
    2016-12-12
  • JavaScript獲取圖片像素顏色并轉(zhuǎn)換為box-shadow顯示

    JavaScript獲取圖片像素顏色并轉(zhuǎn)換為box-shadow顯示

    這篇文章主要介紹了JavaScript獲取圖片像素顏色并轉(zhuǎn)換為box-shadow顯示的方法,用到了HTML5中的FileReader API和getImageData,轉(zhuǎn)換為的CSS3 box-shadow也要注意瀏覽器的兼容問題,需要的朋友可以參考下
    2016-03-03
  • JS簡(jiǎn)單生成隨機(jī)數(shù)(隨機(jī)密碼)的方法

    JS簡(jiǎn)單生成隨機(jī)數(shù)(隨機(jī)密碼)的方法

    這篇文章主要介紹了JS簡(jiǎn)單生成隨機(jī)數(shù)(隨機(jī)密碼)的方法,簡(jiǎn)單分析了javascript隨機(jī)數(shù)相關(guān)函數(shù)并結(jié)合具體實(shí)例形式分析了隨機(jī)數(shù)的相關(guān)生成技巧,需要的朋友可以參考下
    2017-05-05

最新評(píng)論

汽车| 浠水县| 和龙市| 平阳县| 安吉县| 阳高县| 台南县| 赣州市| 阿勒泰市| 灵川县| 法库县| 荔浦县| 水城县| 陆良县| 康定县| 水富县| 新民市| 公主岭市| 大庆市| 京山县| 望谟县| 弥勒县| 临颍县| 玉山县| 临澧县| 罗江县| 健康| 新昌县| 无为县| 柏乡县| 额敏县| 富顺县| 铜陵市| 从江县| 托克托县| 故城县| 永泰县| 陆川县| 泰兴市| 射洪县| 独山县|