千家信息网

web浏览器端怎么实现

发表于:2024-11-26 作者:千家信息网编辑
千家信息网最后更新 2024年11月26日,这篇文章主要介绍"web浏览器端怎么实现"的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇"web浏览器端怎么实现"文章能帮助大家解决问题。浏览器端实现方案开发:大
千家信息网最后更新 2024年11月26日web浏览器端怎么实现

这篇文章主要介绍"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倍的大小。

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方案的尝试:

//要转成图片的domlet htm = '
这里是页面内容...
';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 = [             '',             '',             '',                 '',             '',             '',                 '
'+ new Date() +'
', '', '' ].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截图是设置缩放参数:

//csshtml{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性能优化:

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浏览器端怎么实现"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注行业资讯频道,小编每天都会为大家更新不同的知识点。

图片 截图 问题 方案 生成 浏览器 浏览 开发 图像 格式 代码 属性 文件 支持 像素 圆角 字体 高度 封面 更多 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 ipv6 dhcp服务器 数据库中平凡依赖是什么原因 中秋节网络安全手抄报 数据库提取字段数值的前几位 期权系统软件开发商排名 南京智铭网络技术有限公司 成都应用软件开发价位 24小时网络安全态势 智能化软件开发设计 批发业可以做软件开发吗 数据库用户名与数据库 常见的计算机网络安全措施有 第七史诗无法连接到服务器 修改数据库用什么软件 计算机网络技术上下游专业 网络安全预警机制怎么做表格 虹口区品质软件开发销售电话 金蝶数据库安装最新官方版 软件开发是现代服务业 网络安全和信息化局是干什么的 南沙区软件开发工程师 靖江自动化网络技术参考价格 数据库编程和c语言编程的比较 大学生软件开发经验 邯郸网络安全工程师招聘 拓客网络技术有限公司 郑州股票软件开发公司 多媒体服务器下载 软件开发起名字 王者服务器卡炸
0