canva繪制海報01:canvas繪制圖片并解決導出后略模糊問題

需求如下:根據(jù)后臺返回的海報背景圖和一個鏈接二維碼(vue-qr)舵变,合成一張圖配椭,然后可以進行長按保存本地操作

思路如下

  1. 使用 canvs.drawImage 繪制圖片到相應位置
  2. canvas.toDataUrl 導出圖片數(shù)據(jù)流到 img 上, 顯示到頁面

遇到的問題

  1. 圖片地址是網(wǎng)絡地址且不同域名垢夹,js中新建Image對象并直接賦值src, 會產(chǎn)生跨域
  2. canvas繪制的圖片會變得模糊
跨域問題的解決
  1. 將圖片網(wǎng)絡地址轉(zhuǎn)換為base64流,不推薦
  2. 將圖片下載放置本地列肢,使用本地固定的圖片载庭,部分需求下不能使用, 不理想
  3. 將圖片網(wǎng)絡地址的域名與運行環(huán)境域名保持一致即可, 能解決部分,但也不太理想
  4. 需要后端配合設置Access-Control-Allow-Origin: *

另外豁遭,img 標簽和 js 中的image 都建議增加 crossorigin = "anonymous" 屬性
**注意: **有部分網(wǎng)友評論img.setAttribute('crossOrigin', 'anonymous') 必須是寫 在你賦值 img.src 之前友多,所以樓主寫法有誤 可以看看這個鏈接 去看看, https://stackoverflow.com/questions/20424279/canvas-todataurl-securityerror/27260385#27260385

模糊問題的解決
未優(yōu)化的就決方案

效果圖如下:

未優(yōu)化.jpeg

模糊在線demo

<!DOCTYPE html><html><style>  .content{    display: flex;  }  .poster_img {    width: 300px;  }</style><body>  <div class="content">    <div>      <p>要繪制的圖像:</p>      <img id="tulip" class="poster_img" src="./poster.jpg" alt="The Tulip" />    </div>    <div>      <p>畫布:</p>      <canvas id="myCanvas" width="300" style="border:1px solid #d3d3d3;background:#ffffff;">        Your browser does not support the HTML5 canvas tag.      </canvas>    </div>    <div>      <p>DataURL后的圖片樣式:</p>      <img class="poster_img" id="canvas_img" src="" alt="" srcset="">    </div>  </div></body><script>  var c = document.getElementById("myCanvas");  var ctx = c.getContext("2d");  var canvasImg = document.getElementById("canvas_img")  const img = new Image()  img.src = document.getElementById("tulip").src;  img.onload = function () {    const imgScale = img.width / img.height;    c.style.width = c.width + 'px'    c.style.height = c.width / imgScale + 'px'    c.width = c.width;    c.height = c.width / imgScale;    ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, c.width, c.height);    canvasImg.src = c.toDataURL('image/jpeg', 1)  }</script></html>

模糊原因分析:
??在瀏覽器的 window 對象中有一個 devicePixelRatio 的屬性,該屬性表示了屏幕的設備像素比堤框,即用幾個(通常是2個)像素點寬度來渲染1個像素域滥。
??舉例來說,假設 devicePixelRatio 的值為 2 蜈抓,一張 100×100 像素大小的圖片启绰,在 Retina 屏幕下,會用 2 個像素點的寬度去渲染圖片的 1 個像素點沟使,因此該圖片在 Retina 屏幕上實際會占據(jù) 200×200 像素的空間委可,相當于圖片被放大了一倍,因此圖片會變得模糊。
??類似的着倾,在 canvas context 中也存在一個 backingStorePixelRatio 的屬性拾酝,該屬性的值決定了瀏覽器在渲染canvas之前會用幾個像素來來存儲畫布信息。 backingStorePixelRatio 屬性在各瀏覽器廠商的獲取方式不一樣卡者,所以需要加上瀏覽器前綴來實現(xiàn)兼容蒿囤。

解決方案:
1.首先一樣,獲取 Canvas 對象:
2.獲取像素比崇决,將 Canvas 寬高進行放大材诽,放大比例為:devicePixelRatio / webkitBackingStorePixelRatio , 我們寫了一個兼容的方法。
3.按實際渲染倍率來縮放canvas恒傻。
注意基礎知識點:
要設置canvas的畫布大小脸侥,使用的是 canvas.width 和 canvas.height;
要設置畫布的實際渲染大小盈厘,使用的 style 屬性或CSS設置的 width 和height睁枕,只是簡單的對畫布進行縮放。
4.繪制

優(yōu)化后的解決方案

效果圖如下

優(yōu)化后.jpg

優(yōu)化后不模糊的在線demo

<!DOCTYPE html><html><style>  .content{    display: flex;  }  .poster_img {    width: 300px;  }</style><body>  <div class="content">    <div>      <p>要繪制的圖像:</p>      <img id="tulip" class="poster_img" src="./psoter.jpg" alt="The Tulip" />    </div>    <div>      <p>畫布:</p>      <canvas id="myCanvas" width="300" style="border:1px solid #d3d3d3;background:#ffffff;">        Your browser does not support the HTML5 canvas tag.      </canvas>    </div>    <div>      <p>DataURL后的圖片樣式:</p>      <img class="poster_img" id="canvas_img" src="" alt="" srcset="">    </div>  </div></body><script>  var getPixelRatio = function (context) {    var backingStore = context.backingStorePixelRatio ||      context.webkitBackingStorePixelRatio ||      context.mozBackingStorePixelRatio ||      context.msBackingStorePixelRatio ||      context.oBackingStorePixelRatio ||      context.backingStorePixelRatio || 1;    return (window.devicePixelRatio || 1) / backingStore;  };  var c = document.getElementById("myCanvas");  var ctx = c.getContext("2d");  var ratio = getPixelRatio(ctx);  ctx.scale(ratio, ratio)  var canvasImg = document.getElementById("canvas_img")  const img = new Image()  img.src = document.getElementById("tulip").src;  img.onload = function () {    const imgScale = img.width / img.height;    c.style.width = c.width + 'px'    c.style.height = c.width / imgScale + 'px'    c.width = c.width * ratio;    c.height = c.width / imgScale;    ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, c.width, c.height);    canvasImg.src = c.toDataURL('image/jpeg', 1)  }</script></html>

參考鏈接:
一個關(guān)于image訪問圖片跨域的問題,http://www.reibang.com/p/8fa0fb53c183

解決 canvas 將圖片轉(zhuǎn)為base64報錯: Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported, http://www.reibang.com/p/6fe06667b748

解決 canvas 在高清屏中繪制模糊的問題, https://www.html.cn/archives/9297

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末沸手,一起剝皮案震驚了整個濱河市外遇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌罐氨,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,627評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件滩援,死亡現(xiàn)場離奇詭異栅隐,居然都是意外死亡,警方通過查閱死者的電腦和手機玩徊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評論 3 399
  • 文/潘曉璐 我一進店門租悄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人恩袱,你說我怎么就攤上這事泣棋。” “怎么了畔塔?”我有些...
    開封第一講書人閱讀 169,346評論 0 362
  • 文/不壞的土叔 我叫張陵潭辈,是天一觀的道長。 經(jīng)常有香客問我澈吨,道長把敢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,097評論 1 300
  • 正文 為了忘掉前任谅辣,我火速辦了婚禮修赞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘桑阶。我一直安慰自己柏副,他們只是感情好勾邦,可當我...
    茶點故事閱讀 69,100評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著割择,像睡著了一般眷篇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上锨推,一...
    開封第一講書人閱讀 52,696評論 1 312
  • 那天铅歼,我揣著相機與錄音,去河邊找鬼换可。 笑死椎椰,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的沾鳄。 我是一名探鬼主播慨飘,決...
    沈念sama閱讀 41,165評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼译荞!你這毒婦竟也來了瓤的?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,108評論 0 277
  • 序言:老撾萬榮一對情侶失蹤吞歼,失蹤者是張志新(化名)和其女友劉穎圈膏,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體篙骡,經(jīng)...
    沈念sama閱讀 46,646評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡稽坤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,709評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了糯俗。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片尿褪。...
    茶點故事閱讀 40,861評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖得湘,靈堂內(nèi)的尸體忽然破棺而出杖玲,到底是詐尸還是另有隱情,我是刑警寧澤淘正,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布摆马,位于F島的核電站,受9級特大地震影響鸿吆,放射性物質(zhì)發(fā)生泄漏今膊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,196評論 3 336
  • 文/蒙蒙 一伞剑、第九天 我趴在偏房一處隱蔽的房頂上張望斑唬。 院中可真熱鬧,春花似錦、人聲如沸恕刘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽褐着。三九已至坷澡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間含蓉,已是汗流浹背频敛。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留馅扣,地道東北人斟赚。 一個月前我還...
    沈念sama閱讀 49,287評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像差油,于是被迫代替她去往敵國和親拗军。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,860評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 注:[n]標識為遺留問題,在文章末尾遺留問題部分有詳細解釋說明妆偏。 之前做了一個在線給圖片添加文本框的工具刃鳄,大體思路...
    流動碼文閱讀 1,459評論 0 1
  • 注:[n]標識為遺留問題叔锐,在文章末尾遺留問題部分有詳細解釋說明。 之前做了一個在線給圖片添加文本框的工具罐柳,大體思路...
    lzxxx閱讀 17,173評論 4 9
  • 一掌腰、canvas簡介 1.1 什么是canvas狰住?(了解) 是HTML5提供的一種新標簽 Canvas是一個矩形區(qū)...
    J_L_L閱讀 1,520評論 0 4
  • 一张吉、圖形的組合方式 globalAlpha是一個介于0和1之間的值(包括0和1),用于指定所有繪制的透明度催植。默認值...
    空谷悠閱讀 1,282評論 0 0
  • 驗證瀏覽器是否支持 Your browser does not support HTML5 Canvas. f...
    shuaiutopia閱讀 2,640評論 0 0