前言
诶,ie6,ie7这些顽固的浏览器我就不管了,反正现在主要开发移动网页,可以用到html5,css3的很多很多特性。
背景介绍
近日做了一个小小项目,是一个很流行的通过微信投票然后选出最最美,最最好的某某某,然后给奖励的。
其中一个比较重要的点就是要保证上传的图片的比例尺寸一致,当然我们不采用固定尺寸—采用的是固定比例的方式,为此我做了一个pc端移动端通用的裁剪工具。这个问题跟这个裁剪工具还有浏览器对图片的处理息息相关。
先说说裁剪的步骤先:
注意:裁剪比例是150:200,即,3比4
图片1:
选择图片
缩小放大移动图片移动裁剪框旋转等等操作。
好了,裁剪结果如下:
我们检查一下这张图片,看看是不是符合比例
可以看到尺寸为:197:263
那么计算得到的比例是:
0.7490494296577946
跟0.75有一定差距。为什么会出现这个结果?因为裁剪出来的图片是像素,最小单位为1,精度已经不够了,必然会出现误差,然后有些情况是不会出误差的,但是大部分情况都会出现。我们在裁剪的时候只要确保出现的比例误差在取1像素级别的情况下是最小的就行了—-1像素级别最接近原有比例的裁剪结果是可以接受的。
再看看第二个裁剪结果:
选取图片
这样子的
大家看得很爽对吧?下面我要治好你们的颈椎病。经过数次操作这样
裁剪
然后检查尺寸
好了,我们算一算:
469/625=0.7504
误差为:
0.0004/0.75=0.0005333333333332746
这个误差已经可以接受了,也就是说,当我们采用裁剪方式得到等比例图片时候,因为裁剪的精度限制,很多情况精度都是1像素,所以裁剪出来的比例是有误差的,只能取其中最接近的去趋近。裁剪方面已经不算是bug了。
那么,问题来了,为什么我还说是坑爹呢。下面我们看看实际显示效果。
问题出现了
我们打开网站看看
一切都这么美好
直到我的膝盖中了一箭,竟然遇到它。
诶玛,这绝壁是图片尺寸出了问题,但是哪一个出问题了???我的比例如此接近,都是如此完美!!!
好了,我们来一个排查。逐张逐张图片分析。
真的是有一张像素多1了,那怎么解决???
在解决之前不妨做一下计算,看看在缩放的时候到底发生了什么。这时候一口认定是裁剪图片出了问题可不是负责任的做法,之前我们已经做了测试,在1像素的精度下,很多时候只能趋近裁剪比例,而非真正精确到比例。
下面给出几张图片的真实缩放计算数据和浏览器采用的数据。
图片尺寸为:762 X 1016
图片的真实比例=762/1016=0.75
缩放高度=159/(762/1016)=212
图片尺寸为:729 X 972
图片的真实比例=729/972=0.75
缩放高度=159/(729/972)=212
图片尺寸为:972 X 1296
图片的真实比例=972/1296=0.75
缩放高度=159/(972/1296)=212
图片尺寸为:700 X 933
图片的真实比例=700/933=0.7502679528403001
缩放高度=159/(700/933)=211.9242857142857
图片尺寸为:299 X 399
图片的真实比例=299/399=0.7493734335839599
缩放高度=159/(299/399)=212.1772575250836
图片尺寸为:636 X 848
图片的真实比例=636/848=0.75
缩放高度=159/(636/848)=212
图片尺寸为:715 X 953
图片的真实比例=715/953=0.7502623294858342
缩放高度=159/(715/953)=211.92587412587415
结论
我计算了七张图片都给气疯了,特么逗我玩呢。。。。大于211小于或者等于212的都算是211,大于212小于或等于213的都算是212,一般正常人思考的四舍五入都没个影子。。。。
所以,这种情况不是我们裁剪图片时候比例不给力,而是浏览器的缩放图片策略跟我们想象的太有距离了。说真的,这种情况其实最好的解决方案是,裁剪出来的图片都是同一个尺寸,譬如:300x400这种,别等比缩放了,坑死。但是有时候又必须用等比缩放,这时候怎么办好呢?
下面提供一个思路:
我们别管浏览器给我们缩放的图片了,外层包裹一个尺寸唯一的背景图片,譬如是150X200,然后里面绝对定位我们的效果图片,即使多一个像素少一个像素都对整个框大小没影响。
譬如:
<div class="这是一个显示单元">
<div class="main-img" style="width:auto;height:auto;" style="position: fixed;">
<img id="这是背景图片,用来占位置。" src="150x200.jpg">
<img style="position: absolute;left:0;top:0;width:100%;" id="这才是我们的图片。">
</div>
</div>
补充
下面补充一份这样的demo。。。
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2015/9/25
Time: 11:35
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title></title>
<style>
#app{
background: rgba(33,33,33,0.4);
width: 640px;
}
#app:after{
content: "";
display: block;
clear: both;
}
.list_item{
float: left;
width: 48%;
border: 1px solid #008000;
margin-left: 10px;
margin-bottom: 10px;
}
.img_panel{
width: 100%;
position: relative;
}
.img_panel img{
max-width: 100%;
width: 100%;
}
.img_panel .real_img{
position: absolute;
left: 0;
top: 0;
}
.desc{
letter-spacing: 1px;
line-height: 21px;
font-size: 14px;
}
</style>
</head>
<body>
<div id="app">
<div class="list_item">
<div class="img_panel">
<img src="loading.jpg">
<img src="pic1.jpg" class="real_img">
</div>
<div class="desc">这是文字描述</div>
</div>
<div class="list_item">
<div class="img_panel">
<img src="loading.jpg" >
<img src="pic2.jpg" class="real_img">
</div>
<div class="desc">这是文字描述</div>
</div>
<div class="list_item">
<div class="img_panel">
<img src="loading.jpg">
<img src="pic3.jpg" class="real_img">
</div>
<div class="desc">这是文字描述</div>
</div>
<div class="list_item">
<div class="img_panel">
<img src="loading.jpg">
<img src="pic4.jpg" class="real_img">
</div>
<div class="desc">这是文字描述</div>
</div>
</div>
</body>
</html>