一、需求场景:

最近闲来无事,boss提出了一个要求,研究相关代码并完成一个关于编辑图片功能的性能优化,该功能的主要界面展示如下:

通过了几分钟的短暂试用,发现就是一个简单的裁剪并保存用户选择并上传的图片作为用户头像的功能。

主要功能点如下:

  1. 选择图片并上传。
  2. 拖动中间选择区域的位置或者大小选择设置的图片区域。
  3. 点击确定按钮,完成图片设置。

初步一看,貌似没有什么值得优化的地方,通过与boss深入了解后知晓,在选择容量较大(超过10MB)的图片时,浏览器响应速度会变得异常缓慢,具体表现是

拖动中间选择区域的位置或者大小时,大约3-4秒才响应一次,严重影响了使用者的用户体验,作为一名专(zhuang)业(bi)的前端人员来说,是完全不能容忍的。

二、性能分析:

作为一名专(zhuang)业(bi)的前端人员来说,遇到问题的首要肯定是先进行性能分析。一般来说浏览器的性能问题无非就是CPU和内存消耗占用。

通过对比查看性能管理器中的chrome内存占用后发现,选择大容量图片前,chrome的内存占用是883MB,而选择大容量图片后,chrome的内存占用达到了2232MB,

内存占用暴涨将近了200%!这就是出现性能问题的所在。事不宜迟,开始着手研究并解决问题。

三、查看代码:

通过查看代码,发现实现该功能的程序猿(也可能是媛)是通过在背景渲染一张完整的image,前景的图片选择区域设置一个透明度为0.3的蒙版(图中的黑色背景区域),

然后在选择区域(图中绿色方框)的背景区域再渲染一张image,再通过动态设置background-position的top、left和size来达到预览并获取选中区域图片的目的。

html结构如下:

<div class="pic_area" style="display:block" ng-show="roomPhotoEdit.file">
  <div class="pic_editor">
    <!-- upload image -->
    <span class="pic" id="editing_pic">
      <!-- 渲染的第一张图片 -->
      <img onload="angular.element(this).scope().roomPhotoEdit.initCrop()" ng-src="{{roomPhotoEdit.file}}" alt="">
    </span>
    <!-- 黑色蒙版背景区域 -->
    <span class="crop_dimmed"></span>
    <!-- 图中绿色方框区域 -->
    <span class="crop_box" ng-style="roomPhotoEdit.cropLayout" style="top:75px;left:75px">
       <!-- 渲染的第二张图片 -->
  <span class="drag_area" ng-style="roomPhotoEdit.edited"></span>
  <button class="drag_handle handle_lt" data-type="lt"></button>
  <button class="drag_handle handle_rt" data-type="rt"></button>
  <button class="drag_handle handle_lb" data-type="lb"></button>
  <button class="drag_handle handle_rb" data-type="rb"></button>
    </span>
  </div>
</div>

javascript代码如下(基于AngularJS):

scope.roomPhotoEdit.edited = {
'background-image': 'url(' + currentImage.attr('src') + ')',           // 这里多渲染了一张图片
'background-position': backgroundPositionOption[imageSizeType],         // 动态设置top和left
'background-size': backgroundSizeOption[imageSizeType]              // 设置预览区域的尺寸
}

通过代码可以很明显的看到通过在class为drag_area的区域额外渲染一张背景图片并动态修改background-position和background-size来达到预览选择区域图片的目的。

由于额外渲染了一张图片,如果用户选择的容量超大的图片,则会导致浏览器内存占用暴涨,如果能只渲染一张图片,应该就能极大减少内存占用,可以从此入手。

四、尝试优化:

首先就是去除拖放区域中额外渲染的背景图片。

可以从上图中看到去除了背景图片之后,拖放区域被黑色蒙版遮盖住了,没有预览的效果了。

通过度娘之后得知可以通过动态设置黑色蒙版区域的border-width、border-style、border-color来达到显示拖放区域的预览图片效果。

话不多说,先来直接看看效果。

再来看之前drag_area区域的html结构,可以发现,之前的背景图片等样式全部被去除了。

取而代之的之前的黑色蒙版区域crop_dimmed的样式,可以看到设置了border-width、border-style和border-color,来达到显示中间预览区域的效果。

最后要做的只是,在预览区域的拖放事件中动态去设置drop_dimmed区域的border-width属性即可。

该属性主要的计算规则如下(其中layoutTop为绿色方框区域的top属性,layoutLeft为绿色方框区域的left属性,containerWidth为外部容器的宽度,containerHeight为外部容器的高度,position.size为绿色方框区域的宽高,在这里拖放区域只能等比拖放,所以是个正方形,宽高一致):

border-top-width: layoutTop + "px"
border-right-width: containerWidth - layoutLeft - position.size + "px"
border-bottom-width: containerHeight - layoutTop - position.size + "px"
border-left-width: layoutLeft + "px"

五、验收

代码改完了最后一步当然是验收了,通过查看修改后的内存占用发现,即使选择了大容量的图片之后,内存占用也稳定在了800MB左右,而且操作比之前流畅多了。

搞定,收工!

六、总结:

从最初的纯粹为了图片裁剪区域的预览,而额外渲染了一张图片开始,到最后的去除额外图片渲染,而采用border-width的方案来达到裁剪区域预览的目的。

前端er们做的事情无非为了用户体验这4个字不断在努力。而前端的一切的方案和手段,最终目的都是为了提升用户体验。

毕竟,我们做出的是最接近用户的产品。

巧用css的border属性完成对图片编辑功能的性能优化的更多相关文章

  1. 重温CSS:Border属性

    边界是众所周知的,有什么新的东西吗?好吧,我敢打赌,在这篇文章中,有很多你不看永远不知道的东西! 不仅可以用CSS3来创建圆角,使用原有CSS一样可以显示自定义图形.这是正确的(有待考究):在过去,没 ...

  2. css 利用border属性制作箭头 Using Borders to Make Pure CSS Arrows

    不再需要多余的图片 用border属性自然能创造箭头效果 学习地址:http://tech.patientslikeme.com/2010/11/09/using-borders-to-make-pu ...

  3. 如果用css的border属性画一个三角形

    假设页面中有个div,如何通过css做一个三角形.这是我们项目中用到的今天就稍微总结下.顺便说一句偷偷写博客的感觉还挺爽 div { width: 0; height: 0; border-top: ...

  4. CSS之 border 属性

    特性 border-width 不支持百分比  border-color 默认颜色是 color  border-color 透明值的作用:可利用增加可点击区域,利用内阴影做边框  border 应用 ...

  5. CSS:不可思议的border属性

    原文:Magic of CSS border property 译文:不可思议的CSS border属性 译者:dwqs 在CSS中,其border属性有很多的规则.对于一些事物,例如三角形或者其它的 ...

  6. CSS性能优化的几个技巧

    前言 随着互联网发展至今,对于网站来说,性能显的越来越重要了,CSS作为页面渲染和内容展现的重要环节,影响着用户对整个网站的第一体验.所以,我们需要重视与CSS相关的性能优化. 项目开发初期我们可能因 ...

  7. CSS padding margin border属性详解

    图解CSS padding.margin.border属性W3C组织建议把所有网页上的对像都放在一个盒(box)中,设计师可以通过创建定义来控制这个盒的属性,这些对像包括段落.列表.标题.图片以及层. ...

  8. 【转】图解CSS的padding,margin,border属性(详细介绍及举例说明)

    W3C组织建议把所有网页上的对像都放在一个盒(box)中,设计师可以通过创建定义来控制这个盒的属性,这些对像包括段落.列表.标题.图片以及层.盒模型主要定义四个区域:内容(content).边框距(p ...

  9. CSS padding margin border属性详解【转载】

    本文转载自:http://www.cnblogs.com/linjiqin/p/3556497.html ,感谢相关博主. 图解CSS padding.margin.border属性 W3C组织建议把 ...

随机推荐

  1. C#6.0语言规范(六) 转换

    转换能够被视为是一个特定类型的表达式.转换可能会导致给定类型的表达式被视为具有不同的类型,或者它可能导致没有类型的表达式获取类型.转换可以是隐式或显式的,这决定了是否需要显式转换.例如,从类型int到 ...

  2. 关于OC中的几种延迟执行方式

    第一种: [UIView animateWithDuration: delay: options: animations:^{ self.btn.transform = CGAffineTransfo ...

  3. java—单例设计模式

    单例设计模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 1.构造方法私有化 2.声明一个本类对象 3.给外部提供一个静态方法获取对象实例 什么时候使用? 1.通过在工具类的设计中使用: ...

  4. Resolve类中错误体系的处理

    标红的表示要走3步骤,也就是: final List<MethodResolutionPhase> methodResolutionSteps = List.of( MethodResol ...

  5. 对html中iframe的研究

    虽然平时不怎么用iframe,但经常在网上听一些前辈说iframe怎样怎样,今天索性对iframe来个大研究,那样就不必去记那些条条框框了,自己体验一遍比看什么都好. 创建两个文件一个index.ht ...

  6. map集合的见解、排序

    map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等 HashMap:我们最常用的Map,它根据key的HashCode 值 ...

  7. HBase:分布式列式NoSQL数据库

    传统的ACID数据库,可扩展性上受到了巨大的挑战.而HBase这类系统,兼具可扩展性的同时,也提出了类SQL的接口. HBase架构组成 HBase采用Master/Slave架构搭建集群,它隶属于H ...

  8. UEFI+GPT与BIOS+MBR各自有什么优缺点?

    1.分区数量上,gpt好像可以支持无限个分区,不过window上只认128个,而且gpt分区不分主分区,逻辑分区,可以理解为全部都是主分区,就相当于可以允许你一个分区一个系统,128个系统了.而这是m ...

  9. WPF 中Canvas图形移动、缩放代码

    从Flash转C#,很多内容一知半解,边摸索边前进,代码粗糙,权当留个脚印. 只是想得到一个基础的移动和缩放功能的界面,找了很久都是画线.画矩形等基础形状的代码,移动和缩放说的并不清晰,只能自己努力来 ...

  10. WPF备忘录(3)如何从 Datagrid 中获得单元格的内容与 使用值转换器进行绑定数据的转换IValueConverter

    一.如何从 Datagrid 中获得单元格的内容 DataGrid 属于一种 ItemsControl, 因此,它有 Items 属性并且用ItemContainer 封装它的 items. 但是,W ...