午夜视频免费看_日韩三级电影网站_国产精品久久一级_亚洲一级在线播放_人妻体内射精一区二区三区_91夜夜揉人人捏人人添红杏_91福利在线导航_国产又粗又猛又黄又爽无遮挡_欧美日韩一区在线播放_中文字幕一区二区三区四区不卡 _日日夜夜精品视频免费观看_欧美韩日一区二区三区

主頁 > 知識庫 > 探究 canvas 繪圖中撤銷(undo)功能的實現(xiàn)方式詳解

探究 canvas 繪圖中撤銷(undo)功能的實現(xiàn)方式詳解

熱門標(biāo)簽:ai電銷機器人連接網(wǎng)關(guān) 鶴壁手機自動外呼系統(tǒng)怎么安裝 農(nóng)村住宅地圖標(biāo)注 威海營銷外呼系統(tǒng)招商 中紳電銷智能機器人 漳州人工外呼系統(tǒng)排名 跟電銷機器人做同事 濟南辦理400電話 鄭州電銷外呼系統(tǒng)違法嗎

最近在做網(wǎng)頁版圖片處理相關(guān)的項目,也算是初入了 canvas 的坑。項目需求中有一個給圖片添加水印的功能。我們知道,在瀏覽器端實現(xiàn)圖片添加水印功能,通常的做法就是使用 canvasdrawImage 方法。對于普通的合成(比如一張底圖和一張 PNG 水印圖片合成)來說,其大致實現(xiàn)原理如下:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');

// img: 底圖
// watermarkImg: 水印圖片
// x, y 是畫布上放置 img 的坐標(biāo)
ctx.drawImage(img, x, y);
ctx.drawImage(watermarkImg, x, y);

直接連續(xù)使用 drawImage() 把對應(yīng)的圖片繪制到 canvas 畫布上就行。

以上就是背景介紹。但是略麻煩的是添加水印的需求中還有一個需要實現(xiàn)的功能是用戶能夠切換水印的位置。我們自然會想到能否實現(xiàn) canvasundo 功能,當(dāng)用戶切換水印位置時,先撤銷上一步 drawImage 操作,然后再重新繪制水印圖片位置。

restore / save ?

效率最高也是最方便的肯定是查閱 canvas 2D 原生 API 是否有此功能。經(jīng)過一番搜索, restore / save 這一對 API 進入視線。我們先看一下這兩個 API 的描述:

CanvasRenderingContext2D.restore() 是 Canvas 2D API 通過在繪圖狀態(tài)棧中彈出頂端的狀態(tài),將 canvas 恢復(fù)到最近的保存狀態(tài)的方法。 如果沒有保存狀態(tài),此方法不做任何改變。

CanvasRenderingContext2D.save() 是 Canvas 2D API 通過將當(dāng)前狀態(tài)放入棧中,保存 canvas 全部狀態(tài)的方法。

乍看起來可以滿足需求。我們看一下官方示例代碼:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

ctx.save(); // 保存默認的狀態(tài)
ctx.fillStyle = "green";
ctx.fillRect(10, 10, 100, 100);

ctx.restore(); // 還原到上次保存的默認狀態(tài)
ctx.fillRect(150, 75, 100, 100);

結(jié)果如下圖所示:

奇怪,好像和我們預(yù)期的結(jié)果不太一致。我們想要的結(jié)果是 save 方法調(diào)用后能夠保存當(dāng)前畫布的快照, resolve 方法調(diào)用后能夠完全回到上一個保存的快照處的狀態(tài)。

再仔細研究一下 API。原來我們遺漏一個重要概念: drawing state ,也就是繪制狀態(tài)。保存到棧中的繪制狀態(tài)包含以下幾個部分:

  1. 當(dāng)前的變換矩陣
  2. 當(dāng)前的剪切區(qū)域
  3. 當(dāng)前的虛線列表

以下屬性當(dāng)前的值:strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, lineDashOffset, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation, font, textAlign, textBaseline, direction, imageSmoothingEnabled.

好吧, drawImage 操作后對畫布的改變根本不存在于繪制狀態(tài)中。所以,使用 resolve / save 無法實現(xiàn)我們需要的 undo 功能。

模擬棧實現(xiàn)

既然原生的 API 保存繪制狀態(tài)的棧無法滿足需求,那么自然我們會想到自己模擬一個保存操作的棧。隨之而來的問題就是:每次繪制操作之后,應(yīng)該保存什么數(shù)據(jù)進棧?前面說過,我們想要的是每步繪制操作之后能夠保存當(dāng)前畫布的 快照 ,如果能拿到快照數(shù)據(jù),同時能利用快照數(shù)據(jù)恢復(fù)畫布的話,問題也就迎刃而解了。

幸運的是 canvas 2D 原生提供了獲取快照和通過快照恢復(fù)畫布的 API —— getImageData / putImageData 。以下是 API 說明:

/*
 * @param { Number } sx 將要被提取的圖像數(shù)據(jù)矩形區(qū)域的左上角 x 坐標(biāo)
 * @param { Number } sy 將要被提取的圖像數(shù)據(jù)矩形區(qū)域的左上角 y 坐標(biāo)
 * @param { Number } sw 將要被提取的圖像數(shù)據(jù)矩形區(qū)域的寬度
 * @param { Number } sh 將要被提取的圖像數(shù)據(jù)矩形區(qū)域的高度
 * @return { Object } ImageData 包含 canvas 給定的矩形圖像數(shù)據(jù)
 */
 ImageData ctx.getImageData(sx, sy, sw, sh);
 
 /*
 * @param { Object } imagedata 包含像素值的對象
 * @param { Number } dx 源圖像數(shù)據(jù)在目標(biāo)畫布中的位置偏移量(x 軸方向的偏移量)
 * @param { Number } dy 源圖像數(shù)據(jù)在目標(biāo)畫布中的位置偏移量(y 軸方向的偏移量)
 */
 void ctx.putImageData(imagedata, dx, dy);

我們來看一個簡單的應(yīng)用方式:

class WrappedCanvas {
    constructor (canvas) {
        this.ctx = canvas.getContext('2d');
        this.width = this.ctx.canvas.width;
        this.height = this.ctx.canvas.height;
        this.imgStack = [];
    }
    drawImage (...params) {
        const imgData = this.ctx.getImageData(0, 0, this.width, this.height);
        this.imgStack.push(imgData);
		this.ctx.drawImage(...params);
    }
    undo () {
        if (this.imgStack.length > 0) {
            const imgData = this.imgStack.pop();
            this.ctx.putImageData(imgData, 0, 0);
        }
    }
}

我們封裝了一下 canvasdrawImage 方法,每次調(diào)用該方法之前都會保存上一個狀態(tài)的快照到模擬的棧中。在執(zhí)行 undo 操作時,從棧中取出最新保存的快照,然后重新繪制畫布,即可實現(xiàn)撤銷操作。實際測試也符合預(yù)期。

性能優(yōu)化

上一節(jié)中我們很粗獷地實現(xiàn)了 canvas 的撤銷功能。為什么說粗獷呢?一個很顯而易見的原因就是此方案性能不好。我們的方案相當(dāng)于每次都是重新繪制整個畫布。假設(shè)操作步驟很多,我們在模擬棧也就是內(nèi)存中就會保存很多預(yù)存的圖片數(shù)據(jù)。此外,在繪制圖片過于復(fù)雜時, getImageDataputImageData 這兩個方法會產(chǎn)生比較嚴(yán)重的性能問題。stackoverflow 上有詳細的討論: Why is putImageData so slow? 。我們還可以從 jsperf 上這個測試用例的數(shù)據(jù)來驗證這一點。淘寶 FED 在Canvas 最佳實踐中也提到了盡量“不在動畫中使用 putImageData 方法”。另外,文章里還提到一點,“盡可能調(diào)用那些渲染開銷較低的 API”。我們可以從這里入手思考如何進行優(yōu)化。

之前說過,我們通過對整個畫布保存快照的方式來記錄每個操作,換個角度思考,如果我們把每次繪制的動作保存到一個數(shù)組中,在每次執(zhí)行撤銷操作時,首先清空畫布,然后重繪這個繪圖動作數(shù)組,也可以實現(xiàn)撤銷操作的功能??尚行苑矫?,首先這樣可以減少保存到內(nèi)存的數(shù)據(jù)量,其次還避免了使用渲染開銷較高的 putImageData 。以 drawImage 為比較對象,看 jsperf 上這個測試用例,二者的性能存在數(shù)量級的差距。

因此,我們認為此優(yōu)化方案是可行的。

改進后的應(yīng)用方式大致如下:

class WrappedCanvas {
    constructor (canvas) {
        this.ctx = canvas.getContext('2d');
        this.width = this.ctx.canvas.width;
        this.height = this.ctx.canvas.height;
        this.executionArray = [];
    }
    drawImage (...params) {
        this.executionArray.push({
            method: 'drawImage',
            params: params
        });
		this.ctx.drawImage(...params);
    }
    clearCanvas () {
        this.ctx.clearRect(0, 0, this.width, this.height);
    }
    undo () {
        if (this.executionArray.length > 0) {
            // 清空畫布
            this.clearCanvas();
            // 刪除當(dāng)前操作
            this.executionArray.pop();
            // 逐個執(zhí)行繪圖動作進行重繪
            for (let exe of this.executionArray) {
                this[exe.method](...exe.params)
            }
        }
    }
}

新人入坑 canvas,如有錯誤與不足,歡迎指出。以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

標(biāo)簽:萍鄉(xiāng) 甘南 惠州 營口 紅河 文山 咸陽 蘇州

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《探究 canvas 繪圖中撤銷(undo)功能的實現(xiàn)方式詳解》,本文關(guān)鍵詞  探究,canvas,繪,圖中,撤銷,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《探究 canvas 繪圖中撤銷(undo)功能的實現(xiàn)方式詳解》相關(guān)的同類信息!
  • 本頁收集關(guān)于探究 canvas 繪圖中撤銷(undo)功能的實現(xiàn)方式詳解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    久久影视电视剧免费网站清宫辞电视 | 青青草原成人在线视频| 成人欧美一区二区三区黑人麻豆| 手机在线不卡av| 国产女人18毛片水真多18| 97超级碰碰| 欧美日韩一二区| 亚洲激情男女视频| 久久亚洲私人国产精品va媚药| 免费国产精品视频| 久青草视频在线观看| www.涩涩涩| 久久草视频在线看| 欧美综合在线观看| 中国china体内裑精亚洲片| 日韩欧美一级在线播放| 动漫精品一区二区| 亚洲日本一区二区| 国产精品美女视频| 99久久精品免费看| 日韩电影免费在线| 亚洲成熟少妇视频在线观看| 久久精品99久久久久久| 中文字幕伦理片| 麻豆tv在线播放| 亚洲 国产 欧美一区| 92福利视频午夜1000合集在线观看| 日韩最新免费不卡| 美女视频黄免费的亚洲男人天堂| 亚洲精品99久久久久中文字幕| 欧美激情中文不卡| 午夜精品福利视频网站| 一区二区三区四区视频精品免费| 99riav一区二区三区| 日韩国产欧美在线视频| 亚洲男人第一天堂| 日韩美女视频免费在线观看| 亚洲综合视频在线观看| 91麻豆精品国产91久久综合| 图片区偷拍区小说区| 91小视频在线播放| 亚洲一区和二区| 欧洲美女亚洲激情| 九九热免费在线| 99久久激情视频| av污在线观看| 日本精品在线免费观看| 国产一级免费视频| 特级毛片www| xxxx18国产| 日韩精品一级二级| 成人av第一页| 欧美日韩日日摸| 精品日韩一区二区三区| 精品精品欲导航| 色一区av在线| 99久久国产免费免费| 国产精品久久久久久一区二区 | 国产精品30p| 亚洲av无码乱码在线观看性色| 99热国产精品| 中文字幕精品一区二区精品绿巨人| 亚洲人成亚洲人成在线观看图片| 欧美一区二区免费视频| 最近2019年日本中文免费字幕| 国产日韩精品入口| 亚洲精品乱码久久久久久蜜桃91 | 国产人与禽zoz0性伦| 欧美日韩乱国产| 亚洲欧美另类综合| 黄色资源网久久资源365| 国产精品初高中害羞小美女文| www欧美在线| 免费无遮挡无码永久在线观看视频| 欧美性猛交xxxx乱大交hd| 亚洲日韩欧美一区二区在线| 免费视频最近日韩| 日本免费一区二区三区| 在线精品视频视频中文字幕| 国产欧美一区二区三区另类精品| 成人福利小视频| 中文字幕欧美精品日韩中文字幕| 欧美精品激情在线| 91女人18毛片水多国产| 久久男人av资源网站| 久久午夜激情| 疯狂蹂躏欧美一区二区精品| 天堂av一区二区| av午夜一区麻豆| 国产精品久久久久aaaa九色| 91黄色在线视频| 久久777国产线看观看精品| 国产免费高清一区| 亚洲精品久久久久久| 欧美二区在线播放| 你懂得视频在线观看| 亚洲人成电影网站色…| 中文字字幕在线中文| 国产经典欧美精品| 欧洲一区二区在线观看| 久久久久久一级片| 师生出轨h灌满了1v1| 久精品国产欧美| 日韩av影院在线观看| 国产伦精品一区二区三区免费| 国产免费黄色一级片| 亚洲一级二级在线| 久久久国产精华液999999| 91在线云播放| 50路60路老熟妇啪啪| 久久久精品99| 懂色av懂色av粉嫩av| 中文字幕欧美一区| 久久久久久久电影一区| 久久99久久久久| 中文字幕一区二区人妻视频| 美女又黄又免费的视频| 欧美另类网站| 91麻豆精品国产| 婷婷社区五月天| 亚洲黄色av网站| 永久看片925tv| 欧美情侣性视频| 久久99精品视频| 亚洲免费精彩视频| 日韩成人av一区二区| 亚洲三级理论片| 久久精品人人做人人爽电影| 亚洲欧美在线aaa| 五月天丁香花婷婷| 欧美日韩性生活| 五月天婷婷久久| 欧美乱大交xxxxx潮喷l头像| 国产美女久久精品| 亚洲色图五月天| 亚洲成人激情av| 欧美日韩成人精品| 又色又爽又黄无遮挡的免费视频| 欧美极品少妇xxxxⅹ喷水| 国产美女明星三级做爰| 黄网站欧美内射| 午夜精品久久久久久久久久久久久| 国产视频1区2区| 欧美一卡2卡3卡4卡| 日本一区二区免费视频| 欧美理论电影在线| 蜜桃av免费在线观看| 亚洲自拍偷拍视频| 91麻豆精品国产自产在线 | 在线一区二区三区| 欧美午夜精品久久久久久蜜| 成人信息集中地| 亚洲午夜激情网站| 天天操狠狠操夜夜操| 在线免费观看一区| 午夜成人亚洲理伦片在线观看| 福利精品视频| 亚洲小说欧美激情另类| 国产成人在线免费观看视频| 99re国产在线播放| 久久se这里有精品| 国产黄频在线观看| 深夜福利视频网站| 亚洲图片在线视频| 久久久久久www| 久久久久久免费| 色综合久久中文字幕综合网| 一区二区三区视频| 欧美色国产精品| 视频一区免费在线观看| 一女三黑人理论片在线| 久久精品电影网站| 黄色大全在线观看| 国产尤物99| 欧美国产激情一区二区三区蜜月| aaaaa一级片| 日韩免费观看高清| 日韩精品电影一区亚洲| 少妇一晚三次一区二区三区| 91黄视频在线观看| yy6080午夜| 精品国产区一区二区三区在线观看| 精品人妻伦一二三区久| 一区二区国产盗摄色噜噜| www.色.com| 欧美激情亚洲视频| 国产亚洲va综合人人澡精品 | 国产高清在线一区二区| 欧美国产日产图区| 久久久久久久一区二区三区| 精品少妇人妻一区二区黑料社区| 国产欧美日本一区视频| 国产91精品青草社区| 日韩久久中文字幕| 国产精品日韩欧美综合| 成人午夜看片网址| 黄色在线观看av| 97超级碰碰人国产在线观看| 日韩国产在线观看| 99热自拍偷拍| 日韩精品黄色网| 日日噜噜夜夜狠狠视频欧美人| 一区二区三区四区| 精品视频在线免费看| 91 中文字幕| 欧美国产日本在线| 91欧美一区二区| 伊人色综合久久天天五月婷| 日韩精品在线视频| 激情综合网激情| av在线无限看| 在线免费观看羞羞视频一区二区| 这里只有精品免费视频| 国产深夜男女无套内射| 欧美肥老妇视频| 中文字幕在线一区二区三区| 欧美性受xxxx黑人| 国产伦精品一区二区三区精品视频 | 亚洲自拍偷拍网址| 午夜欧美性电影| 欧美婷婷精品激情| 欧美日韩人妻精品一区二区三区| 国产精品爽爽久久久久久| 久久国产三级精品| 蜜臀av一区二区| 国产av无码专区亚洲av| 成人午夜视频在线播放| 中文字幕在线观看欧美| 涩多多在线观看| 无码一区二区三区在线| 一级黄色片毛片| 91精品国产91久久久久青草| 亚洲成年人影院在线| 一区二区三区毛片| 国产精品一区二区男女羞羞无遮挡 | 丁香花五月婷婷| 黄色在线视频网址| 夜夜躁狠狠躁日日躁av| 久久久久国产精品麻豆| 91麻豆精品国产91久久久使用方法| 春色成人在线视频| 99免费视频观看| 婷婷国产成人精品视频| 伊人在线视频观看| 久久国产精品波多野结衣av| 7799精品视频天天看| 国产一级精品视频| 亚洲天堂国产精品| 蜜臀av中文字幕| 欧美一区二区三区成人片在线| 能看的毛片网站| 亚洲一区二区三区精品在线观看| 欧美激情在线播放| 久久夜色精品国产欧美乱| 亚洲第一精品在线观看| 中文字幕 欧美日韩| 麻豆国产尤物av尤物在线观看| 91日韩精品视频| 国产天堂在线播放| 污污动漫在线观看| 国产视频三区四区| 日韩av电影一区| 亚洲 国产 日韩 欧美| 99精品在线观看视频| 蜜臀久久久久久久| 国产精品污网站| 欧美丝袜一区二区三区| 欧美大片国产精品| 欧美高清第一页| 日韩影片在线播放| 欧美综合在线播放| 国产精品久久成人免费观看| 色一情一乱一伦一区二区三区丨 | 国产精品成人久久| 国产精品一区2区| 91精品国产麻豆国产自产在线| 欧美激情a∨在线视频播放| 538国产精品视频一区二区| koreanbj精品视频一区| 九一免费在线观看| www日韩视频| 性活交片大全免费看| 久久久国产精华液| 亚洲黄色一级大片| 国产在线视频一区二区三区| 国产精品不卡视频| 欧美日韩在线播放三区四区| 亚洲品质视频自拍网| 国产精品aaa| 91精品国产毛片武则天| 中文字幕国产专区| 国产精品亚洲欧美在线播放| 成人免费视频免费观看| 欧美日韩一区二区三区在线 | 久久丫精品忘忧草西安产品| 九九九在线视频| 奇米四色…亚洲| 色综合天天做天天爱| xxx一区二区| 四虎影院一区二区| 丁香花五月婷婷| 天堂一区二区三区| 九色一区二区| 喷水视频在线观看| 国产精品久久久久久69| 中文字幕亚洲一区二区av在线| 亚洲欧美在线一区| 国产日韩久久| 一级特级黄色片| 久久久久免费| 欧美精品日韩综合在线| 91亚洲国产成人久久精品网站 | 欧美视频一区二区三区在线观看| 国内精品400部情侣激情| 精品九九九九| 日本精品在线免费观看| 国产精品乱码一区二三区小蝌蚪| 欧美日韩精品一区二区三区 | 亚洲欧美日韩国产中文在线| 亚洲国产97在线精品一区| 欧美黑人巨大xxx极品| 免费av一区二区三区| 欧洲成人午夜精品无码区久久| 日批视频在线播放| 欧美精品欧美精品系列| 成人午夜激情免费视频| 欧美色图亚洲激情| 国产成人av自拍| 久久亚洲精品一区| 99九九99九九九99九他书对| 视频一区视频二区在线观看| 黑人巨大精品欧美一区二区三区| 久久中文精品视频| 精品国产一区二区三区在线| 992在线观看| 久久成人18免费观看| 欧美视频专区一二在线观看| 欧洲s码亚洲m码精品一区| www亚洲国产| 亚洲高清视频免费观看| 91丨porny丨最新| 亚洲免费人成在线视频观看| 国产福利精品在线| 久久婷婷五月综合| 欧美一区二区.| 国产一区精品视频| 精品视频第一页| 成人永久看片免费视频天堂| 日韩免费视频线观看| 曰韩不卡视频| 亚洲黄色一级大片| 亚洲成人网在线观看| 免费cad大片在线观看| 一区二区的视频| 亚洲国产精品yw在线观看| 欧美日韩在线播放一区二区| 亚洲一区 欧美| 岛国精品一区二区| 2019精品视频| 青青草国产精品视频| 亚洲av电影一区| 欧美成年人网站| 粉嫩av蜜桃av蜜臀av| 972aa.com艺术欧美| 91在线观看免费网站| 中文字幕一区二区人妻视频| 日韩你懂的在线播放| 伊人成人免费视频| 国产亚洲一区二区三区在线观看 | 欧美一级二级在线观看| 91九色极品视频| 亚洲国产av一区二区三区| 在线国产精品视频| 天天色天天综合| 亚洲精品在线观| 尤物视频最新网址| 色婷婷久久久综合中文字幕| 男女视频网站在线观看| av不卡免费电影| 成人午夜影院在线观看| 欧美三级韩国三级日本三斤在线观看| 综合av第一页| 国产精品sss| 国产第一页第二页| 日韩欧美一级特黄在线播放| 中文字幕一区二区久久人妻网站| 亚洲成人tv网| 国产永久免费网站| 欧美综合亚洲图片综合区| 亚洲国产日韩在线一区| 色悠悠久久综合| 97人妻精品一区二区三区免费| 色噜噜久久综合| 亚洲精品在线视频免费观看| 激情文学综合插| 亚洲最大的网站| 婷婷在线免费视频| 色吊一区二区三区| 国产精品999视频| 精品高清美女精品国产区| www.涩涩涩| 欧美日韩亚洲综合| 精品少妇一区二区三区在线| 极品少妇xxxx精品少妇| 久久av一区二区三区亚洲| 首页国产欧美久久| 日韩在线一区视频| 欧美精品第1页| 久久亚洲成人av| 国产成人精品在线视频|