2014年10月11日星期六

javascript模拟flash头像裁切上传 - 古德God

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
javascript模拟flash头像裁切上传 - 古德God  阅读原文»

是的,jq已经有类似的插件了,或者干脆用flash算了,为什么我还要自己写?因为造(wo)轮(bu)子(hui)也(flash)是一个学习的过程,轮子不会造,将来怎么造飞机?先来一张最终效果图:

一、大概思路

用js来做这个效果,先得将图片A上传到服务器,关于异步上传的插件有很多,不用插件也可以参考本人上一篇博客用纯js的方式上传,上传之后显示到页面里,由于上传的图片尺寸各不相同,要完整地显示图片,就要将上传后的图片用css控制按比例缩放显示,然后通过矩形选框选择需要的部分,用js获取矩形选框的左上角坐标,加上选框的宽高按比例计算后传给后台,后台程序根据所传参数来裁切得到图片B后返回到前台并将上传的原图A删除,节省空间。

二、分析

将效果图分为左右两部分,先看左边,由一张图片加一个矩形选区组成,图片和选区之间有一层半透明的遮罩,但是这样的话会连选区部分一块遮住,就没有上面这种框选出来的效果了,事实上结构是这样的:由下往上分别是1图片层,2遮罩层,3选区层(一个div,绝对定位),4图片层(绝对定位)。第1层和第4层的图片是一样的,大小及left、top值也一样,给第3层选区层加个overflow:hidden,就呈现出了上面的效果,虚线边框及拖拽的8个点后文会讲到。下图比较直观地说明的它们的层级关系,第3层灰色部分为overflow:hidden隐藏的部分:

做完图发现左右两边框的位置不一样,但重在说明原理。接下来,选区部分可以拖动,用到拖拽原理:鼠标按下,记录var disx=event.clientX,var disy=event.clientY,拖动,计算当前event.clientX与disx的差值为x,当前event.clientY与disy的差值为y,设置第4层图片的left值为图片当前offsetLeft+disx,top值为offsetTop+disy。如选区往左移动10px,由于第4层只能在第1层范围内移动,那么刚好第4层的left值等于负的第3层的left值,top值同理。拖拽原理图:

选区大小是可以按比例改变的,这就需要用到选区周围的8个点,如下图可以分为4个部分:

每个部分里的点触发的事件是一样的,4个部分触发的事件都是改变选区大小,不一样的地方在于第1部分会同时改变选区的left和top值,第2和第4部分分别只改变的是选区的top、left值,第3部分不会改变选区的left和top值。4个部分原理都一样,拿第1部分说事,点击第1部分的点往左上角拖动,选区变大的同时设置其left和top值(会减小),而left减小的值刚好等于选区增大的值,这个值的计算方法同拖拽原理。拖拽过程中需要限制范围,不能超出整个图片的范围。

选中需要截取的部分后,获取当前选区(第4层)的左上角的坐标,即第4层的offsetLeft、offsetTop值,再获取选区的宽高,这4个值不能直接往后台传,因为此时的图片可能是被缩放过的,而后台是根据原图尺寸来截取的,那么需要在图片上传完之后获取图片原始宽高,与页面中图片显示宽高得出一个比例,将这4个值乘以这个比例得出的值才是后台需要的。

至于选区的边框,做得简单点可以直接设置border:1px dashed #fff,更好的方法是放四个position:absolute的div,分别固定在选区的上下左右,上下宽100%,高1px,左右宽1px,高100%,背景设为一个波浪纹的gif图片,repeat,出来的效果很是惊艳!

右边部分3张图片仅仅是展示用,显示的内容是左边选区选中的部分,而选区的大小是可以改变的,所以右边的图片大小及位置是随着选区的变化而变化。选择图片上传后,选区有个默认宽高,右边3个框宽高是固定的,根据选区宽与右边三个框的宽分别相除得出的比例可以算出右边三个框内的图片应该显示的尺寸,显示原理同左边,相比左边只是少了第1、2层。

这种方式的优点是纯js,兼容性也好,另外还可以做个特性检测,支持HTML5的浏览器可以直接在前端切割图片,缺点是裁切之前要选将图片上传。源码晚点贴上来。


本文链接:javascript模拟flash头像裁切上传,转载请注明。

C++_系列自学课程_第_12_课_语句_《C++ Primer 第四版》 - volcanol  阅读原文»

  前面的文章说完了表达式和类型转换的部分内容,在我参考的书里面,接下来讨论的是各种语句,包括:顺序语句、声明语句、复合语句(块语句)、语句作用域

、if语句、while语句、for语句、do...while语句、break语句、continue语句、goto语句、try语句。

  这里我们来讨论这些语句,为了方便讨论和记忆,我们可以将这些语句可以分为五大类: 简单语句、条件语句、循环语句、流程控制语句、异常处理。当然也可以

不这么分类,我这么说就是为了自己好理解和记忆。

一、简单语句

  我将顺序语句、声明语句、复合语句分到简单语句里面,因为这些语句直观。

1、语句

  C++中,大部分语句以分号结束, 例如在表达式后加上分号就构成表达式语句, 如下所示:

  2 + 3 ; //表达式语句

2、空语句

  在C语言中,单独一个分号表示为空语句,C++继承了这个概念。

; //空语句

  空语句不产生编译代码,这个优化过程由编译器自己完成,不需要程序员关心。

  空语句在语法要求需要一个语句,但是又不需要执行具体功能的地方。如下所示:

  if(iVar > 10)

    ;
//空语句,如果iVar 大于10 则什么也不做
  else

    some statement

  当然上面的例子,可以有更简洁的方式来表达,这里只是为了说明空语句的用法,不必考虑实际是否会这么写代码。 下面给一个具体的有实际意义的实例:

我们可以编写一段代码,用于接受用户的输入,在用户输入特定的信息之前不做任何事:

Exp:

int main()
{
char chVar = 0;

while(cin>>chVar && (chVar != 'y' && chVar != 'Y'))
;

cout
<<"you have input 'y' or 'Y',then jump out the while loop"<<endl;


return 0;
}

程序的执行结果如下所示:

[root@localhost cpp_src]# g++ test.cpp
[root@localhost cpp_src]# .
/a.out
a
b c d e f h j
Y
you have input
'y' or 'Y',then jump out the while loop

  这段程序在用户输入y 或者 Y 之前,会一直等待用户输入y或者Y, 这里这里当我们输入两者之一的时候,就会退出循环,然后输出提示信息。

  通常在程序当中定义

3、顺序语句

  如果没有其他控制机制,计算机在执行程序的时候,从上往下、从左往右执行程序代码。 如下所示:

  int iVar = 10 ; //声明语句

  iVar
= 2 * 4 ; //赋值语句

  sum(
1, iVar); // 函数调用语句

  上面的声明语句、赋值语句、函数调用语句就是一组顺序语句,顺序语句从上往下、从左往右执行。

4、声明语句

  在C++中,对象的声明或者定义也是语句,,通常定义语句也是声明语句,如下所示:

  string strVar; //定义语句

  extern int iVar ; //声明语句

5、语句块

  语句块也叫复合语句, 使用{ 、} 括起来的语句,复合语句标识了一个作用域,在块中定义的名字其作用域仅在块中或者块中嵌套的块中有效。 在块中定义的标

识符从其定义位置开始,到块结束的位置处有效。

  复合语句用作语法规则要求使用语句,但是使用单个语句无法表达程序逻辑的地方。 例如: 在while循环或者for循环的循环体使用复合语句。

例如:

  while(i < 100)
  {

    cout
<<i<<endl;
    
++i;
  }

    

6、语句作用域

  我们知道对象有其作用范围,超过其作用范围就不能对其进行访问。 例如在一个函数内部定义的变量就不能再函数的外部进行访问。 有些控制结构的语句

可以在其内部定义对象, 这些对象的作用域就是控制结构内部,超过语句的范围,这些对象就不能再被访问。

  例如,前面介绍的内容中我们有如下定义的语句:

  int iArray[5] = {1,2,3,4,5};

  
for(int i = 0; i !=sizeof(iArray); ++i)

    cout
<< iArray <<endl;

  我们看for语句,在for语句的头部,我们定义了变量 i, 我们可以在for 语句的内部访问变量i,循环体属于for语句的一部分,因此我们可以在循环体中访问变量i;

这里for语句的循环体只有一个语句,就是 最后的cout流输出语句。

  我们不能再for语句之外访问在for语句内部定义的变量,如下所示:

1 #include <iostream>
2 #include <string>
3 #include <vector>
4 #include <bitset>
5 #include <stdio.h>
6
7 using std::cin;
8 using std::cout;
9 using std::endl;
10 using std::vector;
11 using std::bitset;
12
13 int main()
14 {
15 int iArray[5] = {1,2,3,4,5};
16
17 for(int i= 0; i != sizeof(iArray); ++i)
18 cout<<iArray<<endl;
19
20 i += 10 ;
2

阅读更多内容

没有评论:

发表评论