一、需求场景:

最近闲来无事,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. flask-Datatables

    我先给大家推荐一个jQuery开源库网址  http://www.jq22.com/ Datatables 是一款jquery表格插件.他是一个高度灵活的工具,可以将任何HTML表格添加高级的交互功能 ...

  2. 简单介绍RPM包制作方法

    RPM是RedHat Package Manager(RedHat软件包管理工具)的缩写,是一种用于互联网下载包的打包及安装工具,它包含在某些Linux分发版中.它生成具有.RPM扩展名的文件.使用r ...

  3. flask信号使用

    flask信号: 安装: flask中的信号使用的是一个第三方插件,叫做blinker.通过pip list看一下,如果没有安装,通过以下命令即可安装blinker: pip install blin ...

  4. 安装ORACLE时 各Linux版本下载地址

    oracle linux :https://edelivery.oracle.com/osdc/faces/SearchSoftware 需要注册oracle账号 redhat官方下载 https:/ ...

  5. 剑指offer三从头到尾打印链表

    一.题目: 输入一个链表,从尾到头打印链表每个节点的值. 二.解题方法: 方法一:采用递归的方式实现 方法二:借助堆栈的“后进先出”实现 import java.util.ArrayList; imp ...

  6. 常见数据结构的Java实现

    单链表的Java实现 首先参考wiki上的单链表说明,单链表每个节点包含数据和指向链表中下一个节点的指针或引用.然后看代码 import java.lang.*; public class Singl ...

  7. Android之混淆心得与亲身体验

    project.properties 中设置 proguard.config=proguard-project.txt proguard-project.txt  中设置 -optimizationp ...

  8. 22-hadoop-hive搭建

    1, hive简介 hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供简单的sql查询功能,可以将sql语句转换为MapReduce任务进行运行. 其优点是 ...

  9. java日期互转:LocalDateTime、String、TimeStamp、Long、Instant、Date

    由于java版本的迭代,一个使用java开发的项目中可能出现多种日期对象,例如LocalDateTime.LocalDate.Date,不像C#只有一个DateTime,因此在各种日期格式或者对象之间 ...

  10. vscode浏览器打开html vscode修改默认浏览器

    vscode怎么浏览器打开html预览?这里大家可以通过安装open in browser插件解决. 1.vscode怎么浏览器预览 1.点击拓展 2.输入open in browser,选择第一个 ...