亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

web瀏覽器端怎么實現

發布時間:2022-01-11 17:20:26 來源:億速云 閱讀:146 作者:iii 欄目:開發技術

這篇文章主要介紹“web瀏覽器端怎么實現”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“web瀏覽器端怎么實現”文章能幫助大家解決問題。

瀏覽器端實現方案

開發:大事件長圖和專輯詳情頁大事件tab的視覺效果基本一致,如果能復用可以減少開發時間。

開發:怎么復用呢?

于是便有了下面在瀏覽器端嘗試dom轉圖片的兩種方案:

html2canvas

html2canvas一個在瀏覽器端通過JS對整個或部分頁面進行“截屏”的庫。

html2canvas使用方法簡單,截屏的核心代碼如下:

let imgBase64;
html2canvas(htm,{
   onrendered : function(canvas){
    //生成base64圖片數據
    imgBase64 = canvas.toDataURL();
});

使用簡單,但是坑不少,遇到的坑及解決方案:

1.截圖模糊

主要解決思路:

1)將canvas的width和height屬性放大為2倍。

2)將canvas的CSS樣式width和height設置為原先1倍的大小。

<canvas width="200" height="100" style="width:100px;height:50px;"></canvas>
2.截圖不全

源碼獲取dom高度不準確,修改源碼,獲取高度后手動傳,修改方式如下:

源碼:

return renderDocument(node.ownerDocument, options, node.ownerDocument.defaultView.innerWidth, node.ownerDocument.defaultView.innerHeight, index).then(function(canvas) {
        if (typeof(options.onrendered) === "function") {
            log("options.onrendered is deprecated, html2canvas returns a Promise containing the canvas");
            options.onrendered(canvas);
        }
        return canvas;
});

修改后

//添加自定義高度寬度
    var width = options.width != null ? options.width : node.ownerDocument.defaultView.innerWidth;
    var height = options.height != null ? options.height : node.ownerDocument.defaultView.innerHeight;
    return renderDocument(node.ownerDocument, options, width, height, index).then(function (canvas) {
        if (typeof(options.onrendered) === "function") {
            log("options.onrendered is deprecated, html2canvas returns a Promise containing the canvas");
            options.onrendered(canvas);
        }
        return canvas;
    });
3.截圖慢

截圖慢得從html2canvas的原理說起,html2canvas并不是真正的截圖,而是遍歷加載的頁面DOM,收集所有元素的信息,然后基于從DOM讀取的屬性使用canvas來繪制。

基于這個截圖原理,慢的問題優化空間不大,而且html2canvas還有些CSS的限制,它只能正確地呈現它支持的CSS屬性,完整的CSS屬性支持列表,可以在官網查看。

關于慢,最簡單的解決方案是在用戶操作前提前生成截圖。

4.crash

html2canvas截圖后,將圖片的base64傳到客戶端的分享組件,當base64超過500k可能導致客戶端卡死或crash,如果慢的問題還能忍,那這個問題是真的沒法接受的。

svg

除了html2canvas網上也有更輕量更快的庫,這些庫是基于svg的,嘗試了下確實比html2canvas快很多。

svg方案的嘗試:

//要轉成圖片的dom
let htm = '<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="auto"><foreignObject width="100%" height="100%"><div xmlns="http://www.w3.org/1999/xhtml"><div>這里是頁面內容...</div></div></foreignObject></svg>';
let DOMURL = window.URL || window.webkitURL || window;
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
let img = new Image();
let svg = new Blob([htm], {type: 'image/svg+xml;charset=utf-8'});
let url = DOMURL.createObjectURL(svg);
let imgBase64;
img.onload = function () {
  ctx.drawImage(img, 0, 0);
  imgBase64 = canvas.toDataURL();
}
img.src = url;

svg方案沒法繞過的坑:

1.ios下不支持跨域圖片

由于安全限制,ios下跨域圖片加crossOrigin屬性也沒法繞過跨域問題。

2.crash

和html2canvas一樣,svg轉圖片后最終也是轉base64傳分享組件,base64超過500K可能導致的卡死和crash問題也存在。

服務器端實現方案

開發:瀏覽器端的方案crash問題不能忍,不如在服務器端生成圖片,傳圖片URL到分享組件?

本著最大限度復用代碼的初衷,首選了無頭瀏覽器phantomjs截圖的方案。

PhantomJS

PhantomJS是基于WebKit內核的無頭瀏覽器,提供瀏覽器環境的命令行接口,我們可以進行網頁截圖、抓取網頁數據等操作,更多詳情可以去PhantomJS官網查看。

安裝PhantomJS時,注意安裝以下依賴:

sudo yum -y install gcc gcc-c++ make flex bison gperf ruby openssl-devel freetype-devel fontconfig-devel libicu-devel sqlite-devel libpng-devel libjpeg-devel

服務器端方案選擇的是phantomjs-node庫,實現截圖的核心代碼如下

var sitepage = null; var phInstance = null; phantom.create()     .then(instance => {         phInstance = instance;         return instance.createPage();     })     .then(page => {         let htm = [             '<!DOCTYPE html>',             '<html>',             '<head>',                 '<meta charset="utf-8">',             '</head>',             '<body style="background:#fff">',                 '<div>'+ new Date() +'</div>',             '</body>',             '</html>'         ].join("");         page.property('content',htm);         page.render('./test.png').then((err) => {             phInstance.exit()         }).catch(err => {             phInstance.exit();         })     })     .catch(error => {         phInstance.exit();     });

PhantomJS遇到的坑也不少,主要是環境問題:

1.沒截圖生成

開發:在mac上和windows上生成截圖正常,部署到測試環境后不能生成截圖,打印PhantomJS日志,沒有明確的報錯信息。linux下權限問題?

查看PhantomJS和目錄權限,PhantomJS沒有寫權限,修復權限問題,圖片仍然不能生成。

開發:字母命名的截圖正常生成,不支持圖片文件名包含數字?

一番驗證,截圖名包含數字phantomjs-node不能正常生成圖片文件。

2.截圖空白

開發:顏色和圖案均能夠渲染到截圖中,只有文字不能渲染,字體有問題?

確認測試機中字體目錄為空,更新字體,文字終于能正常渲染到截圖中。

3.截圖模糊

又是模糊問題…

css使用相對rem單位,PhantomJS截圖是設置縮放參數:

//css
html{font-size: 100px;}
.owner_avatar{width:.30rem;height: .30rem;border-radius: .30rem;margin-right: .10rem;}
.events_img{width: .50rem;height:.50rem;}
//phantomjs縮放處理
page.property('viewportSize',{width:828,height:736});
page.property('zoomFactor',2)
page.property('content',htm);
4.截圖加載慢

模糊問題設置2倍圖后,圖片大小暴漲到6M+,導致加載慢,設置截圖質量:

page.render(fileName,{quality:85}).then((err) => {
    phInstance.exit();
})
5.截圖慢

PhantomJS生成一個最簡單的截圖,耗時2S左右,這個速度顯然是不能接受的,暫時沒找到比較好的優化方式。

node canvas

node canvas擴展了canvas API以提供與節點的接口,例如流式傳輸PNG數據,轉換為Buffer實例等,更多介紹可以去node canvas官網查看。

node canvas的環境搭建比較麻煩,依賴庫與PhantomJS類似,這里就不列舉了。

繪制圖片的核心代碼:

const { createCanvas, loadImage } = require('canvas');
const canvas = createCanvas(200, 200);
const ctx = canvas.getContext('2d');
ctx.font = '30px';
ctx.fillText('test', 50, 100);
loadImage('test.jpg').then((image) => {
  ctx.drawImage(image, 0, 0, 70, 70);
})

node canvas與下面imagemagick的方案對比,imagemagick的性能更好,node canvas沒再深入只實現了簡單demo,踩坑不多。

ImageMagick 與 GraphicsMagick

ImageMagick是一套功能強大、穩定而且免費的工具集和開發包,可以用來讀、寫和處理超過90種的圖片文件,包括流行的TIFF、JPEG、GIF、 PNG、PDF以及PhotoCD等格式。

ImageMagick可以根據web應用程序的需要動態生成圖片, 還可以對一個(或一組)圖片進行改變大小、旋轉、銳化、減色或增加特效等操作,并將操作的結果以相同格式或其它格式保存,對圖片的操作,即可以通過命令行進行,也可以用C/C++、Perl、Java、PHP、Python或Ruby編程來完成。更多詳情可在ImageMagick官網查看。

GraphicsMagick是從 ImageMagick 5.5.2 分支出來的,據說它變得更穩定和優秀,更多詳情可在GraphicsMagick官網查看。

看起來GraphicsMagick是更好的選擇,但是由于node gm這個庫沒有實現GraphicsMagick的半透明和圓角支持,而且針對專輯的大事件長圖做了一些性能對比兩者差異不大,所以選擇使用ImageMagick。

node gm切換ImageMagick的方式非常簡單,只要加以下設置:

var gm = require('gm');
var imageMagick = gm.subClass({ imageMagick: true });

不可避免的,使用ImageMagick也遇到一些坑:

1.半透明遮罩

設計:專輯封面背景使用白透明遮罩,遮罩的顏色根據封面圖來定,深色封面圖用白色文字,淺色封面圖用黑色文字。

開發:OK,先canvas獲取封面圖顏色信息,再判斷顏色深淺

//RGB與YUV互轉,Y>=128 為淺色
Y'= 0.299*R' + 0.587*G' + 0.114*B'
U'= -0.147*R' - 0.289*G' + 0.436*B' = 0.492*(B'- Y')
V'= 0.615*R' - 0.515*G' - 0.100*B' = 0.877*(R'- Y')
R' = Y' + 1.140*V'
G' = Y' - 0.394*U' - 0.581*V'
B' = Y' + 2.032*U'
//ImageMagick設置透明色
.fill("rgba(0,0,0,.5)")
2.頭像圓角

設計:這些頭像要用圓角哦。

開發:OK(還好ImageMagick支持圓角)

.fill("avatar.jpg")
.drawCircle(80,120,30,120)

ImageMagick圓角圖片實現方式與canvas類似,畫一個圓,然后用頭像圖片去填充來實現頭像圓角。

3.昵稱emoji表情

ImageMagick繪制昵稱中的表情圖比較麻煩,使用支持emoji的字體,嘗試過Twitter的彩色emoji字體,但是ImageMagick有BUG,不能還原為彩色的。

最終解決方案:

1)使用等寬字體,方便計算精確的emoji位置

2)ImageMagick繪制昵稱中的表情圖片

.draw("image Over " + size + " " + url)

ImageMagick性能優化:

web瀏覽器端怎么實現

ImageMagick生成單張圖片耗時100ms左右,但是并發請求多了平均耗時就暴漲到3S+,這個速度顯然是不能接受的,經過一番優化后將平均耗時降到1S左右,主要優化點如下:

1.gm代碼拼接,VM中執行

多次調用gm多次操作圖片,嚴重影響性能,將圖片操作代碼拼接成字符串,在VM中執行,只調用一次gm,核心代碼如下:

let sandbox = {
    gm : imageMagick,
    start : Date.now()
}
//計算圖片高度
let offset = getOffset();
let qrcodeStr = getQrcodeStr();
let titleStr = (function(){
    return [
        '.fontSize(24)',
        '.fill("gray")',
        '.drawText(164,152,"我是標題")'
    ];
})();
let str = 'gm(828,'+ offset.height +',"#fff").font("'+ FONTS +'",48)'+ titleStr + qrcodeStr +'.quality(90).write("test.jpg",function(err){console.log(err || Date.now() - start)})';
let script = new vm.Script(str);
let context = vm.createContext(sandbox);
script.runInContext(context);
2.mpc格式

mpc是ImageMagick提供的一種持久高速緩存格式,減少對圖像格式進行解碼和編碼像素的開銷。

mpc生成兩個文件:

1)一個擴展名.mpc保留了與圖像或圖像序列相關的所有屬性(例如寬度,高度,色彩空間等)。

2)一個擴展名.cache,是本地原始格式的像素緩存。

讀取mpc圖像文件時,ImageMagick讀取圖像屬性,并將內存映射到磁盤上的像素緩存,無需解碼圖像像素,不過mpc的文件大小比其他圖像格式大。

mpc圖像文件適用于一次寫入,多次讀取模式,使用mpc將圖像直接映射到內存,而不是每次重新讀取和解壓源圖像。

3.Q8版本

ImageMagick Q16版本允許在不縮放的情況下讀寫16位圖像,但像素緩存消耗的資源是Q8版本的兩倍,Q8版本的執行速度通常比Q16版本要快。

像素緩存消耗 = 寬度*高度*位深度/ 8 *通道
Q8位深 = 8 
Q16位深 = 16
通道 = 紅 + 綠 + 藍 + 阿爾法強度

關于“web瀏覽器端怎么實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

web
AI

天津市| 孟州市| 张北县| 稷山县| 马山县| 岳西县| 家居| 聊城市| 吐鲁番市| 贵港市| 龙陵县| 商河县| 元阳县| 华池县| 原平市| 神农架林区| 澳门| 县级市| 睢宁县| 措美县| 海门市| 同仁县| 隆林| 塘沽区| 河西区| 麻阳| 新巴尔虎左旗| 名山县| 都昌县| 绍兴县| 阳城县| 班玛县| 镇平县| 涿鹿县| 万州区| 宁城县| 灵寿县| 庐江县| 长武县| 高阳县| 东至县|