一、需求场景:

最近闲来无事,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. java后端导出excel表格

    转载 :https://www.cnblogs.com/zhaoyuwei/p/9038135.html 不需要在实体类些@Excel(name = "登录名", width = ...

  2. ORA-01113 & ORA-01110同时出现

    \NOARCHIVED LOG , 没备份 , Redo Log 被覆盖 , 某个datafile不能online 设计知识点:BBED> set block 1BBED> p kcvfh ...

  3. 【disruptor】2、disruptor中生产者线程与消费者之间的协调

    由于ringbuffer是一个环形的队列,那么生产者和消费者在遍历这个队列的时候,如何制衡呢? 1.生产快,消费慢,数据丢失? 生产者速度过快,导致一个对象还没消费完,就循环生产了一个新的对象要加入r ...

  4. odoo 开发基础 -- 视图之widget

    Odoo 中的widget many2many_tags one2many_list selection progressbar selection statusbar handle monetary ...

  5. 课程三(Structuring Machine Learning Projects),第一周(ML strategy(1)) —— 1.Machine learning Flight simulator:Bird recognition in the city of Peacetopia (case study)

    []To help you practice strategies for machine learning, the following exercise will present an in-de ...

  6. 在matlab中实现线性回归和logistic回归

    本文主要讲解在matlab中实现Linear Regression和Logistic Regression的代码,并不涉及公式推导.具体的计算公式和推导,相关的机器学习文章和视频一大堆,推荐看Andr ...

  7. 如何用ajax下载文件

    引子 在HTML5没来之前,浏览器想要下载文件,可能有这么几种方式: 借助a标签,<a href="学习资料.xlsx"></a> window.locat ...

  8. StreamSets学习系列之StreamSets的Core Tarball方式安装(图文详解)

    不多说,直接上干货! 前期博客 StreamSets学习系列之StreamSets支持多种安装方式[Core Tarball.Cloudera Parcel .Full Tarball .Full R ...

  9. 【转】谷歌三大核心技术(二)Google MapReduce中文版

      Google MapReduce中文版     译者: alex   摘要 MapReduce 是一个编程模型,也是一个处理和生成超大数据集的算法模型的相关实现.用户首先创建一个Map函数处理一个 ...

  10. 高可用Hadoop平台-答疑篇

    1.概述 这篇博客不涉及到具体的编码,只是解答最近一些朋友心中的疑惑.最近,一些朋友和网友纷纷私密我,我总结了一下,疑问大致包含以下几点: 我学 Hadoop 后能从事什么岗位? 在遇到问题,我该如何 ...