正方形格子布局图片拖动的自动对齐功能

2016-02-17 00:51 20 1 收藏

生活已是百般艰难,为何不努力一点。下面图老师就给大家分享正方形格子布局图片拖动的自动对齐功能,希望可以让热爱学习的朋友们体会到设计的小小的乐趣。

【 tulaoshi.com - 平面设计 】

正方形格子布局图片拖动的自动对齐功能,PS教程,图老师教程网

快速导航:

1、功能背景

2、功能要求

3、一般解决方案及问题

4、优化方案思路

5、代码实现

6、总结

功能背景

  良无限首页的魔方楼层(也称百变楼层,图片按找格子大小制作,并可以自由布局图片顺序)是相当成功的页面展现形式,可以用非常有品质的形式,自由组合不同大小的banner或商品。这种布局方式出现后,曾被包括淘宝商城在内的多个页面或网站所借鉴。

正方形格子布局图片拖动的自动对齐功能,PS教程,图老师教程网

  这么有特色的楼层,维护上是个问题,一个比较好的方式,就是把魔方的每个元素用绝对定位排在楼层中,在后台做一个拖动图片的插件,让运营同学拖动图片到指定位置,并自动生成该元素的绝对定位的坐标。

  图片拖动并不难实现,监测鼠标的移动即可。

  然而,为了提高拖动的准确性,需要图片可以在一定范围内自动对齐到基准点的功能,这样运营同学可以更方便准确地排列图片。

  这个自动对齐的功能虽然看起来很好实现,但是实现的方式未必都是最优的,现在让我们仔细瞧瞧这个看似简单的功能的实现思路。

功能要求

1、魔方楼层的每个格子的左上点坐标规定为基准点

2、当图片被拖动到基准点周围的一定范围内(10px),图片自动对齐到基本点。

  技术重点:判断当前坐标,是否在基准点的自动对齐范围内。

一般解决方案及问题

1、把所有基准点的坐标存储起来,图片每次移动时,都遍历基准点库,判断当前坐标是否在基准点的对齐范围之内。

2、魔方是由正方形组成,所以基准点之间是由规律的,所以优化上一个方案:基准点库其实可以自动生成,由 width * n 即可得出基准点, 再用一个上限(1000)来限制一下即可。

  问题:以上方案都是基于基准点库、遍历、对比来实现的,我们会发现,遍历这个过程很难控制其效率,若再与每一次的鼠标移动监听的频率相叠加,这个实现貌似很笨重。那有没有更好的方式,脱离基准点库和遍历,只做简单的计算后进行对比就能实现呢?

优化方案思路

正方形格子布局图片拖动的自动对齐功能,PS教程,图老师教程网

  我优化的目的:脱离基准点库、遍历,只做简单的计算后进行对比。

  所以,我的思路是,寻找基准点及自动对齐范围内的值的规律。

  为了更好地描述这个方案,我们先明确、明确一下词汇表

  必要条件:

  基准方格:组成魔方的基本单位,可以重复排列组成魔方,案例中的基准方格包括140×140的图片位+ 2px的图片间距,即142×142的方格。

  基准边距(w:基准方格边长,本例中是142

  偏移量(e:第一个基准方格的坐标,即魔方偏移(0,0)的偏移量,本例中是3.(横向纵向的偏移量必须相等。)

  自动对齐范围(a:基准点周围的一定距离,进入这个范围内,则对齐到基准点, 本例中是10,限制:a w/2 (这个范围必须小于二分之一基准边距,如果大于,则不能判断将要靠近哪一个基准点)

  当前坐标值(p): 等待校验是否在自动对齐范围内的值 p = k + x

  思路扩展:

  基准点(k:每个基准方格的左上顶点,但由于是正方形,所以基准点的二维的横纵坐标,可以简化为一维的方式。所以在本例中,基准点有:3、145、287、429、571、713、855,经过抽象,得出公式:k = w * n + e

  基准点倍数(n): 第几个基准点,n为整数,若n 0,则代表 基准点为负值。

  核心思路:基准点及自动对齐范围内的值的规律

正方形格子布局图片拖动的自动对齐功能,PS教程,图老师教程网

  根据这个思路,我将自动对齐范围由 [ k-a , k+a ] 推导成为参考范围:[ n-a/w , n+a/w ]

  这样也可以有这个思路计算出来一个参考值,概念如下:

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/pmsj/)

  参考值(z: 当前坐标值经过一定运算得出的值,用来比较,以判断是否在参考范围内。计算方法:z = (p – e) / w

  参考范围:自动对齐范围的边界值,通过参考值的算法,得出的边界范围:[ n – a/w , n + a/w ]

  如此一来,我只要通过把当前坐标(p)通过简单的计算 (p-e)/w,得出一个参考值(z),再把这个参考值(z),与他的参考边界(n-a/w  n+a/w)相比较,即可得出这个值是否在自动对齐范围之内的结论。

if(n-a/w = (p-e)/w = n+a/w){

//success

}

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/pmsj/)

n-a/w = z = n+a/w

-a/w = z – n = a/w

由于 a w/2 ,所以 a/w 1/2 ,所以 |z-n| 1/2,即:

正方形格子布局图片拖动的自动对齐功能,PS教程,图老师教程网

这样的话貌似可以得出结论,但是遗憾的是n是不可知的,但是由|z-n| a/w可以知道:

z n ,则 z-n 在 [0, a/w]

z n ,则 z-n 在 [-a/w, 0]

n 0 时:

(z – z的整数位 = z的小数位)

z n ,则 n = z的整数位 ;z-n = z的小数位 ;z的小数位在 [0, a/w]

z n ,则 n-1 = z的整数位z-(n-1) = z-n+1 = z的小数位 ;z的小数位在 [1-a/w, 1]

n = 0 时:

z n ,则 n = z的整数位 ;z-n = z的小数位 ;z的小数位在 [0 , a/w]

z n ,则 n = z的整数位 ;z-n = z的小数位 ;z的小数位在 [-a/w , 0] z的小数位的绝对值在 [0 , a/w]

(若 z 0, 则整数位和小数位都小于0,如:(-4.25) – (-4) = -0.25

n 0 时:

z n ,则 n+1 = z的整数位 z-(n+1) = z-n-1 = z的小数位 ;z的小数位在 [-1 , a/w-1] z的小数位的绝对值在 [1-a/w , 1]

z n ,则 n = z的整数位z-n = z的小数位 ;z的小数位在 [-a/w , 0] z的小数位的绝对值在 [0 , a/w]

综上所述:

z的小数位的绝对值 [0 , a/w][1-a/w , 1]

即:

正方形格子布局图片拖动的自动对齐功能,PS教程,图老师教程网

这样一来,只要通过z = (p-e)/w计算出z的值,取出小数位,然后在[0 , a/w]、[1-a/w , 1]区间中比较,就可以得出结论了。

代码实现

  好,接下来分享一下如何实现以上方案:

1、输入和输出:

输入:当前坐标数值、基准边距、偏移量(默认为0)、自动靠近范围(默认为10)

输出:当前坐标值是否在自动对齐范围内(boolean)、目标坐标数值

2、具体代码:

/*** isPos 正方形格子布局的自动对齐* @description 在正方形格子布局的自动对齐中,用于判断当前位置是否进入自动对齐范围,并返回目标位置* @param {Object} config 配置项* @param {Number} config.pos 当前坐标数值(横坐标或纵坐标) 必填* @param {Number} config.standard 标准边长 必填* @param {Number} [config.offset] 偏移量 默认为0* @param {Number} [config.autoRang] 自动对齐范围 默认为10* @return {Object} obj 返回对象* @return {Boolean} obj.status 当前坐标值是否在自动对齐范围内* @return {Number} obj.pos 目标坐标值* @example* //配置示例* var config = {*    pos: 156,*    standard: 142,*    offset: 3,*    autoRang: 10* };*/var isPos = function(config){    var pos = parseInt(config.pos, 10),        standard = parseInt(config.standard, 10),        offset = parseInt(config.offset, 10) || 0,        autoRang = parseInt(config.autoRang, 10) || 10,        fixed = parseInt(config.fixed, 10) || 3,        targetPos = pos,        posStatus = false,        r1, r2, referPos, n;        if((!pos && pos != 0) || !standard) return {};    /**    * 计算坐标值的参考值(与标准边长相除)    */    var getReferPos = function(_pos){        var z = parseFloat((_pos/standard).toFixed(fixed)),            int = parseInt(z, 10);        return {            z: z,            int: int,            float: Math.abs(parseFloat((z - int).toFixed(fixed)))        };    }(pos - offset);    n = getReferPos.int;    referPos = getReferPos.float;    r2 = parseFloat((autoRang/standard).toFixed(fixed));    r1 = 1 - r2;    if((referPos = r1 && referPos = 1) || (referPos = r2 && referPos = 0)){        n = (referPos = r1 && referPos =1) ? (getReferPos.z  0 ? n+1 : n-1) : n;        //计算自动靠齐的目标位置。        targetPos = n * standard + offset;        posStatus = true;    }    return {        status: posStatus,        pos: targetPos,        z: getReferPos.z,        n: n,        r: referPos    };};

3、DEMO与测试:

http://lp.taobao.com/go/act/lptest/ispostest.php

总结

  这个小功能看似很不起眼,但是经过分析及抽象,不仅通过巧妙的算法解决了性能问题,还抽象出来以后解决类似问题的通用方法。

  上述算法,可用于格子的布局中,格子可以是长方形,格子数目没有限制,偏移量没有限制、格子大小也没有限制。不用遍历基准点库,只通过简单计算及比较,即可得出是否需要自动对齐的结果。算法相对精炼。

  问题虽小,但是精益求精的解决问题,是我们所追求的。

  最后分享 几句话,是TMS标题中的:

  生活中的万事万物,无不可以吸收教益,无不可以成文,只要求思之深而无不在定能有所得益。

  知识需要反复探索,土地需要辛勤耕耘

  最后,感谢夏达同学帮这篇文章设计的主题图片,非常有品质感!

来源:http://www.tulaoshi.com/n/20160217/1577006.html

延伸阅读
玩转6×6正方形画幅的3条构图技巧 当 4:3和3:2画幅渐渐让人们Tulaoshi.Com厌倦的时候,正方形构图开始显示出其独特的魅力,你既可以如Peter Marlow那样买一台Mamiya或者Rollei 2.8F,也可以试着重新裁剪你的老片,看看有没有可以在正方形构图上焕发新生的旧作,下面是一些正方形构图的小Tips,也许可以在你的拍摄或裁剪过程中提供一些...
实例讲解 如何拍好正方形构图的摄影作品   无论是摄影师还是发烧友,我们经常习惯于使用6:4的长宽比去观察这个世界,因为这就是标准单反镜头的成像比例。但这并不意味着你必须使用这个比 例。一个更有创造性的办法是根据你的拍摄主体来决定相片的构图。这张正方形的蒲公英照片就是一个很好的例子:如果不经剪裁,这张相片在左右两侧...
手工杯垫视频教程 为了让大家更清楚了解杯垫的制作方法,在这里我还拍了一个视频不知道怎么下手的朋友可以根着视频一起动手,相信你还完会也能做出漂亮的手工杯垫。 准备材料 材料工具: 水杯,花布(用作杯子套),毛毡(用作杯垫),纽扣,细绳,针线,珠光针,用作模板的纸张,卷尺。 测量大小 测量水杯的杯口、杯身...

经验教程

692

收藏

68
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部