亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > HTML > 正文

canvas進階之如何畫出平滑的曲線

2024-08-26 00:21:04
字體:
來源:轉載
供稿:網友

背景概要

相信大家平時在學習canvas 或 項目開發(fā)中使用canvas的時候應該都遇到過這樣的需求:實現(xiàn)一個可以書寫的畫板小工具。

嗯,相信這對canvas使用較熟的童鞋來說僅僅只是幾十行代碼就可以搞掂的事情,以下demo就是一個再也簡單不過的例子了:

<!DOCTYPE html><html><head>    <title>Sketchpad demo</title>    <style type="text/css">        canvas {            border: 1px blue solid;         }    </style></head><body>    <canvas id="canvas" width="800" height="500"></canvas>    <script type="text/javascript">        let isDown = false;        let beginPoint = null;        const canvas = document.querySelector('#canvas');        const ctx = canvas.getContext('2d');        // 設置線條顏色        ctx.strokeStyle = 'red';        ctx.lineWidth = 1;        ctx.lineJoin = 'round';        ctx.lineCap = 'round';        canvas.addEventListener('mousedown', down, false);        canvas.addEventListener('mousemove', move, false);        canvas.addEventListener('mouseup', up, false);        canvas.addEventListener('mouseout', up, false);        function down(evt) {            isDown = true;            beginPoint = getPos(evt);        }        function move(evt) {            if (!isDown) return;            const endPoint = getPos(evt);            drawLine(beginPoint, endPoint);            beginPoint = endPoint;        }        function up(evt) {            if (!isDown) return;                        const endPoint = getPos(evt);            drawLine(beginPoint, endPoint);            beginPoint = null;            isDown = false;        }        function getPos(evt) {            return {                x: evt.clientX,                y: evt.clientY            }        }        function drawLine(beginPoint, endPoint) {            ctx.beginPath();            ctx.moveTo(beginPoint.x, beginPoint.y);            ctx.lineTo(endPoint.x, endPoint.y);            ctx.stroke();            ctx.closePath();        }    </script></body></html>

它的實現(xiàn)邏輯也很簡單:

  • 我們在canvas畫布上主要監(jiān)聽了三個事件:mousedown、mouseupmousemove,同時我們也創(chuàng)建了一個isDown變量;
  • 當用戶按下鼠標(mousedown,即起筆)時將isDown置為true,而放下鼠標(mouseup)的時候將它置為false,這樣做的好處就是可以判斷用戶當前是否處于繪畫狀態(tài);
  • 通過mousemove事件不斷采集鼠標經過的坐標點,當且僅當isDowntrue(即處于書寫狀態(tài))時將當前的點通過canvas的lineTo方法與前面的點進行連接、繪制;

通過以上幾個步驟我們就可以實現(xiàn)基本的畫板功能了,然而事情并沒那么簡單,仔細的童鞋也許會發(fā)現(xiàn)一個很嚴重的問題——通過這種方式畫出來的線條存在鋸齒,不夠平滑,而且你畫得越快,折線感越強。表現(xiàn)如下圖所示:

canvas,曲線

為什么會這樣呢?

問題分析

出現(xiàn)該現(xiàn)象的原因主要是:

我們是以canvas的lineTo方法連接點的,連接相鄰兩點的是條直線,非曲線,因此通過這種方式繪制出來的是條折線;

canvas,曲線

受限于瀏覽器對mousemove事件的采集頻率,大家都知道在mousemove時,瀏覽器是每隔一小段時間去采集當前鼠標的坐標的,因此鼠標移動的越快,采集的兩個臨近點的距離就越遠,故“折線感越明顯“;

如何才能畫出平滑的曲線?

要畫出平滑的曲線,其實也是有方法的,lineTo靠不住那我們可以采用canvas的另一個繪圖API——quadraticCurveTo ,它用于繪制二次貝塞爾曲線。

二次貝塞爾曲線

quadraticCurveTo(cp1x, cp1y, x, y)

調用quadraticCurveTo方法需要四個參數,cp1x、cp1y描述的是控制點,而xy則是曲線的終點:

canvas,曲線

更多詳細的信息可移步MDN

既然要使用貝塞爾曲線,很顯然我們的數據是不夠用的,要完整描述一個二次貝塞爾曲線,我們需要:起始點、控制點和終點,這些數據怎么來呢?

有一個很巧妙的算法可以幫助我們獲取這些信息

獲取二次貝塞爾關鍵點的算法

這個算法并不難理解,這里我直接舉例子吧:

假設我們在一次繪畫中共采集到6個鼠標坐標,分別是A, B, C, D, E, F;取前面的A, B, C三點,計算出BC的中點B1,以A為起點,B為控制點,B1為終點,利用quadraticCurveTo繪制一條二次貝塞爾曲線線段;

canvas,曲線

接下來,計算得出CD點的中點C1,以B1為起點、C為控制點、C1為終點繼續(xù)繪制曲線;

canvas,曲線

依次類推不斷繪制下去,當到最后一個點F時,則以DE的中點D1為起點,以E為控制點,F為終點結束貝塞爾曲線。

canvas,曲線

OK,算法就是這樣,那我們基于該算法再對現(xiàn)有代碼進行一次升級改造:

let isDown = false;let points = [];let beginPoint = null;const canvas = document.querySelector('#canvas');const ctx = canvas.getContext('2d');// 設置線條顏色ctx.strokeStyle = 'red';ctx.lineWidth = 1;ctx.lineJoin = 'round';ctx.lineCap = 'round';canvas.addEventListener('mousedown', down, false);canvas.addEventListener('mousemove', move, false);canvas.addEventListener('mouseup', up, false);canvas.addEventListener('mouseout', up, false);function down(evt) {    isDown = true;    const { x, y } = getPos(evt);    points.push({x, y});    beginPoint = {x, y};}function move(evt) {    if (!isDown) return;    const { x, y } = getPos(evt);    points.push({x, y});    if (points.length > 3) {        const lastTwoPoints = points.slice(-2);        const controlPoint = lastTwoPoints[0];        const endPoint = {            x: (lastTwoPoints[0].x + lastTwoPoints[1].x) / 2,            y: (lastTwoPoints[0].y + lastTwoPoints[1].y) / 2,        }        drawLine(beginPoint, controlPoint, endPoint);        beginPoint = endPoint;    }}function up(evt) {    if (!isDown) return;    const { x, y } = getPos(evt);    points.push({x, y});    if (points.length > 3) {        const lastTwoPoints = points.slice(-2);        const controlPoint = lastTwoPoints[0];        const endPoint = lastTwoPoints[1];        drawLine(beginPoint, controlPoint, endPoint);    }    beginPoint = null;    isDown = false;    points = [];}function getPos(evt) {    return {        x: evt.clientX,        y: evt.clientY    }}function drawLine(beginPoint, controlPoint, endPoint) {    ctx.beginPath();    ctx.moveTo(beginPoint.x, beginPoint.y);    ctx.quadraticCurveTo(controlPoint.x, controlPoint.y, endPoint.x, endPoint.y);    ctx.stroke();    ctx.closePath();}

在原有的基礎上,我們創(chuàng)建了一個變量points用于保存之前mousemove事件中鼠標經過的點,根據該算法可知要繪制二次貝塞爾曲線起碼需要3個點以上,因此我們只有在points中的點數大于3時才開始繪制。接下來的處理就跟該算法一毛一樣了,這里不再贅述。

代碼更新后我們的曲線也變得平滑了許多,如下圖所示:

canvas,曲線

本文到這里就結束了,希望大家在canvas畫板中“畫”得愉快~我們下次再見:)

感興趣的童鞋可戳這里關注我的博客,任何新鮮好玩的博文將會第一時間分享到這兒哦~

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到HTML教程頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
欧美影院午夜播放| 成人黄色视屏网站| 久久影院午夜片一区| 久久精品色图| 日本成人网址| 青娱乐国产在线| www.日本高清视频| 国产一区二区三区久久久久久久久| yw3121.龙物视频永不失联| 在线视频中文亚洲| 国产亚洲精品bv在线观看| 好男人社区在线视频| 欧美 日韩 国产在线| 欧美日韩免费观看中文| 国产深夜精品| 国产日韩在线免费| 亚洲综合激情另类专区老铁性| 国产日韩视频一区二区三区| 四虎海外永久免费网址| 欧美婷婷久久五月精品三区| www久久日com| 日本免费黄色小视频| 欧美黄色aaaa| 成人有码在线播放| 日本道在线视频| 国产精品亚洲欧美在线播放| 欧美一级欧美一级在线播放| 欧美性猛交 xxxx| 国内性生活视频| 精品av导航| 97精品国产97久久久久久粉红| 牲欧美videos精品| 91国自产精品中文字幕亚洲| 成人精品高清在线| 国产免费一区二区三区香蕉精| 久久精品国产免费| 第一中文字幕在线| www成人啪啪18软件| 欧美巨大xxxx做受沙滩| 欧美xingq一区二区| 亚洲精品乱码电影在线观看| 午夜国产在线观看| 在线成人激情黄色| 在线视频一区二区| 亚洲乱码在线| 国产欧美一区二区三区米奇| 一级做a爰片性色毛片视频| 992tv在线观看| 国产精品久久久乱弄| 亚洲aaaaaaa| 精品福利视频一区二区三区| 亚洲日本国产精品| 九九综合在线| 久久久久亚洲av无码麻豆| 999国内精品视频在线| 欧美日韩亚洲高清| 国产精品外国| 在线免费一区二区| 亚洲精品黑牛一区二区三区| 在线视频你懂得| 亚洲精品xxxx| 91成人福利视频| 亚洲网址你懂得| 在线免费观看中文字幕| 小泽玛利亚视频在线观看| 欧美亚州一区二区三区| 亚洲乱码一区二区三区三上悠亚| 日韩一级片免费看| japonensisjava老师可播放| 俄罗斯xxxx性全过程| 久久久久久久久久久91| 国产二区视频在线观看| 午夜久久中文| 奇米色777欧美一区二区| 四虎成人永久免费视频| 亚洲的天堂在线中文字幕| 日本视频在线观看| 女人高潮被爽到呻吟在线观看| 99蜜桃臀久久久欧美精品网站| 在线国产欧美| 亚洲综合专区| 日韩一卡二卡三卡| 国产在线更新| 131美女爱做视频| 精品视频一二三| 中文字幕视频在线免费观看| 中文字幕欧美日韩一区| 亚洲精品一区二区妖精| 免费黄漫在线观看| 亚洲欧美日韩精品一区二区| 无码aⅴ精品一区二区三区浪潮| 激情五月激情综合网| 国产精品中文字幕日韩精品| 久久精品电影网站| 国产精品天天看天天狠| 午夜精品美女自拍福到在线| 一区二区三区四区av| 欧美日韩一区二区三区在线免费观看| 欧美图片自拍偷拍| 日韩免费三级| 亚洲欧美日韩偷拍| 精品日本美女福利在线观看| 欧美成人小视频| 日本一区二区免费在线观看| 中文字幕日韩欧美精品在线观看| 伊人中文在线| 中文字幕一区在线| 成年人免费看毛片| 国产精品高潮呻吟视频| 26uuu亚洲综合色| 国产精品影片在线观看| 日本福利午夜视频在线| 亚洲激情另类| 国产一区视频导航| 日日夜夜免费精品| 激情婷婷欧美| 国产叼嘿视频在线观看| 亚洲视频在线观看一区二区| 日韩在线免费电影| 国产色在线 com| 美国黄色特级片| 九九热视频精品在线观看| www日本视频| 国产婷婷色一区二区在线观看| ㊣最新国产の精品bt伙计久久| 狠狠色综合网站久久久久久久| 粉嫩av国产一区二区三区| 欧美激情喷水视频| 二人午夜免费观看在线视频| 日韩av在线电影观看| 欧美日韩在线一| av资源在线看| 丁香花高清视频完整版在线观看| 国产91露脸中文字幕在线| 国产专区视频| 九色porny丨国产首页在线| 中文字幕在线中文字幕在线中三区| xfplay先锋影音夜色资源站| 一二三四在线观看视频| 91精品一区国产高清在线gif| 日韩午夜激情电影| 黄色激情在线播放| 久久精品女人的天堂av| 奇米777四色影视在线看| 另类视频在线观看+1080p| 欧美日韩在线视频免费| 欧美俄罗斯性视频| 久久精品影视伊人网| 香蕉成人啪国产精品视频综合网| 午夜精品无码一区二区三区| 欧美日韩中国免费专区在线看| 欧美动漫一区二区| 成人毛片在线| 成人一区二区三区视频| 奇米777四色影视在线看| 交视频在线观看国产| 欧美大片免费看| 中文字幕精品www乱入免费视频| 丝袜美腿成人在线| 日本欧美国产在线| 欧美xxxx中国| 国产麻豆9l精品三级站| 最新真实国产在线视频| 亚洲美女精品视频| 都市激情在线视频| 成人黄色av电影| 国产爆初菊在线观看免费视频网站| 另类综合日韩欧美亚洲| 国产一区二区按摩在线观看| 欧美综合在线视频观看| 久久精品久久精品亚洲人| 九九热在线免费视频| 中文字幕第一区二区| 欧美韩国日本精品一区二区三区| 国产麻豆免费视频| 欧美在线一二三区| japan乱配videos老少配| 久久这里只有精品6| 黑色丝袜福利片av久久| 国产小视频免费在线网址| 欧美三区视频| 一级片视频免费观看| 欧美精品日韩精品| 99视频有精品高清视频| 欧美精品自拍| 四虎精品成人免费观看| 久久精品国产68国产精品亚洲| 李丽珍裸体午夜理伦片| 一道本视频在线观看| 国产精品一级久久久| 欧洲成人在线视频| 精品国偷自产在线视频| 国产伦精品一区二区三区免.费| 综合激情网...| 久久亚洲资源| 精品久久国产老人久久综合| 青青草手机视频在线观看| 91久久精品日日躁夜夜躁国产| 免费黄色av网站| 国产乱码在线观看| 日韩亚洲综合在线| 欧美日本高清一区| 日本精品一区在线观看| 日本成人在线网站| 亚洲精品一区av| 这里只有精品6| 成人高清在线观看免费| 欧美日韩高清一区二区不卡| 欧美日韩国内自拍| 国产综合在线观看| 爱爱免费视频网站| 伊人久久中文字幕| 日韩欧美中文一区二区| 韩国女主播一区二区| 综合一区中文字幕| 国产va在线| 亚洲欧美中文日韩v在线观看| 国产福利片在线| 亚洲aⅴ天堂av在线电影软件| 91精品91久久久中77777| 国产精品久久久久av免费| 国产一级黄色片免费| 伊人成人免费视频| 国产精品高颜值在线观看| 精品人妻无码一区二区| 美美哒免费高清在线观看视频一区二区| 亚洲国产日韩欧美| 国产欧美精品一区二区三区-老狼| 国产真实精品久久二三区| 91精品国产aⅴ一区二区| 午夜一区二区三区免费| 国产精品久久久久永久免费观看| 亚洲欧美自拍偷拍色图| 国产精品久久中文| 欧美日韩成人免费视频| 涩爱av色老久久精品偷偷鲁| 超碰在线资源站| 精东传媒在线观看| 亚洲图片欧美另类| 欧美一区二区播放| 制服丝袜中文字幕一区| 欧美色图一区二区三区| 91精品国产高清一区二区三蜜臀| 国产极品久久久| 麻豆视频在线播放| 正在播放精油久久| 亚洲精品一区二区精华| www.99热这里只有精品| 一本色道久久综合亚洲精品不卡| 亚洲va欧美va国产va天堂影院| av网站在线免费看| 自拍亚洲一区欧美另类| 免费看又黄又无码的网站| 欧美极品aⅴ影院| 亚洲春色在线视频| 久久久精品有限公司| 久久亚洲精品爱爱| 欧美一级片免费在线观看| 嫩草香蕉在线91一二三区| 欲求不满中文字幕| 亚洲第一综合网站| 日本一区二区三区在线观看| 日本一区二区免费不卡| 成人一二三区视频| 99热在线精品观看| 这里只有精品在线| 国内成人在线| 亚洲av无码一区二区三区dv| 成人亚洲欧美一区二区三区| 波多野结衣视频在线观看| 精品国产一区二区三区麻豆免费观看完整版| 黄色在线资源| 国产精品久久久毛片| 欧美综合国产精品久久丁香| 天天射综合网视频| 亚洲精品视频在线观看免费视频| 国产乱码精品一区二区三| 成年人在线网站| 国产成人精品亚洲日本在线观看| 九九久久99| 久88久久88久久久| 欧美日韩亚洲国产| 日本一二区视频| 内射国产内射夫妻免费频道| 女同毛片一区二区三区| 午夜精品久久久久久久蜜桃app| 一本综合久久| 成人在线视频www| 亚洲一区二区在线播放相泽| 在线观看日韩一区二区| av日韩免费电影| 黄色免费网址大全| 一区二区三区四区五区视频在线观看| 国产69精品久久久久久久久久| 偷拍盗摄高潮叫床对白清晰| 欧美a在线视频| 午夜黄色小视频| 色婷婷综合久久久中文一区二区| 999精彩视频| 欧美成人免费在线观看视频| 国产欧美一区二| 免费看av大片| 在线观看免费视频国产| 中国精品18videos性欧美| 日韩电影一区二区三区| 亚洲精品**中文毛片| 高清不卡av| 搜索黄色一级片| 一本色道久久综合亚洲精品不卡| 国产一区二区精品久久91| 亚洲人成电影网站色…| 久久精品人人| 伊人精品在线观看| 国产高清自产拍av在线| 伊人久久成人| 操你啦视频分享| 成人高潮片免费视频| 你懂的视频欧美| 亚洲一区站长工具| 先锋影音av中文资源| 免费看国产黄色片| 国产精品国模大尺度视频| 日本一区二区三区视频在线看| 欧美色爱综合| 久久夜色精品国产欧美乱极品| 午夜电影网一区| 日韩三级电影免费观看| 韩国精品视频|