关于图片处理:楠姐技术漫话图计算的那些事-京东云技术团队

不晓得大家在平时的工作中 有没有据说过“图计算”这个名词 但大家肯定在各工作汇报,技术分享中据说过“智能化”,“人工智能”这样的字眼 而咱们明天要唠的这个图计算 就是人工智能畛域内近几年煊赫一时的前沿宠儿 也是咱们风控反欺诈中罕用的“大杀器” 在理解图计算之前 首先得理解什么是“图” 咱们明天所说的图 其实是用于示意对象之间关联关系的一种数据结构 具备很强的抽象性和灵活性 在构造和语义等方面具备很强的示意能力 正是因为图构造丰盛的表现力 在现实生活中有很多能够示意为“图”的例子 例如社交网络、道路网、金融交易等 研发或者算法相干的小伙伴们都晓得 咱们罕用的机器学习和深度学习算法 大多都是用于解决一些规整、有序,或者结构化的数据 比方矩阵、图片、文本、序列等 且所解决的数据都是被假如是独立同散布的 然而图上的节点都是天然相连 这也就表明节点之间不是独立的 此时,明天咱们要提的图计算就来了 它的外围正是为了将数据建模为图构造 并解决如何将问题解法转化为图构造上的计算问题 当算法工作波及到多个体之间关联剖析时 图计算往往可能使得问题能很天然地示意为一系列对图构造的操作和计算 然而图计算所须要解决的问题多种多样 难以使用一套计算模式解决所有的问题 接下来咱们就来零碎地盘一盘 对于图计算的那些事儿 ---★--- 比方,借助边是否有方向 图能够分为有向图和无向图 借助边是否有权重 图还能分为有权图和无权图 借助图中的点和边是否具备多种类型 图又能分为同构图和异构图 还有,借助图构造和图信息是否随工夫变动 图能分为动态图和动态图 “度”和“街坊” 是波及图节点的两个重要概念 节点的“度”是指的与之相连的节点个数 如果是有向图,还会辨别“入度”、“出度” 节点的“街坊”则是指与之相连的其余节点 对于图的示意 还有几个根底概念是不得不提的 一个是“邻接矩阵” 用于量化示意节点之间的边关系 还有就是“节点特色”和“边特色” 用于表征节点和边的特有数值属性 无论如许简单的图算法模型 都是基于这些基本概念进行的 提一个对于图的最根本的问题——节点表征问题 就是如何基于以上的图的信息和属性 对图中的节点或者边进行量化示意 在CV和NLP工作中 ...

May 17, 2023 · 2 min · jiezi

关于图片处理:京喜APP-图片库优化-京东云技术团队

作者:京东批发 何骁 介绍京喜APP晚期开发次要是疾速原生化迭代代替原有H5,进步用户体验,在这期间也积攒了不少性能问题。之后咱们开始进行一些性能优化相干的工作,本文次要是介绍京喜图片库相干优化策略以及对于图片相干的一些关联常识。 图片性能问题作为电商APP,图片在各个业务场景被大量应用。咱们须要做到尽可能升高网络耗费/内存耗费/硬盘耗费,同时不升高图片品质,进步图片加载速度,给用户带来更好的应用体验。基于这些性能指标,咱们也通过初步性能评估梳理出了一些性能问题: 图片加载慢/流量耗费高图片链接次要由后盾接口下发,下发图片格局和尺寸由每个业务后盾指定。局部业务没有应用更小的图片格式比方WebP,或图片尺寸过大,都会使图片过大导致网络耗费高。特地是网络状况不佳的场景,图片加载过慢给用户带来不好的体验。同时也会导致更多的I/O读写和解码耗时,造成更多的电量耗费。 图片内存占用高通过初步的APP内存应用评估,图片内存耗费占APP总内存耗费的比例最高,特地是大尺寸图片会占用很多内存。一方面APP占用太高内存退到后盾容易被零碎杀死,导致下次关上重新启动影响体验。另一方面APP大量应用内存,容易被零碎杀死产生OOM。特地是咱们目前有大量的低端设施用户,设施内存绝对比拟低。 优化方向基于下面剖析出的一些性能问题,咱们对图片框架进行了整体重构优化。一方面是升高图片网络传输,进步图片加载速度。另一方面是缩小图片内存耗费。 最小化网络传输京东图片服务器提供了多种解决性能,例如图片格局转换,图片降质,图片缩放,图片圆角等性能。这些性能通过在图片URL中增加特定参数实现,图片服务器会依据参数设置提前将图片解决实现并保留到CDN服务器。咱们能够通过增加图片解决参数,缩小图片传输大小。 尽管后盾能够提前进行URL预处理,下发已增加过图片参数的图片URL。然而因为对接后盾业务很多,每个业务图片参数设置差别很大无奈对立,而且可能会造成性能影响,例如没有应用webP图片格式,下发太大的图片尺寸。同时思考到推动各业务后盾批改老本也很高,并且前端机型多,不同机型须要应用不同的图片尺寸。另外也不不便灰度降级性能,后续性能批改也不不便。所以在客户端进行图片URL预处理是更好的形式,能够对立管制,也不便之后性能更新。 图片URL预处理 图片库在网络图片加载前,检测是否是京东域名的图片URL。如果域名匹配,图片框架先对图片URL进行预处理,预处理包含域名对立,增加缩放参数,增加webP参数,增加降质参数的形式缩小图片网络传输大小。 提醒:因为后盾返回的图片URL可能会带有一部分图片解决参数,例如https://img11.360buyimg.com/img/pingou-head/25.jpg!webp,间接追加图片参数可能会导致图片解决参数不失效,或格局谬误导致加载失败。所以转换时会先将所有图片参数提前计算出来,之后一起解决,防止增加反复参数。域名对立目前图片服务器提供了多个图片域名可应用,例如m.360buyimg.com,img10.360buyimg.com等多个域名。m.360buyimg.com次要提供给挪动端应用。然而因为对接了各种业务后盾,导致接口会下发不同的域名图片。图片应用不同域名可能会导致以下问题: 不利于缓存复用- 图片框架通常默认以URL字符串生成图片缓存key,不同域名导致生成不同的缓存key。硬盘缓存无奈复用会导致图片反复下载,内存缓存无奈复用导致同样的图片占用多份内存。不利于HTTP/2连贯复用- 大部分界面图片比拟多,很多场景都会同时加载多张图片,特地是首屏通常会加载几十张图片。当加载多个图片时,每个域名都须要从新建设HTTPS连贯,经验DNS解析/TCP连贯/TLS握手过程(目前一次HTTPS申请创立过程大略耗时50-150ms)。如果利用HTTP/2链接复用就只须要创立一次HTTPS申请,之后的图片申请能够缩小这部分的耗时。所以在预处理时,如果是京东域名的图片,将图片URL域名对立替换为m.360buyimg.com。 追加图片参数图片缩放 很多业务后盾返回的原始图片URL的size都比客户端理论显示的size要大。一方面导致应用更多的网络流量造成节约。另一方面会导致占用更多内存。同时因为图片size和理论显示size不统一导致像素不对齐,GPU须要做额定的插值解决,也会肯定的影响渲染性能。所以咱们通过增加缩放参数的形式,指定图片服务器下发更小和更匹配理论显示size的图片尺寸。 动静scale计算尺寸 因为iOS设施次要应用2x/3x的分辨率,所以业务方应用API时须要传入对应的ptsize大小,图片库外部依据设施的scale进行动静计算出实在的像素宽高。 提醒:android设施因为屏幕差别比拟大,更适宜应用固定的scale。太多的图片尺寸不利于CDN缓存,无缓存的时候须要对图片进行相干参数解决,图片解决自身是耗时操作。Scale降级 低端机降级- 对于局部3xscale的低端设施,因为机器自身内存比拟低,应用3x分辨率计算出来的图片像素宽高比较大,会造成更多的内存耗费以及解码/渲染更多的性能耗费。所以对于宽高超过肯定要求的图片,降级到应用2x分辨率来计算像素宽高,缩小设施性能耗费。iPad降级- 因为目前APP并没有针对iPad做特定优化,所以iPad设施下默认是放大显示。这会导致在iPad下图片尺寸计算出来特地大。所以也是针对iPad图片尺寸做了特定限度,避免下发图片尺寸过大。大图片降级- 失常状况下图片宽/高不应该超过屏幕宽/高。为了避免局部业务应用过大的图片size,所以增加了一个限度,最终生成的图片像素尺寸不能超过屏幕宽/高。降质 图片服务器反对0-100的图片品质参数设置,通过升高图片品质能够缩小图片大小,然而品质升高太多也会影响图片的观看体验。咱们将图片品质参数设置为q70,指定图片服务器下发70%品质的图片。对于大部分业务,一方面能够大幅缩小图片下载大小,同时也能够保障观看体验。通过增加图片降质参数至多能够缩小30-40%的图片大小。 应用WebP 依照Google官网的数据,与PNG相比,WebP无损图像的字节数要少26%。WebP有损图像比同类JPG图像字节数少25-34%。图片服务器反对转换webP格局,能够缩小图片大小。针对png/jpg图片格式,增加webP参数,指定图片服务器下发webp格局。尽管webP相比png/jpg图片解码须要更长时间,但绝对网络传输速度晋升还是很大。 提醒:因为目前图片服务器并不反对GIF转webP,GIF并没有做解决。URL预处理缓存增加轻量缓存,进步URL转换性能。因为URL转换自身有肯定的耗时,而且单个图片URL可能会屡次加载/屡次转换。转换后的URL会间接保留到缓存中,下次应用能够间接返回。缓存key由URL+相干图片转换参数拼接组成。 图片API设计图片解决参数通过options设置,默认应用q70图片品质以及webP格局。业务方在调用加载图片办法时传入,上面是iOS端的API: imageView6.jx.setImage(url: URL(string: "https://img11.360buyimg.com/img/pingou-head/25.jpg"), placeholder: nil, options: [.imageSize(CGSize(width: 40, height: 40))])磁盘缓存优化图片缓存查找优化设置图片不同的size参数会导致更多的图片下载和磁盘缓存,例如同样一张图片100px、200px、300px尺寸因为URL不同会下载3次,同时缓存也无奈不同。因为图片库通常默认应用URL作为图片缓存key,所以咱们须要针对图片缓存key查找图片进行优化革新。简略来讲,雷同的图片小size的图片能够间接复用更大size的缓存,这样当存在更大尺寸图片时,能够防止图片间接下载并且复用磁盘缓存。 升高图片内存耗费png/jpg等图片格式在显示之前都须要通过解码生成一张位图,之后依据位图创立纹理传给GPU做渲染。一张位图的内存耗费大略是像素宽x像素高x位深。通常图片应用的是RGBA,位深为32位。一张500px_500px的大略1MB内存。对于GIF图片因为自身有多帧,所以最终的内存耗费为单帧内存x帧数。 咱们的优化方向一方面是通过图片缩放的形式,缩小图片位图的内存耗费。另一方面限度图片缓存下限防止缓存应用过高。 图片缩放通过下面URL预处理过程让图片服务器下发更小的图片格式,曾经升高了一部分内存。然而URL预处理只解决了jd域名的jpg/png图片,对于GIF或京东域名外的图片没有解决,包含一部分URL转换后加载失败的图片。所以对于这部分图片,咱们会在端侧做图片缩放的解决,升高内存耗费。例如一张300px_300px蕴含100帧的GIF图片,理论显示区域只有50px_50px,优化后总内存耗费可从30MB+内存升高到3MB。 GIF动静帧率播放之前依据线上监控数据发现,局部页面场景偶然会配置尺寸大/帧数多的GIF图片,导致内存占用极高。例如一张500x400px播放200帧的GIF图片会占用100MB+内存耗费。所以针对这种场景,咱们针对GIF做了减帧播放革新。当GIF图片总内存耗费大于一定量级时(例如图片内存缓存上线的20%),将GIF播放的帧数适当缩小,每一帧的播放工夫减少,这样能够将内存管制在肯定范畴之内。 提醒:这里也能够通过 GIF 图片缓存 Buffer 管制内存总量,然而会导致更频繁的解码造成更多的 CPU 耗费。图片内存缓存下限图片缓存的设计目标是缩小图片解码耗费。图片第一次应用的时候,将图片进行解码后的位图保留在内存中,这样能够防止下次应用时防止反复解码。尽管图片内存高能够尽量避免图片反复解码,然而占用太高内存也会导致APP后盾被零碎杀掉或产生OOM等问题。所以咱们应该将内存缓存管制在肯定范畴内。 例如iOS的第三方图片库SDWebImage/Kingfisher默认都应用零碎库NSCache来实现内存缓存。尽管NSCache会在设施内存缓和时回收内存,然而默认并不限度可保留内存最大字节数,所以在设施内存可用的状况下内存能够始终减少。所以通过设置图片缓存下限,避免图片缓存占用太高内存。图片缓存定义了一个默认的初始值下限,之后对于3x大屏幕设施和高端设施(内存比拟高),适当减少更多内存下限。 优化成绩 其余收益 域名对立- 缩小了10%+的反复图片下载和内存耗费。同时缩小之前多域名图片加载时反复创立HTTPS申请的过程,缩小图片加载工夫。其余策略加载异样解决因为大量图片通过URL预处理转换后,可能会存在图片不存在的异样场景导致加载失败。所以当产生图片加载失败时,咱们还是须要加载原始图片URL。然而这里须要屏蔽一些非凡的加载谬误,防止非必要的加载,例如无网络/网络超时/被动勾销加载等谬误。之后会将谬误图片URL上报到后盾,不便之后调整URL转换策略,也能够发现一部分谬误的图片URL推动业务批改。同时将这部分连贯退出到谬误连贯缓存中,防止下次反复执行预处理和反复上报。 线上配置目前存在的一些性能,例如URL预处理/对立域名/WebP应用等性能,都增加了线上配置,不便灰度/降级。一在呈现问题时能够降级某些性能,新性能上线时也能够进行灰度测试。 大图检测须要有一个机制及时发现图片不符合规范的问题。一方面咱们通过线上灰度检测的形式,当发现大图片时会进行上报,后续推动业务方进行优化。另一方面咱们在日常测试阶段,会开启Debug检测工具,当检测到大图片时,通过图片翻转/高亮背景色彩的形式揭示业务开发同学进行优化。 Flutter图片库优化目前京喜APP有10+个二级界面是基于Flutter开发,所以咱们也针对Flutter图片加载做了一些优化。 对接原生图片库因为Flutter框架自带图片库只提供内存图片缓存,并不反对硬盘缓存,所以会导致图片反复下载。所以咱们通过重写ImageProvider,当加载网络图片时,通过Channel调用原生图片库,原生图片库下载图片到本地磁盘后,返回图片文件目录。之后Flutter通过文件目录加载解码图片显示。这样一方面能够利用原生图片库相干优化能力,同时也能够复用图片硬盘缓存防止反复下载。 缩小内存耗费应用Image组件时,通过设置cacheHeight/cacheWidth,将图片解码为置顶像素宽高的位图尺寸,缩小内存耗费。同时因为Flutter内存耗费绝对原生更高,所以在Flutter界面敞开时,通过调用imageCache办法革除图片内存耗费升高内存耗费。 GIF优化动画优化- 因为通常应用Flutter都是混合栈的机制,原生和Flutter界面在页面导航中互相跳转。所以当Flutter界面存在GIF图片时,跳转到原生当前GIF动画还会始终执行。所以咱们通过在Image组件内监听Flutter engine发送的生命周期告诉,当Flutter界面不在栈顶时,进行GIF动画执行,缩小内存和CPU耗费。缩小解码次数- Flutter框架外部对GIF渲染的解决形式,在屏幕每一帧判断以后须要显示的GIF帧,之后对该GIF帧进行解码之后渲染。因为并不会把解码过的帧保留,所以会导致频繁解码导致内存稳定大。通过优化,对曾经解码过的帧进行保留,防止反复解码的耗费,同时防止内存的稳定。优化前内存稳定很显著 优化后内存倾于安稳 提醒:保留每一帧也会导致更多的内存耗费。目前APP中通常是小尺寸的GIF所以整体可控。能够思考设置缓冲区下限来管制缓存的图片帧数防止内存过高。后续优化方向更优的缓存算法优先移除最大内存- iOS零碎NSCache实现。通过设置最大内存数,当内存不足时优先移除最大的值。LRU缓存- 优先淘汰最久未应用的图片内存。对于很多二级界面的场景,用户关上界面后并不会再次关上。然而因为这些图片缓存是最初应用,所以革除内存时也会最初移除,然而在这种场景下就不太适合。界面栈治理- 当界面敞开时将该界面的所有的图片内存移除,然而对于常常会关上的界面会导致频繁图片编解码也不太适合。所以针对不同的业务场景应用不同的回收形式可能更加适合: ...

May 11, 2023 · 1 min · jiezi

关于图片处理:临时存储

February 20, 2023 · 0 min · jiezi

关于图片处理:智能AI技术图像编辑Luminar-Neo中文激活

图像编辑哪款软件好用?Luminar Neo中文激活版是个不错的智能编辑工具,利用最新ai技术,高效智能的为您的编辑提供助力!应用咱们全新的疾速外围引擎放慢您的编辑工作流程。它基于 Skylum 开发的独特技术并在模块零碎上运行,这意味着当初能够独自优化应用程序的不同局部以获得最佳成果。得益于独立的模块引擎,Luminar Neo 将更频繁地更新。Luminar Neo 具备更灵便的编辑过程,这意味着编辑照片所需的内存更少。新引擎对内存应用进行了许多小的后盾优化,进步了应用程序外部所有过程的速度,从上传到利用编辑成果、应用图层和导出。 应用新的从新照明选项彻底改变您的照片。Luminar Neo 剖析每张图像以辨认场景的深度及其主题,从而对曝光和色调进行独特的管制。 Luminar Neo破解版点此

October 9, 2022 · 1 min · jiezi

关于图片处理:mac图片放大Topaz-Gigapixel-AI

Mac图片无损放大软件哪款好用?Topaz Gigapixel AI for Mac是Mac上一款图片无损放大软件,应用AI人工智能来扩大图像。topaz gigapixel ai为用户提供无损放大的图像,同时还减少了天然细节损失解决,能够放大和填充图像调整产品,而不使图片失真! Topaz Gigapixel AI for Mac(图片无损放大软件)

August 11, 2022 · 1 min · jiezi

关于图片处理:Day-15100-Fabricjs-实现图片对比度控制

(一)需要在标注图片时,须要管制对于同一图片的对比度,所以须要实现对于图片对比度的管制。 接下来是需要廓清 失常图片 1、对比度对比度设置为0.25时 2、对比度设置为0.5时 3、对比度设置为-0.5时 (二)阐明定义阐明图像对比度指的是一幅图像中明暗区域最亮的白和最暗的黑之间不同亮度层级的测量,即指一幅图像灰度反差的大小。差别范畴越大代表比照越大,差别范畴越小代表比照越小,好的对比率120:1就可容易地显示活泼、丰盛的色调,当对比率高达300:1时,便可反对各阶的色彩。 差别范畴越大代表比照越大,差别范畴越小代表比照越小,好的对比率120:1就可容易地显示活泼、丰盛的色调,当对比率高达300:1时,便可反对各阶的色彩。但对比率蒙受和亮度雷同的窘境,现今尚无一套无效又公正的规范来掂量对比率,所以最好的辨识形式还是依附使用者眼睛。 (三)代码1、须要装置Fabricnpm install fabric --save 2、代码import React from 'react';import { fabric } from "fabric";class Fabric extends React.Component { constructor(props) { super(props); } componentDidMount(){ const canvas = new fabric.Canvas('canvas'); console.log('canvas',canvas); // 图片 const imgEl = document.createElement('img') imgEl.crossOrigin = 'Anonymous' // 让图片能让所有人存取 imgEl.src = 'https://2.bp.blogspot.com/-H3JXh2cIKHs/WuwLvnz19cI/AAAAAAAAMXs/-qySdr5zEcc-kcLC4arf5m5H3F_trN7sgCK4BGAYYCw/s1600/kristopher-roller-110203-unsplash-m.jpg' imgEl.onload = () => { const image = new fabric.Image(imgEl, { scaleX: 0.5, scaleY: 0.5, angle: 0, // angle: 15, top: 0, left: 0 }) // 将 filters 实例 push 进 filters 外头 image.filters.push(new fabric.Image.filters.Contrast({contrast: 0.2})) // 这边须要重整所有的滤镜成果 image.applyFilters() canvas.add(image) } }; render() { return <div> <h1>Learn, {this.props.name}</h1> <canvas id="canvas" width="666" height="600"></canvas> </div>; }}export default Fabric;参考链接https://github.com/fabricjs/f... ...

December 16, 2021 · 1 min · jiezi

使用canvas一步步实现图片打码功能

使用canvas一步步实现图片打码功能原文地址https://github.com/MY729/front-common-funtion/blob/master/picture-code-demo/README.md 预览地址https://my729.github.io/front-common-funtion/picture-code-demo/picture-code.html 准备工作demo 基于 vue + elelment-ui 首先创建一个html文件, 并引入 vue 和 elelment-ui(注意还有样式文件) <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <!-- elelment-ui样式 --> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"></head><body> </body><!-- 引入vue --><script src="https://cdn.jsdelivr.net/npm/vue"></script><!-- 引入element-ui --><script src="https://unpkg.com/element-ui/lib/index.js"></script></html>接下来就可以写我们的打码功能啦 实现思路创建canvas画布,并将要打码的图片绘制上去监听鼠标在图片上的点击,移动、松开事件,在canvas画布上绘制要打码的区域处理绘制的打码区域保存打码后的图片将要打码的图片绘制到canvas画布上// 初始化 绘制图片toCode (currentImg) { this.$nextTick(() => { // 获取将要绘制的canvas的父元素节点 let parentId = document.getElementById('parentId') // 初始化图片 let drawImg = new Image() drawImg.setAttribute('crossOrigin', 'anonymous') drawImg.crossOrigin = 'Anonymous' drawImg.src = currentImg // 创建canvas元素并添加到父节点中 let addCanvas = document.createElement('canvas') parentId.appendChild(addCanvas) let canvas = parentId.lastElementChild canvas.id = 'imgCanvas' if (canvas.getContext) { let ctx = canvas.getContext('2d') // 绘制图片 drawImg.onload = function () { canvas.width = 720 canvas.height = 500 ctx.drawImage(drawImg, 0, 0, 720, 500) } } })}点击打码按钮,绘制打码区域思路: ...

June 17, 2019 · 5 min · jiezi

Web 性能优化: 图片优化让网站大小减少 62%

这是 Web 性能优化的第二篇,上一篇在下面看点击查看:Web 性能优化: 使用 Webpack 分离数据的正确方法图像是web上提供的最基本的内容类型之一。他们说一张图片胜过千言万语。但是如果你不小心的话,图片大小有时高达几十兆。因此,虽然网络图像需要清晰明快,但它们尺寸可以缩小压缩的,使用加载时间保持在可接受的水平。在我的网站上,我注意到我的主页的页面大小 超过了 1.1MB,图片占了约88%,我还注意到我提供的图像比它们需要的大(在分辨率方面),显然,还有很多改进的空间。我开始阅读 Addy Osmani 的优秀 Essential Image Optimization电子书,并开始在我的网站上按照他们的建议做了一些图片的优化。,然后再对响应式图像进行了一些研究并应用了它。这使得页面大小减少到 445kb,约 62% !什么是图像压缩?压缩图像就是在图片保持在可接受的清晰度范围内同时减少文件大小,我使用 imagemin 来压缩站点上的图像。要使用 imagemin,确保你已经安装了 Node.js,然后打开一个终端窗口,cd 进入项目,并运行以下命令:npm install imagemin然后创建一个名为 imagemin.js 的新文件,写入下面的内容:const imagemin = require(‘imagemin’);const PNGImages = ‘assets/images/.png’;const JPEGImages = ‘assets/images/.jpg’;const output = ‘build/images’;你可以根据自己的需要更改 PNGImages、JPEGImages 和 output 的值,以符合你的项目结构。此外要执行图片压缩,还需要根据要压缩的图像类型安装对应的插件。JPEG/JPGJPG 的优点JPG 最大的特点是 有损压缩。这种高效的压缩算法使它成为了一种非常轻巧的图片格式。另一方面,即使被称为“有损”压缩,JPG的压缩方式仍然是一种高质量的压缩方式:当我们把图片体积压缩至原有体积的 50% 以下时,JPG 仍然可以保持住 60% 的品质。此外,JPG 格式以 24 位存储单个图,可以呈现多达 1600 万种颜色,足以应对大多数场景下对色彩的要求,这一点决定了它压缩前后的质量损耗并不容易被我们人类的肉眼所察觉——前提是你用对了业务场景。JPG 使用场景JPG 适用于呈现色彩丰富的图片,在我们日常开发中,JPG 图片经常作为大的背景图、轮播图或 Banner 图出现。JPG 的缺陷有损压缩在上文所展示的轮播图上确实很难露出马脚,但当它处理矢量图形和 Logo 等线条感较强、颜色对比强烈的图像时,人为压缩导致的图片模糊会相当明显。此外,JPEG 图像不支持透明度处理,透明图片需要召唤 PNG 来呈现。使用 MozJPEG 压缩 jpeg这里使用 Mozilla 的 MozJPEG 工具,该工具可以通过 imagemin-mozjpeg 作为 Imagemin 插件使用。你可以通过运行以下命令来安装它:npm install imagemin-mozjpeg然后将以下内容添加到的 imagemin.js 中:const imageminMozjpeg = require(‘imagemin-mozjpeg’);const optimiseJPEGImages = () => imagemin([JPEGImages], output, { plugins: [ imageminMozjpeg({ quality: 70, }), ] });optimiseJPEGImages() .catch(error => console.log(error));可以通过在终端中运行 node imagemin.js 来运行脚本。这将处理所有JPEG图像,并将优化后的版本放 build/images 文件夹中。我发现将 quality 设置为 70 在大多数情况下可以产生足够清晰的图像,但你的项目需求可能不同,可以自行设置合适的值。默认情况下,MozJPEG 生成渐进式 jpeg,这会导致图像从低分辨率逐渐加载到高分辨率,直到图片完全加载为止。由于它们的编码方式,它们也比原始的 jpeg 略小。你可以使用 Sindre Sorhus 提供的这个命令行工具来检查JPEG图像是否是渐进式的。Addy Osmani 已经很好地总结了使用渐进式 jpeg 的优缺点。对我来说,我觉得利大于弊,所以我坚持使用默认设置。如果你更喜欢使用原始的jpeg,可以在 options 对象中将 progressive 设置为 false。另外,请确保 imagemin-mozjpeg 版本的变化,请重新查看对应文档。PNG (PNG-8 与 PNG-24)PNG 的优缺点PNG(可移植网络图形格式)是一种无损压缩的高保真的图片格式。8 和 24,这里都是二进制数的位数。按照我们前置知识里提到的对应关系,8 位的 PNG 最多支持 256 种颜色,而 24 位的可以呈现约 1600 万种颜色。PNG 图片具有比 JPG 更强的色彩表现力,对线条的处理更加细腻,对透明度有良好的支持。它弥补了上文我们提到的 JPG 的局限性,唯一的缺点就是 体积太大。PNG 应用场景前面我们提到,复杂的、色彩层次丰富的图片,用 PNG 来处理的话,成本会比较高,我们一般会交给 JPG 去存储。考虑到 PNG 在处理线条和颜色对比度方面的优势,我们主要用它来呈现小的 Logo、颜色简单且对比强烈的图片或背景等。使用 pngquant 优化 PNG 图像pngquant 是我优化PNG图像的首选工具,你可以通过 imagemin-pngquant 使用它:npm install imagemin-pngquant然后将以下内容添加到 imagemin.js 文件中:const imageminPngquant = require(‘imagemin-pngquant’);const optimisePNGImages = () => imagemin([PNGImages], output, { plugins: [ imageminPngquant({ quality: ‘65-80’ }) ], });optimiseJPEGImages() .then(() => optimisePNGImages()) .catch(error => console.log(error));我发现将 quality 设置为 65-80 可以在文件大小和图像质量之间较好的折衷方案。有了这些设置,我可以得到一个屏幕截图,我的网站从 913kb 到 187kb,没有任何明显的视觉损失,惊人的79% 的降幅!这是两个文件。看一看,自己判断一下:原图(913kb)优化后的图像(187kb)WebPWebP 的优点WebP 像 JPEG 一样对细节丰富的图片信手拈来,像 PNG 一样支持透明,像 GIF 一样可以显示动态图片——它集多种图片文件格式的优点于一身。WebP 的官方介绍对这一点有着更权威的阐述:与 PNG 相比,WebP 无损图像的尺寸缩小了 26%。在等效的 SSIM 质量指数下,WebP 有损图像比同类 JPEG 图像小25-34%。 无损 WebP 支持透明度(也称为 alpha 通道),仅需 22% 的额外字节。对于有损 RGB 压缩可接受的情况,有损 WebP 也支持透明度,与 PNG 相比,通常提供 3 倍的文件大小。将 WebP 图像提供给支持它们的浏览器WebP 是谷歌引入的一种相对较新的格式,它的目标是通过以无损和有损格式编码图像来提供更小的文件大小,使其成为 JPEG 和 PNG 的一个很好的替代方案。WebP 图像的清晰度通常可以与 JPEG 和 PNG相提并论,而且文件大小要小得多。例如,当我将屏幕截图从上面转换到 WebP 时,我得到了一个 88kb 的文件,其质量与 913kb 的原始图像相当,减少了90% !看看这三张图片,你能说出区别吗?原图PNG (913kb)优化PNG图像(187kb)WebP图像(88kb,可在Chrome或Opera浏览器中浏览)就我个人而言,我认为视觉效果是可以比较的,而且节省下来的大小是不容忽视的。既然我们已经认识到在可能的情况下使用WebP格式是有价值的,那么很重要的一点是—它不能完全替代 JPEG 和 PNG,因为浏览器对 WebP 支持并不普遍。在撰写本文时,Firefox、Safari 和 Edge 都是不支持WebP的浏览器。然而,根据 caniuse.com 的数据,全球超过70%的用户使用支持WebP的浏览器。这意味着,通过使用 WebP 图像,可以为大约 70% 的客户提供更快的 web 页面及更好的体验。安装它,运行以下命令:npm install imagemin-webp然后将以下内容添加到你的 imagemin.js 文件中:const imageminWebp = require(‘imagemin-webp’);const convertPNGToWebp = () => imagemin([PNGImages], output, { use: [ imageminWebp({ quality: 85, }), ] });const convertJPGToWebp = () => imagemin([JPGImages], output, { use: [ imageminWebp({ quality: 75, }), ] });optimiseJPEGImages() .then(() => optimisePNGImages()) .then(() => convertPNGToWebp()) .then(() => convertJPGToWebp()) .catch(error => console.log(error));我发现,将 quality 设置为 85 会生成质量与 PNG 相当但小得多的 WebP 图像。对于 jpeg,我发现将 quality 设置为 75 可以在视觉和文件大小之间取得很好的平衡。提供 HTML格式的WebP图像一旦有了 WebP 图像,可以使用以下标记将它们提供给可以使用它们的浏览器,同时向不兼容 WebP 的浏览器使用 png 或者 jpeg。<picture> <source srcset=“sample_image.webp” type=“image/webp”> <source srcset=“sample_image.jpg” type=“image/jpg”> <img src=“sample_image.jpg” alt=""></picture>使用此标记,理解 image/webp 媒体类型的浏览器将下载 Webp 图片并显示它,而其他浏览器将下载 JPEG 图片。任何不支持 <picture> 的浏览器都将跳过所有 source 标签,并加载底部 img 标签。因此,我们通过提供对所有浏览器类的支持,逐步增强了我们的页面。请注意,在所有情况下,img 标记都是实际呈现给页面的内容,因此它确实是语法的必需部分。 如果省略 img 标记,则不会渲染任何图像。<picture> 标签和其中定义的所有 source 都在那里,以便浏览器可以选择要使用的图片的路径。 选择源图像后,其 URL 将传给 img 标记,这就是显示的内容。这意味着你无需设置 <picture> 或 source 标记的样式,因为浏览器不会渲染这些标记。 因此,你可以像以前一样继续使用 img 标签进行样式设置。总结正如你所看到的,优化 web 上使用的图像的过程并不复杂,通过减少页面加载时间,可以为客户带来更好的用户体验,希望本文对你有所帮助,共进步!代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。原文:https://medium.freecodecamp.o…你的点赞是我持续分享好东西的动力,欢迎点赞!一个笨笨的码农,我的世界只能终身学习!更多内容请关注公众号《大迁世界》! ...

March 5, 2019 · 2 min · jiezi

淘宝放大镜的两种实现方法JS

啥是淘宝放大镜这个,当你的鼠标移动到左边的主图上时,右边会出现一个放大的图,暂且就把这个叫做放大镜吧。大概的做法第一种,左边一个小图,右边一个原图,当鼠标在小图上移动的时候,通过更改left和top的值来实现同步移动(原图的position属性设置为absolute)第二种,鼠标在小图上移动的时候,通过改变原图的background-position的值来同步移动。关键操作第一步,获取鼠标在小图上的位置,并且定位好跟随鼠标的方块(你应该知道是哪个方块吧。。)的位置。//e.offsetX ,offsetY是鼠标的位置//方块的left top在你的鼠标的左上方(网页左上角是原点),因此是减去一个方块的一半。 var x = e.offsetX - 方块.offsetWidth / 2; var y = e.offsetY - 方块.offsetHeight / 2; 方块.style.left = x + ‘px’; 方块.style.top = y + ‘px’;这明显是不足够的!还需要考虑极端位置/情况如果只用上面的设置,那么当你的鼠标移动到图片边缘的时候,方块有一半会出现在图片外。正确的应该是 当你的方块触碰到边缘的时候,你的方块就不能在移动了,尽管你的鼠标还在往下图中“鼠标的有效活动区域”外移动。那么得加点代码 if (x < 0) { x = 0; } if (y < 0) { y = 0; } if (x > 小图.offsetWidth - 方块.offsetWidth) { x = 小图.offsetWidth - 方块.offsetWidth; } if (y > 小图.offsetHeight - 方块.offsetHeight) { y = 小图.offsetHeight - 方块.offsetHeight; }第二步,控制大图里的left - top或者background-position //第一种方法:需要注意的是这里的left 和 top得反过来,你鼠标在小图上往下移的时候,对应的大图其实是往上移的。 //所以:大图上的left = -小图上的left * 他们的缩放倍率 大图.style.display = “block”; 大图.style.left = -x * 大图.offsetWidth / 小图.offsetWidth + ‘px’; 大图.style.top = -y * 大图.offsetHeight / 小图.offsetHeight + ‘px’; //第二种方法,这里需要注意 backgroundPosition的值是从0 - 100%的(得用百分比表示); //需要注意的是何时为百分百,从上面的极端情况判定我们可以知道 //x 是从0 到 mask.offsetWidth - rect.offsetWidth; //因此这就是0 - 100%;y同理 大图.style.display = “block”; 大图.style.backgroundPosition =${x/(mask.offsetWidth - rect.offsetWidth)*100}% ${y/(mask.offsetHeight- rect.offsetHeight)*100}%;注意事项我们上面说在小图img上绑定mousemove事件来定位方块,其实实际操作上,我们不能直接用img来绑定,而是得用一个和img一样大小遮罩层来绑定,不然在你鼠标移动的时候,图片会疯狂闪烁,疯狂!crazy!还有 就是函数节流,这个想节流就节流吧。还有个很重要的,就是右边那个显示大图的div的大小,一定得是小图上的方块大小 * 缩放倍率 的大小,如果过大,则会多出空白,过小,显示不完全。下面有代码,你可以带回家疯狂测试。再详细一点我知道我可能说的不是很详细,所以。。<!DOCTYPE html><html lang=“en”><head> <meta charset=“UTF-8”> <meta name=“viewport” content=“width=device-width, initial-scale=1.0”> <meta http-equiv=“X-UA-Compatible” content=“ie=edge”> <title>tb放大镜</title> <style> .small-box { position: relative; height: 300px; } .small-pic { width: auto; height: 300px; } .mask { width: 526px; position: absolute; top: 0; left: 0; z-index: 1; height: 100%; cursor: crosshair; } .rect { position: absolute; top: 0; left: 0; width: 100px; height: 100px; opacity: .5; background-color: red; z-index: 0; } .big-box { display: inline-block; position: relative; width: 266px; height:266px; border: 1px solid red; overflow: hidden; } .big-pic { position: absolute; width: 1400px; height: 798px; top: 0; left: 0; } .big-pic2{ display: inline-block; width: 266px; height:266px; background-size: auto 798px; background-image: url(“https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1550846791000&di=15edaf7bce643e13b65f70c82d74de30&imgtype=0&src=http%3A%2F%2Fpic.92to.com%2F360%2F201604%2F08%2F19864861_13.jpg"); background-position: 0 0;} </style></head><body> <div class=“small-box”> <img class=“small-pic” src=“https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1550846791000&di=15edaf7bce643e13b65f70c82d74de30&imgtype=0&src=http%3A%2F%2Fpic.92to.com%2F360%2F201604%2F08%2F19864861_13.jpg" alt=”"> <div class=“mask”></div> <div class=“rect” style=“display: none”></div> </div> <div class=“big-box”> <img class=“big-pic” style=“display: none” src=“https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1550846791000&di=15edaf7bce643e13b65f70c82d74de30&imgtype=0&src=http%3A%2F%2Fpic.92to.com%2F360%2F201604%2F08%2F19864861_13.jpg" alt=”"> </div> <div class=“big-box”> <div class=“big-pic2”></div> </div></body><script> window.onload = function () { var mask = document.getElementsByClassName(‘mask’)[0]; //为什么要用mask呢?不直接用选中small-pic。 //如果直接选择图片标签来绑定下面的mouseover事件,图片会一直闪烁!所以我们得给他一个和图片一样大小的遮罩层 var rect = document.getElementsByClassName(‘rect’)[0]; var bPic = document.getElementsByClassName(“big-pic”)[0]; var bPic2 = document.getElementsByClassName(“big-pic2”)[0]; mask.addEventListener(‘mousemove’, throttle(magnifier,100)) function magnifier(e){ //方块的left top在你的鼠标的左上方(网页左上角是原点),因此是减去一个方块的一半。 var x = e.offsetX - rect.offsetWidth / 2; var y = e.offsetY - rect.offsetHeight / 2; //极端情况,也就是当你的鼠标上的方块到四个边的边缘的时候。 if (x < 0) { x = 0; } if (y < 0) { y = 0; } if (x > mask.offsetWidth - rect.offsetWidth) { x = mask.offsetWidth - rect.offsetWidth; } if (y > mask.offsetHeight - rect.offsetHeight) { y = mask.offsetHeight - rect.offsetHeight; } //方块定位 rect.style.display=“block”; rect.style.left = x + ‘px’; rect.style.top = y + ‘px’; //第一种方法:需要注意的是这里的left 和 top得反过来,你鼠标在小图上往下移的时候,对应的大图其实是往上移的。 //所以:大图上的left = -小图上的left * 他们的缩放倍率 bPic.style.display = “block”; bPic.style.left = -x * bPic.offsetWidth / mask.offsetWidth + ‘px’; bPic.style.top = -y * bPic.offsetHeight / mask.offsetHeight + ‘px’; //第二种方法,这里需要注意 backgroundPosition的值是从0 - 100%的(得用百分比表示); //需要注意的是何时为百分百,从上面的极端情况判定我们可以知道 //x 是从0 到 mask.offsetWidth - rect.offsetWidth; //因此这就是0 - 100%;y同理 bPic2.style.display = “block”; bPic2.style.backgroundPosition =${x/(mask.offsetWidth - rect.offsetWidth)*100}% ${y/(mask.offsetHeight- rect.offsetHeight)*100}%; } mask.addEventListener(‘mouseout’,function(){ rect.style.display = “none”; bPic.style.display = “none”; bPic2.style.display = “none”; }) //函数节流 function throttle(fn, delay) { var pre = new Date().getTime(); return function () { var context = this; var args = arguments; var now = new Date().getTime(); if (now - pre > delay) { fn.apply(this,arguments); } } } }</script></html>后语有错误的地方请指出,谢谢啦 ...

February 23, 2019 · 3 min · jiezi

[盘点]项目中可以怎么优化图片

看似平常的事物,往往会蕴含的巨大的智慧。把看似平常的事物简单做好,可能很正常。如果能把平常的事物做精,做细,这个不平常。1.前言每一个开发者在开发项目中,不可避免要和图片打交道,优化图片似乎也成了一个必修课。图片优化也不仅仅是性能上的优化,还要进行体验上的优化。至于怎么优化图片,没有固定的方式,只能具体场景,具体分析,选择合适的方案。不多说,下面也简单介绍下自己处理过,了解过的一些方式。如果大家有补充,建议。欢迎在评论区留言,交流学习下。2.概念用法‘概念用法’这个词是自己乱起的,可能不太准确,是因为词穷了,不知道怎样形容。总得来说,这部分介绍的处理方式,就是讲一下就知道怎么用的方式,不需要怎么放代码,运行图等。只需要笼统的介绍一下,大家都会懂的一些方式。2-1.图片压缩这个没有隐含的意思,就是把图片的大小进行压缩。目前自己用的比较多的两个压缩网站是TinyPng和智图。使用比较方便,品质也基本保持一致。2-2.base64代替小图标一些比较小的图标,使用 base64 编码代替可以减少 http 请求。但是有一个缺点就是转成 base64 后,编码会比原图更大,图片越大,差别就越大。1K左右的图标,转码出来的 base64 大概是 1.1K-2K。如果是 8K 的图片,转码出来的 base64 可能超过10K。就自己项目开发而言,只有小于 4K 的图标,才会进行转码。2-3.icon-font代替图标由于 icon-font 看着是图片,实际上是字体。优点:就是在于可以矢量缩放,大小图标都可以使用,也可以改变颜色,使用也不麻烦。缺点:需要引入的文件不少(.svg,.ttf,.woff,.eot )。文件大小也比较大。建议是项目的图标要达到一定量才使用 icon-font,如果是几个图标,还是用图片吧。如果需要引入的图标多,就建议使用 icon-font。上面说的 icon-font 由于是字体,所以不支持多色图标。有了解到,现在 icon-font 可以支持多色图标了(symbol引用)。只是兼容性不好。2-4.雪碧图雪碧图就是把很多小的图整合到一起,制作成一张比较大的图,然后作为元素的背景图片使用,定位到相应的图片即可。优点:减少了大量的 http 请求。缺点:背景定位和在移动端适配大小有点麻烦。除此之外,使用雪碧图,有两个个注意地方1.不要把页面所有的图片都合并,比如把 logo 整合会破坏 html 的语义结构。图像复杂的 banner 也不要合并2.尽量只把颜色相近的图标整合在一张图片上,如果图片颜色相差太大,合并出来的图片可能会很大。2-5.响应式图片比如页面上有一张尺寸是 100100 的图片,但是图片的实际尺寸是 10001000 的。这样的情况建议在多准备一张 100*100 的图片。不然可能会造成资源浪费。2-6.混合模式代替变色的图标如下例子,比如页面有这个图标在特定情况下会是下面这个颜色。同一个图标,在不同的时候是不同的颜色。icon-font 可以通过改变 color 实现。或者用两张图片。除了这两个方法,用 CSS3 的混合模式,一样可以实现。两行代码搞定。<!DOCTYPE html><html> <head> <meta charset=“UTF-8”> <title></title> <style> div{ /容器必须有背景/ background: #09f; display: inline-block; } img{ width: 100px; vertical-align: top; } img:hover{ /设置混合模式/ mix-blend-mode: lighten; } </style> </head> <body> <div><img src=“images/icon-good.jpg” class=“u-icon”/></div> <div><img src=“images/icon-good.png” class=“u-icon”/></div> </body></html>运行效果展示完 mix-blend-mode,顺便提下 background-blend-mode 。用法基本一致,只是 mix-blend-mode 作用于 html 元素的混合模式,background-blend-mode 作用于元素背景的混合模式。<!DOCTYPE html><html> <head> <meta charset=“UTF-8”> <title></title> <style> div{ display: inline-block; width: 100px; height: 100px; /设置背景/ background: url(images/icon-good.jpg) no-repeat center,#09f; background-size:100%; /设置背景混合模式/ background-blend-mode: lighten; } </style> </head> <body> <div></div> </body></html>注意事项1.图片必须是白底纯色图标2.现代的浏览器,支持这个属性的浏览器如果图片是透明纯色背景,得到的结果会是这样受限篇幅影响,混合模式暂时就介绍这么多,以后发现好玩的再写文章。有兴趣可以看下面的参考资料。两行 CSS 代码实现图片任意颜色赋色技术不可思议的颜色混合模式 mix-blend-mode不可思议的混合模式 background-blend-mode2-7.简单图标使用 CSS 画有一些简单的图标,可以使用 CSS 代替。比如下面这些自己而言,项目上画的最多的就是各种箭头<!DOCTYPE html><html> <head> <meta charset=“UTF-8”> <title></title> <style> .icon-arrow-bottom { width: 0; height: 0; border: 100px solid #000; border-color: #000 transparent transparent transparent; } .icon-arrow-top { width: 0; height: 0; border: 100px solid #000; border-color: transparent transparent #000 transparent; } </style> </head> <body> <div class=“icon-arrow-bottom”></div> <div class=“icon-arrow-top”</div> </body></html>优点:矢量缩放,颜色可变,不需要发送请求缺点:只适合用简单图形,1-5行 CSS 代码可以搞定的才建议用,超过的不建议。想得痛苦,写也麻烦,花时间也多,效果未必比其它方案好。建议还是图片 base64,或者 icon-font。这里就简单举个例子,需要知道 css3 还可以画什么图形。看参考资料。纯CSS制作的图形效果奇妙的 CSS shapes(CSS图形)【CSS】用CSS绘制图标(图标大全)3.隐式预加载1.从这里开始。下面的demo,有些会用到 ecDo 这个库(自己写的一个常用函数库,欢迎star)。之前的文章有介绍过,这里就不再重复。大家不知道的时候点开看下相应的 API ,运行下,调试下就好。2.为方便展示,下面的demo,除了懒加载,都有在 network 把网速调至了慢速的3G。有些项目图片比较多,如果一次性加载,用户等待时间会过久,可能会造成体验效果很差,甚至导致用户流失,很多网站用到的一个体验优化方式是隐式预加载。等待首屏加载,在用户看首屏(第一张大图)的时候,悄悄的加载其它图片(这里为了展示效果,在项目上其他的小图片不应在第一屏)。<body> <p><img src=“lawyerOtherImg.jpg”/></p> <p>这是预加载的图片</p> <div> <img data-src=“https://materialdb.zhaoyl.com/201809/106796.jpg" class=“load-img” width=“100” height=“100”/><img data-src=“https://materialdb.zhaoyl.com/201809/105567.jpg" class=“load-img” width=“100” height=“100”/><img data-src=“https://materialdb.zhaoyl.com/201809/103097.jpg" class=“load-img” width=“100” height=“100”/><img data-src=“https://materialdb.zhaoyl.com/201809/10205.jpg" class=“load-img” width=“100” height=“100”/><img data-src=“https://materialdb.zhaoyl.com/201809/001.jpg" class=“load-img” width=“100” height=“100”/> </div></body>//测试请先清空缓存window.onload = function () { ecDo.loadImg(’load-img’, function () { console.log(‘加载完毕’) });}注意事项:1.大概预测,用户看首屏的时候,很大概率会往下面看。2.该方式,用户等待的时间比较短。但是图片超大,要慎重考虑。因为该方式无法保证用户在浏览的时候,能把下一屏(比如浏览第一屏的时候,要加载第二屏)的图片加载完毕,让用户无感知。如果切换的下一屏还没加载完毕,也可能会影响体验。demo:https://github.com/chenhuiYj/…4.显式预加载告诉用户正在加载,等到加载完了再一次性渲染在页面上。<style> div{ display: none; }</style><body> <p id=“p”>显示预加载进行中</p> <div id=“div”> <img data-src=“https://materialdb.zhaoyl.com/201809/106796.jpg" class=“load-img” width=“100” height=“100”/><img data-src=“https://materialdb.zhaoyl.com/201809/105567.jpg" class=“load-img” width=“100” height=“100”/><img data-src=“https://materialdb.zhaoyl.com/201809/103097.jpg" class=“load-img” width=“100” height=“100”/><img data-src=“https://materialdb.zhaoyl.com/201809/10205.jpg" class=“load-img” width=“100” height=“100”/><img data-src=“https://materialdb.zhaoyl.com/201809/001.jpg" class=“load-img” width=“100” height=“100”/> </div></body>let oP1=document.getElementById(‘p’);let oDiv=document.getElementById(‘div’);//测试请先清空缓存window.onload = function () { ecDo.loadImg(’load-img’, function () { oDiv.style.display=‘block’; oP1.style.display=‘none’; });}注意事项:1.大概预测,用户看首屏的时候,很大概率会往下面看。2.该方式好处在于加载完毕之后,就所有图片都加载完毕了,体验比较好。如果图片全部过大,加载时间会比较长,loading 的时间也会很长,会影响体验。demo地址:https://github.com/chenhuiYj/…5.懒加载这个大家应该很熟悉了,简单点说就是图片一开始不加载,当用户浏览到什么位置的时候,相应位置得图片就加载出来。<body> <p><img data-src=“lawyerOtherImg.jpg” class=“load-img” width=‘528’ height=‘304’/></p> <p><img data-src=“lawyerOtherImg.jpg” class=“load-img” width=‘528’ height=‘304’/></p> <p><img data-src=“lawyerOtherImg.jpg” class=“load-img” width=‘528’ height=‘304’/></p> <p><img data-src=“https://materialdb.zhaoyl.com/201809/105567.jpg" class=“load-img” width=‘528’ height=‘304’/></p> <p><img data-src=“https://materialdb.zhaoyl.com/201809/106796.jpg" class=“load-img” width=‘528’ height=‘304’/></p> <p><img data-src=“https://materialdb.zhaoyl.com/201809/103097.jpg" class=“load-img” width=‘528’ height=‘304’/></p> <p><img data-src=“https://materialdb.zhaoyl.com/201809/10205.jpg" class=“load-img” width=‘528’ height=‘304’/></p> <p><img data-src=“https://materialdb.zhaoyl.com/201809/001.jpg" class=“load-img” width=‘528’ height=‘304’/></p></body>window.onload = function () { //根据load-img 这个 class 遍历,元素距离页面底部 100像素的时候就开始加载,加载错误就显示error.jpg ecDo.delayFn(ecDo.lazyLoadImg(’load-img’, 100, ’error.jpg’),100,200); window.onscroll = function () { ecDo.delayFn(ecDo.lazyLoadImg(’load-img’, 100, ’error.jpg’),100,200); }}demo:https://github.com/chenhuiYj/…6.图片没加载出来显示默认图片这个例子,当网速比较慢的时候,想要加载的图片没有马上出来。或者图片路径错误,这个时候页面可能会出现一部分空白的地方,或者页面布局会出现错乱,比较常用的做法是先显示一张 loading 图或者是 logo 图。告诉用户,这里是图片,正在加载,体验上会好很多,比如下面这个例子。下面也简单的实现一下。比如网站上有这样的图片<p><img src=“error.jpg” data-src=“https://materialdb.zhaoyl.com/201809/105567.jpg" width=“264”/></p><p><img src=“error.jpg” data-src=“https://materialdb.zhaoyl.com/201809/106796.jpg" width=‘264’/></p><p><img src=“error.jpg” data-src=“https://materialdb.zhaoyl.com/201809/1067961.jpg" width=‘264’/></p>在 network 把网速调至了慢速的3G,以方便调试。//测试前请先清空缓存window.onload = function () { let oImg=document.getElementsByTagName(‘img’); for(let i=0;i<oImg.length;i++){ ecDo.aftLoadImg({ dom:oImg[i], url:oImg[i].dataset.src, errorUrl:oImg[i].src }) }}可以看到,一开始显示的是一张默认图片,等需要加载的图片,加载完了之后,再加载需要加载的图片。(最后一张图片,是故意把路径写错,所以出来的图片是之前的图片)demo:https://github.com/chenhuiYj/…7.小结关于项目上,优化图片的各种方式,自己用过的,听过的,大概就在这里了。实现方案,也不敢说是最好。如果大家有更好的想法,建议,欢迎在评论区留言。————————-华丽的分割线——————–想了解更多,和我交流,内推职位,请添加我微信。或者关注我的微信公众号:乐趣区 ...

November 26, 2018 · 2 min · jiezi